Android: проблема перекрытия фрагментов

я сталкиваюсь с проблемой перекрытия фрагментов при переключении между вкладками и прикреплении фрагментов к представлению вкладки ниже приведен мой код, Пожалуйста, помогите

public class FragmentManage extends Fragment implements ActionBar.TabListener {

    private Fragment mFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
            Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_manage, container, false);

        OnClickListener clickListener = new OnClickListener() { 
            public void onClick(View v) {
                FragmentTransaction ft = getFragmentManager().beginTransaction();
                switch(v.getId()) {
                    case R.id.imageBtnCategory:
                        if (mFragment == null){
                            mFragment = new FragmentCategory();
                        }
                        ft.replace(android.R.id.content, mFragment);
                        break;
                    case R.id.imageBtnManageKey:
                        if (mFragment == null){
                            mFragment = new FragmentKeys();
                        }
                        ft.replace(android.R.id.content, mFragment);
                        break;
                    case R.id.imageBtnChangePswd:
                        if (mFragment == null){
                            mFragment = new FragmentChangePwd();
                        }
                        ft.replace(android.R.id.content, mFragment);
                        break;
                }
                ft.commit();
             }
        };

        ImageButton imageBtnCategory = (ImageButton) v.findViewById(R.id.imageBtnCategory);
        ImageButton imageBtnManageKey = (ImageButton) v.findViewById(R.id.imageBtnManageKey);
        ImageButton imageBtnChangePswd = (ImageButton) v.findViewById(R.id.imageBtnChangePswd);

        imageBtnCategory.setOnClickListener(clickListener);
        imageBtnManageKey.setOnClickListener(clickListener);
        imageBtnChangePswd.setOnClickListener(clickListener);

        return v;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        mFragment = new FragmentManage();
        ft.add(android.R.id.content, mFragment);
        ft.attach(mFragment);
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(mFragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}

15 ответов


просто установите цвет фона для вашего <fragment /> в XML-файле.

решает эту проблему.


Я могу очень поздно ответить на этот вопрос.

Примечание:

этот ответ может не быть связан с вышеуказанным вопросом, но надеюсь, что это поможет для некоторых.

Иногда проблема перекрытия фрагментов возникает, когда мы пытаемся использовать другой тип фрагментов (i.e использование фрагментов поддержки в нескольких фрагментах и нормальных фрагментах в другом фрагменте)

недавно я столкнулся с той же проблемой в навигации ящик. По ошибке я использовал "импорт android.поддержка.В4.приложение.Фрагмент; "в одном фрагменте, и используется"импорт android.приложение.Фрагмент; " в нескольких других фрагментах.

надеюсь, это поможет кому-то..


менеджер фрагментов поддерживает стек всех предыдущих фрагментов, которые заменяются иногда фрагменты заднего стека перекрываются с фрагментом, который мы заменили, для меня

  fragmentManager.popBackStack(); 

работает, мы можем сделать это в цикле тоже, чтобы поп все фрагменты в стеке надеюсь, что это поможет, Спасибо. Счастливое Кодирование:)


Ну Настройка цвета фона фрагмента не является решением, потому что фрагмент все еще будет в стеке действий, который может потреблять память.

решение будет удалить все представления из вашего framelayout перед добавлением любого нового фрагмента.

private void changeFragment(Fragment fr){
    FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
    fl.removeAllViews();
    FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
    transaction1.add(R.id.mainframe, fr);
    transaction1.commit();
}

вот как я это исправил ..

установка фона удалит эффект перекрытия с экрана, только если макет соответствует заполнению экрана

новые фрагменты, замененные при нажатии кнопки, не заменялись на tab_selected или tab change action

следующий код исправил это для меня

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    // This is required since button click replaces fragment whose link is lost hence overlapping isuee was occuring
    ft.replace(android.R.id.content, mFragment); 
    // On Tab Change remove old fragment views
    ft.remove(mFragment);
}

еще одна проблема может быть связана с использованием android.R.id.content как контейнер. Я только что создал FrameLayout и используйте id оттуда.


Я также столкнулся с проблемой перекрытия фрагментов.Вот как я решил это -

1) Нам нужно добавить первый фрагмент с addToBackStack, чтобы он остался в стеке -

FirstFragment firstFragment = new FirstFragment();
getFragmentManager().beginTransaction().add(R.id.fragment_container, firstFragment).addToBackStack("first frag").commit();

2) при добавлении второго фрагмента замените первый фрагмент, а не добавляя его.Поскольку первый фрагмент уже был добавлен в стек, поэтому он будет присутствовать при нажатии назад из второго фрагмента -

SecondFragment secondFragment= new SecondFragment();
getFragmentManager().beginTransaction().replace(R.id.fragment_container, secondFragment).addToBackStack("second frag").commit();

3) здесь как заднюю прессу можно отрегулировать, ниже код должен присутствовать в Родительском действии -

 public void onBackPressed(){
    if(getFragmentManager().getBackStackEntryCount() <= 1){
       super.onBackPressed();
    } else {
       getFragmentManager().popBackStack();
    }
 }

private void changeFragment(Fragment fr){
FrameLayout fl = (FrameLayout) findViewById(R.id.mainframe);
fl.removeAllViews();
FragmentTransaction transaction1 =getSupportFragmentManager().beginTransaction();
transaction1.add(R.id.mainframe, fr);
transaction1.commit();}

когда у вас есть фрагмент перекрытия, возможно, ваш фон вашего фрагмента прозрачен, вам нужно поместить android:background="@color/white"' внутри ваших свойств фрагмента

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"

и белый вам нужно положить внутри цветов.XML #FFFFFF в папке rest.


Я иногда та же проблема, но моя проблема не связана с разными менеджерами фрагмент (getSupportFragmentManager(), getFragmentManager()). Думаю, есть еще одна проблема. В моем случае, когда я открываю навигационный ящик, я всегда удаляю старые фрагменты в каждой опции меню, например:

Fragment calendarFragment = context.getSupportFragmentManager().findFragmentByTag(FragmentTag.CALENDAR.name());
if (calendarFragment != null)
{
    context.getSupportFragmentManager().beginTransaction().remove(calendarFragment).commit();
}

невозможно попасть в подменю без навигационного ящика, поэтому фрагменты в основном всегда удаляются. В некоторых случаях после удаления и добавления фрагмента снова внутри действия он внезапно перекрывается с другим (предыдущим) фрагментом?! Но почему менеджер фрагментов внезапно находит предыдущие фрагменты? Это может означать, что диспетчер фрагментов глючит и не удаляет старые фрагменты, или что что-то другое сломано.
Моя мысль заключается в том, что это как-то вина Android Studio или любого другого инструмента разработки adb, который используется им. Почему я думаю, что это так, потому что Android Studio иногда, похоже, теряет экземпляр запущенного приложения. Вероятно, эта проблема как-то связана с той же проблемой: Android Studio не развертывает изменения в app. Я еще не понял, когда это произойдет. Я знаю, что это не может быть проблемой программирования, потому что она не воспроизводима после перезапуска приложения Android Studio. Я предполагаю, что каким-то образом висят какие-то фоновые процессы, которые вызывают несколько экземпляров действий, фрагментов, менеджеров фрагментов и так далее. Кроме того, это не просто ошибка. Я видел много странных поведение в прошлом, похожее на это. (Например, поведение внезапно исчезло, когда приложение не было запущено IDE).


все это имеет отношение к технике за заменить и addToBackStack методы.

Метод replace фактически сделает две вещи. Скройте существующий фрагмент (скажем, A) и добавьте новый (скажем, B) в контейнер.

Добавление этой транзакции в задний стек будет делать обратное. Удалите B и добавьте A.

Итак, решение вашей проблемы -
1. использовать addToBackStack метод.
2. убедитесь, что обратная замена фрагментов в правильном порядке

Второе предложение действительно важно, потому что довольно часто в какой-то момент текущий фрагмент не удаляется, а добавляется другой, что вызывает одновременное отображение двух фрагментов.


создание белого цвета фона решило это и для меня. Я думаю, это ошибка или и проблема реализации в fragmentment менеджер для Android. Я правильно реализовал свои replace и popBackStack ().


когда у меня была такая проблема, оказалось, что я добавляю один фрагмент с childFragmentManager, а другой с fragmentManager родителя, поэтому проверьте, что вы используете тот же тип менеджера фрагментов.


Я не думаю, что реализация белого фона является безопасным решением, хотя это может быть удобно. В основном проблема возникает из-за того, что диспетчер фрагментов путается о том, какой фрагмент всплывать.

backstack выглядит так и думает ваш на фраг 4 1->2, 2->3, 3->4 но ваш На самом деле на frag 6 по какой-то причине так popbackstack идет

удалить(4) Добавить(3)

чтобы лучше контролировать свои навигация я отслеживаю мои текущие / предыдущие фрагменты и заменяю их следующим образом. Это позволяет моему приложению управлять навигацией по фрагментам.

if ( !(currentFragment instanceof Settings)) {
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, settings);
        fragmentTransaction.addToBackStack(null);
        previousFrag = currentFragment;
        currentFragment = settings;
        fragmentTransaction.commit();
    }

во-вторых, я считаю, что fragmentmanager.метод replace () является лучшей альтернативой. Не уверен, что это доступно для OP в то время.

В-третьих, для обработки андроидов родной назад нажмите вы должны иметь возможность прокручивать назад бесконечно. Многие люди рекомендуют не добавлять первый фрагмент в задний стек, не используя это линия.

fragmentTransaction.addToBackStack (null);

однако, если это так, вы должны проверить, если его первый раз приложение загрузилось. Если его нет, и вы исключаете эту строку, то ваше приложение будет иметь эти проблемы при навигации по этому фрагменту. Я предпочитаю оставить его на месте и вместо этого сделать следующее.

не уверен, что это считается хорошим решением, но оно работает очень хорошо.

1-получить подсчет backstack 2 - удалить все существующие Фраги 3 - Следите за вами фрагмент объектов 4-если его последний фрагмент в стеке пользователь хочет выйти, и так как мы добавили основное действие в задний стек, нам нужно удвоить pop

@Override
public void onBackPressed() {

int num = getFragmentManager().getBackStackEntryCount();


        fl.removeAllViews();
        super.onBackPressed();

        if  (currentFragment != previousFrag) {
            currentFragment = previousFrag;
        }else{
            currentFragment = null;
        }

        if (num == 1){
           super.onBackPressed();
        }

Я нашел простое и чистое решение. Для меня проблема заключалась в выполнении транзакции фрагмента в каждом вызове onCreate() моей деятельности. Теперь я выполняю транзакцию только если savedInstanceState == null

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (savedInstanceState == null) {
        // replace fragment 
        }
    }