使用getFragmentManager和getSupportFragmentManager的Android会导致重叠

时间:2015-01-27 05:10:23

标签: android fragmentmanager

我的活动中有类似的内容:

@Override
    public void onNavigationDrawerItemSelected(int position) {
        Fragment fragment = null;
        switch (position+1) {
            case 1: {
                fragment = new Fragment_Login();
                FragmentManager frgManager = getFragmentManager();
                frgManager.beginTransaction().replace(R.id.container, fragment)
                        .commit();
                break;
            }
            case 2: {
                SwipeRefreshListFragment swipeFragment = new Fragment_List_Of_Assessments();
                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                transaction.replace(R.id.container, swipeFragment)
                        .commit();
                break;
            }
            case 3: {
                fragment = new Fragment_Report();
                FragmentManager frgManager = getFragmentManager();
                frgManager.beginTransaction().replace(R.id.container, fragment)
                        .commit();
                break;
            }
            case 4: {
                fragment = new Fragment_Settings();
                FragmentManager frgManager = getFragmentManager();
                frgManager.beginTransaction().replace(R.id.container, fragment)
                        .commit();
                break;
            }
            default:
                break;
        }
    }

程序自动加载case1,但是当选择case2时,getSupportFragmentManager会在case1之上加载Fragment。我想使用supportFragmentManager和FragmentManager都有一些问题。他们似乎有自己的堆栈。问题是我不能只使用其中任何一个,因为SwipeToRefresh Android示例使用ListView,它需要support.v4.Fragment,它需要旧的FragmentManager。那么如何将两个FragmentManagers集成在一起呢?

3 个答案:

答案 0 :(得分:3)

使用PreferenceFragment时,我已经完成了类似的操作(支持库版本不支持)。为了实现这一点,我在Activity中保留了一对布尔值(isLastFragmentSupportTypelastFragmentShowed)以及一个字符串(lastFragmentTag)。

在开始时,您的活动将使它们都为假。当你添加一个新的片段时,你可以使用这两个布尔值来知道你是否需要清除另一个FragmentManager。我将使用您的代码作为示例:

@Override
public void onNavigationDrawerItemSelected(int position) {
    Fragment fragment = null;
    switch (position+1) {
        case 1: {
            if(isLastFragmentSupportType && lastFragmentShowed)
            {//As your last fragment  was a support type you need to clear your supportFragmentManager
              android.support.v4.app.Fragment fr_v4 = getSupportFragmentManager().findFragmentByTag(lastFragmentTag);
               getSupportFragmentManager().beginTransaction().remove(fr_v4).commit();
            }
            fragment = new Fragment_Login();
            FragmentManager frgManager = getFragmentManager();
            frgManager.beginTransaction().replace(R.id.container, fragment,TAG1)
                    .commit();
          lastFragmentTag = TAG1;
          lastFragmentShowed = true;
          isLastFragmentSupportType = false; 
            break;
        }
       //And so on with the others

您需要检查要使用的片段的类型(支持与否),并检查这些变量以查看最后一个片段是否为不同类型。如果是这种情况,请清除其他碎片管理员以清除"清除"屏幕所以它们不会重叠。

还可以使用TAGS识别和检索当前片段,这样您就不需要在代码上包含Fragment个变量。

最后使用onSavedInstanceState以便在需要时保留这些值。

希望有所帮助:)

答案 1 :(得分:1)

这个答案的灵感来自于zozelfelfo的回答。 使用这两种方法替换片段而不是getFragmentManager.beginTransaction.replace...

private void replaceFragment(Fragment fragment, String fragmentTag) {
    if(lastFragmentShowed && isLastFragmentSupportType) {
        android.support.v4.app.Fragment fr_v4 = getSupportFragmentManager().findFragmentByTag(lastFragmentTag);
        getSupportFragmentManager().beginTransaction().remove(fr_v4).commit();
    }
    getFragmentManager().beginTransaction()
            .replace(R.id.fragment_container, fragment, fragmentTag)
            .commit();
    lastFragmentTag = fragmentTag;
    lastFragmentShowed = true;
    isLastFragmentSupportType = false;
}

private void replaceFragment(android.support.v4.app.Fragment fragment, String fragmentTag) {
    if(lastFragmentShowed && !isLastFragmentSupportType) {
        Fragment fr = getFragmentManager().findFragmentByTag(lastFragmentTag);
        getFragmentManager().beginTransaction().remove(fr).commit();
    }
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.fragment_container, fragment, fragmentTag)
            .commit();
    lastFragmentTag = fragmentTag;
    lastFragmentShowed = true;
    isLastFragmentSupportType = true;
}

答案 2 :(得分:0)

我使用BottomNavigationView作为标签栏并将片段切换为标签。除一个片段外的所有片段都是Support Fragments(最后一个片段是PreferenceFragment)。我正在使用" hide-add-show"而不是"删除 - 替换"。因此,可以保留其他选项卡中片段的状态。

要切换的原始功能:

private Fragment lastFragment = null;
private void switchFragment(Fragment fragment) {
    if (lastFragment != fragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (null != lastFragment) {
            transaction.hide(lastFragment);
        }
        lastFragment = fragment;
        if (!fragment.isAdded()) {
            transaction.add(R.id.fragment_container, fragment);
        }
        transaction.show(fragment).commitAllowingStateLoss();
    }
}

我不使用tag或boolean,只想保留对最后一个片段对象的引用。因此,在切换时,只需使用任何片段的实例调用switchFragment()

private Object lastFragment = null;
private void switchFragment(Object fragment) {
    if (lastFragment != fragment) {
        if (null != lastFragment) {
            if (lastFragment instanceof android.support.v4.app.Fragment) {
                hideFragment((android.support.v4.app.Fragment) lastFragment);
            } else if (lastFragment instanceof android.app.Fragment) {
                hideFragment((android.app.Fragment) lastFragment);
            }
        }
        lastFragment = fragment;
        if (fragment instanceof android.support.v4.app.Fragment) {
            showFragment((android.support.v4.app.Fragment) fragment);
        } else if (fragment instanceof android.app.Fragment) {
            showFragment((android.app.Fragment) fragment);
        }
    }
}

因此,此函数仍然执行相同的操作,但通过检查目标类在Support FragmentNative Fragment之间切换。助手功能:

// Support Version:
private void hideFragment(android.support.v4.app.Fragment fragment) {
    getSupportFragmentManager().beginTransaction().hide(fragment).commit();
}

private void showFragment(android.support.v4.app.Fragment fragment) {
    android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (!fragment.isAdded()) {
        transaction.add(R.id.fragment_container, fragment);
    }
    transaction.show(fragment).commitAllowingStateLoss();
}

// Native Version:
private void hideFragment(android.app.Fragment fragment) {
    getFragmentManager().beginTransaction().hide(fragment).commit();
}

private void showFragment(android.app.Fragment fragment) {
    android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction();
    if (!fragment.isAdded()) {
        transaction.add(R.id.fragment_container, fragment);
    }
    transaction.show(fragment).commitAllowingStateLoss();
}

为避免混淆,我删除了import所以类需要全名。