首页 > 解决方案 > 导航抽屉:如何在切换(不旋转)时使片段持久(保持活动状态)

问题描述

片段不会在Fragment:setRetainInstance(true);手机方向更改时重新实例化。当然,我希望我的片段在从一个片段切换到另一个片段时保持活力。但是 Android Studio 4 提供了一个向导模板,只有

DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
        R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
        .setDrawerLayout(drawer)
        .build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);

NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);

从数小时的调试和搜索网络中,如果认为它需要从类中固有,FragmentNavigator所以我可以覆盖FragmentNavigator:naviagte创建新片段的位置 final Fragment frag = instantiateFragment(..,然后添加, ft.replace(mContainerId, frag); 所以我可以找到我的旧片段并使用ftNew.showandftOld.hide代替。当然这是一个愚蠢的想法,因为这种navigate方法充满了其他内部的东西。

而且我不知道它FrameNavigator是在哪里创建的。我可以在MainActivity:OnCreatewith中检索它

NavigatorProvider navProvider = navController.getNavigatorProvider ();
Navigator<NavDestination> navigator = navProvider.getNavigator("fragment");

但当时我只能用我的派生版本替换它。而且没有replaceNavigtor方法,只有addNavigator方法,在哪里调用?

无论如何,这一切都将非常复杂,因此容易出错。 为什么没有简单的选项可以让我的片段保持活力:-(

在较旧的向导模板中,有可能

@Override
public void onNavigationDrawerItemSelected(int position) {
    Fragment fragment;
    switch (position) {
    case 1:
        fragment = fragment1;
        break;
    case 2:
        fragment = fragment2;
        break;
    case 3:
        fragment = fragment3;
        break;
    }
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if(mCurrentFragment == null) {
        ft.add(R.id.container, fragment).commit();
        mCurrentFragment = fragment;
    } else if(fragment.isAdded()) {
        ft.hide(mCurrentFragment).show(fragment).commit();
    } else {
        ft.hide(mCurrentFragment).add(R.id.container, fragment).commit();
    }
    mCurrentFragment = fragment;
}

但我不知道如何使用我的 MainActivity 仅派生为的 Android 4.0 模板执行此操作:

public class MainActivity extends AppCompatActivity {

    private AppBarConfiguration mAppBarConfiguration;

欢迎提出想法:'(

标签: android-fragmentsnavigation-drawer

解决方案


您好,抱歉我迟到的回答!我在导航抽屉和导航组件方面遇到了类似的问题。我尝试了一下,找到了一个可行的解决方案,这可能对其他人也有帮助。

关键是MainActivity的FragmentManager中自定义FragmentFactory的使用。请参阅下面的代码:

公共类 StaticFragmentFactory 扩展 FragmentFactory {

    私人 myNavHostFragment1 行程NavHostFragment;
    私人 myNavHostFragment2 设置NavHostFragment;

    @NonNull
    @Override
    公共片段实例化(@NonNull 类加载器类加载器,@NonNull 字符串类名){
        if (MyNavHostFragment1.class.getName().equals(className)) {
            如果(this.myNavHostFragment1 == null){
                this.myNavHostFragment1 = new MyNavHostFragment1();
            }

            返回 this.myNavHostFragment1 ;
        } else if (MyNavHostFragment2.class.getName().equals(className)) {
            如果(this.myNavHostFragment2 == null){
                this.myNavHostFragment2 = new MyNavHostFragment2();
            }

            返回 this.myNavHostFragment2;
        }

        return super.instantiate(classLoader, className);
    }
}

FragmentFactory 使用 AndroidX 的 NavigationComponent 在不同片段之间的导航中幸存下来。为了使片段保持活动状态,FragmentFactory 存储应该存在的片段实例,如果它不为空,则返回此实例。在类中使用单例模式时,您可以找到类似的模式。

您必须通过调用在相应的活动中注册 FragmentFactory

this.getSupportFragmentManager().setFragmentFactory(new StaticFragmentFactory())

另请注意,我在这里使用嵌套片段,因此一个顶级片段(此处称为 NavHostFragmen)包含多个子片段。所有片段都使用其父片段的相同 FragmentFactory。上面的自定义 FragmentFactory 返回超类方法的结果,当要实例化的 Fragment 不知道是否保持活动状态时。


推荐阅读