Фрагмент не заменяется, а помещается поверх предыдущего
Активность:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment1 fragment = new Fragment1();
Fragment2 fragment2 = new Fragment2();
transaction.replace(R.id.Fragment1, fragment);
transaction.addToBackStack(null);
transaction.commit();
FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
transaction2.replace(R.id.Fragment1, fragment2);
transaction2.addToBackStack(null);
transaction2.commit();
Код в представлении:
<fragment
android:id="@+id/Fragment1"
android:name="com.landa.fragment.Fragment1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_below="@+id/include1" />
Проблема в том, что контент на самом деле не заменяется - он накладывается сверху (поэтому он перекрывается).
Когда я нажимаю назад, первый фрагмент отображается правильно (без второго), но изначально оба они видны (я хочу, чтобы только последний был видимым).
Что мне здесь не хватает?
Ответы
Ответ 1
Здесь вы делаете две вещи:
-
Вы не можете заменить фрагмент, который статически помещен в файл макета xml
. Вы должны создать контейнер (например, FrameLayout
) в макете, а затем добавить фрагмент программно с помощью FragmentTransaction
.
-
FragmentTransaction.replace
ожидает идентификатор контейнера, который содержит фрагмент, а не идентификатор фрагмента в качестве первого параметра. Таким образом, вы должны передать первый аргумент как идентификатор контейнера, в который вы добавили первый фрагмент.
Дополнительную информацию можно найти в этой ссылке.
Ответ 2
У меня была похожая проблема, но моя проблема заключалась в том, что я использовал два разных менеджера фрагментов: один из getSupportFragmentManager()
и один из getFragmentManager()
. Если бы я добавил один фрагмент с помощью SupportFragmentManager
а затем попытался заменить этот фрагмент на FragmentManager
, этот фрагмент просто был бы добавлен сверху. Мне нужно было изменить код так, чтобы использовался тот же FragmentManager
, и это решило проблему.
Ответ 3
Сайт разработчика Android предлагает использовать FrameLayout
для динамического загрузки фрагментов во время выполнения. У вас есть жесткий код фрагмента в вашем XML файле. Поэтому он не может быть удален во время выполнения, как указано в этой ссылке:
http://developer.android.com/training/basics/fragments/creating.html
Эта ссылка показывает, как добавить фрагменты через вашу программу:
http://developer.android.com/training/basics/fragments/fragment-ui.html
Ответ 4
У меня была такая же проблема и я видел все ответы, но ни один из них не содержал мою ошибку! Прежде чем пытаться заменить текущий фрагмент, я показывал фрагмент по умолчанию в xml операции контейнера следующим образом:
<FrameLayout
android:id="@+id/fragment_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="....ShopFragment"
android:id="@+id/fragment"
tools:layout="@layout/fragment_shop" />
</FrameLayout>
после этого, хотя я передавал FrameLayout
во fragmentTransaction.replace()
но у меня была точная проблема. он показывал второй фрагмент поверх предыдущего.
Проблема была устранена путем удаления фрагмента из xml и его программного отображения в onCreate()
контейнера для предварительного просмотра по умолчанию при запуске программы, например:
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_frame_layout,new ShopFragment());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
и контейнер деятельности xml:
<FrameLayout
android:id="@+id/fragment_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
Ответ 5
Вы можете очистить backStack перед заменой фрагментов:
FragmentManager fm = getActivity().getSupportFragmentManager();
for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
fm.popBackStack();
}
// replace your fragments
Ответ 6
Я согласен с ответом Сапана Дивакара. Но я нашел обходное решение о том, как это сделать.
Во-первых, в вашей деятельности (например, activity_main
), где у вас есть все макеты, добавьте FrameLayout
. Высота и ширина должны быть match parent
. Также дайте ему id
.
Теперь, в вашем фрагменте, который заменит текущий макет, вызовите onPause()
и onResume()
. Инициализируйте все внутренние контейнеры в View
. И установите для них visibility
значение GONE
в onResume()
и VISIBLE
в onPause()
.
ПРИМЕЧАНИЕ: не FrameLayout
, который вы заменяете этим фрагментом.
Предположим, что у вас есть ViewPager
, TabLayout
, ImageView
и пользовательский <fragment>
в activity_main.xml
. Добавить, a FrameLayout
, как указано выше.
В abcFragment.java
, в функции onClick()
добавьте addToBackstack(null)
в transaction
.
Пример кода:
в xyzFragment, который заменит abcFragment (и все, что показано в activity_main.xml), сделайте это
@Override
public void onResume() {
super.onResume();
// On resume, make everything in activity_main invisible except this fragment.
slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
viewPager = getActivity().findViewById(R.id.pager);
miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);
slidingTabs.setVisibility(View.GONE);
viewPager.setVisibility(View.GONE);
miniPlayerFragment.setVisibility(View.GONE);
}
@Override
public void onPause() {
super.onPause();
// Make everything visible again
slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
viewPager = getActivity().findViewById(R.id.pager);
miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);
slidingTabs.setVisibility(View.VISIBLE);
viewPager.setVisibility(View.VISIBLE);
miniPlayerFragment.setVisibility(View.VISIBLE);
}
Счастливое кодирование!
Ответ 7
Спасибо Сапан Дивакар и другие. Этот ответ мне помог. Я просто создал RelativeLayout без фрагмента внутри него, использовал RelativeLayout в качестве родительского или группового представления, указав это групповое представление в транзакции для замены, и она сработала.
код:
getSupportFragmentManager(). BeginTransaction() .replace(R.id.content_group_view, itemDetailFragment).commit();
Разметка:
<RelativeLayout
android:id="@+id/content_group_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
</RelativeLayout>
Ответ 8
Используйте контейнер вместо использования фрагмента
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!" />
Теперь в MainActivity
if(condition)
getFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit();
else
getFragmentManager().beginTransaction().replace(R.id.container, new SecondFragment()).commit();
Обратите внимание, что ваш класс фрагмента должен импортировать 'android.app.Fragment'
Убедитесь, что вы используете "support.v4" или "оригинальные" реализации и не смешиваете их. Я получал эту проблему, потому что я их смешивал.
Ответ 9
Вы можете использовать метод setTransition из FragmentTransaction для устранения проблемы перекрытия.
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
Ответ 10
В Oncreate()
BaseFragmentloginpage fragment = new BaseFragmentloginpage();
android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame, fragment);
fragmentTransaction.isAddToBackStackAllowed();
fragmentTransaction.commit();
теперь это будет всегда ваш фрагмент по умолчанию... если вы добавите фрагмент в макет xml, он всегда будет перекрываться, поэтому установите начальный контент с фрагментом во время выполнения
Ответ 11
У меня была такая же проблема после решения этой проблемы.
-
Возьмите кадр, где u заменяет фрагмент ur
<FrameLayout
android:id="@+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent" />
-
и код для замены
public void selectFrag(View view) {
Fragment fr;
if(view == findViewById(R.id.button2))
{
fr = new FragmentTwo();
}else {
fr = new FragmentOne();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.fragment_place, fr);
fragmentTransaction.commit();
если вы хотите весь пример, я пришлю вам просто прокомментировать......
Ответ 12
У меня также была та же проблема, но это было потому, что я не изменил цвет фона фрагмента, который я пытался добавить к моей структуре кадра.
Попробуйте сделать это, layout_height
и layout_width
в match_parent
Ответ 13
Однажды у меня возникла эта проблема, и я обнаружил, что это потому, что случайно удалил атрибут android:background
, которого нет в вашем коде xml. Я считаю, что это работает так же, как когда вы рисуете стену, android:background
- это цвет, которым будет стена, а другие виды размещаются поверх этого базового цвета. Если вы не покрасите стену до того, как разместите свои виды, они окажутся поверх того, что уже было в этой стене, в вашем случае - вашего другого фрагмента. Не знаю, поможет ли это тебе, удачи.
Ответ 14
Я пробовал прежде всего дело и пытаюсь решить проблему, но все еще не получил решение. Я не знаю, почему это не работает для меня. Я согласен с приведенными выше ответами, потому что многие с этим согласны.
Я просто расширяю ответ, и ниже приводится способ, который работает для меня.
Я добавил это свойство android:clickable="true"
в верхний родительский макет файла fragment.xml
.
Я надеюсь, что кто-то получит помощь.