Фрагмент не заменяется, а помещается поверх предыдущего

Активность:

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.

Я надеюсь, что кто-то получит помощь.