Android 谷歌照片应用程序底部导航栏行为

Android 谷歌照片应用程序底部导航栏行为,android,android-fragments,navigation,bottomnavigationview,android-jetpack-navigation,Android,Android Fragments,Navigation,Bottomnavigationview,Android Jetpack Navigation,很长一段时间以来,我一直在研究如何保存片段之间的状态,所以当我返回时,就好像您从未离开过一样。谷歌照片就是一个重要的例子。当你滚动浏览你的照片,然后转到另一个片段并返回时,你会保持原样。我的问题是如何实现这一点,因为我的应用程序加载了不同的片段,当它们返回到这些片段时,它们会被重新创建,而不是像谷歌照片那样加载以前的状态。我所尝试的: 代码的一部分,其中定义了导航主机\u片段,因为它是导航视图 appBarConfiguration = new AppBarConfiguration.Bui

很长一段时间以来,我一直在研究如何保存片段之间的状态,所以当我返回时,就好像您从未离开过一样。谷歌照片就是一个重要的例子。当你滚动浏览你的照片,然后转到另一个片段并返回时,你会保持原样。我的问题是如何实现这一点,因为我的应用程序加载了不同的片段,当它们返回到这些片段时,它们会被重新创建,而不是像谷歌照片那样加载以前的状态。我所尝试的:


代码的一部分,其中定义了导航主机\u片段,因为它是导航视图

 appBarConfiguration = new AppBarConfiguration.Builder(
        R.id.navigation_home, R.id.navigation_profile, R.id.navigation_locate, R.id.navigation_contact_messages, R.id.navigation_settings)
        .build();

    navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    //NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    NavigationUI.setupWithNavController(navView, navController);

    navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    //NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    NavigationUI.setupWithNavController(navView, navController);

    navView.setOnNavigationItemReselectedListener(menuItem -> {

    });

    navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
        if (destination.getLabel() != null) {
            if (levelsFragment[0].equals(destination.getLabel().toString())) {
                //reemplazar por accion
            } else if (levelsFragment[1].equals(destination.getLabel().toString())) {
                //reemplazar por accion
            } else if (levelsFragment[2].equals(destination.getLabel().toString())) {
                //reemplazar por accion
            } else if (levelsFragment[3].equals(destination.getLabel().toString())) {
                //reemplazar por accion
            } else if (levelsFragment[4].equals(destination.getLabel().toString())) {
                //reemplazar por accion
            }
        }
    });

包含底部导航的主活动的Xml:

<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_view"
    style="@style/bottomNav"
    android:layout_width="0dp"
    app:itemTextColor="@color/quantum_grey"
    android:animateLayoutChanges="true"
    app:labelVisibilityMode="auto"
    app:itemIconTint="@color/colorAccent"
    android:layout_height="wrap_content"
    android:layout_marginStart="0dp"
    android:layout_marginEnd="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:menu="@menu/bottom_nav_menu" />

<fragment
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="?actionBarSize"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toTopOf="@id/nav_view"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/mobile_navigation" />


</androidx.constraintlayout.widget.ConstraintLayout>


底部导航在Android和iOS上的行为不同。当你 选择底部导航项目(当前未选择的项目), 每个平台显示不同的结果:

  • 在Android上:应用程序导航到目的地的顶级屏幕。任何先前的用户交互和临时屏幕状态都将重置,
    例如滚动位置、选项卡选择和在线搜索
  • 在iOS上:目的地反映用户先前的交互。如果用户以前访问过应用程序的该部分,他们将返回到 查看的最后一个屏幕(如果需要,保留其先前状态) 可能的)。否则,应用程序将导航到顶级屏幕
需要改进时,可以覆盖默认平台导航 用户体验。例如,Android应用程序需要 在区段之间频繁切换可以保持每个区段的状态。 或者,iOS应用程序可以将用户返回到顶级屏幕(或重置) 它们的滚动位置)是否更适合用例


这是一封来自谷歌问题追踪器的电子邮件。在谷歌照片中,我清楚地表达了我的担忧,这是正确的必须有解决问题的方法

对于我们的最终用户来说,这个bug的两个最大问题和烦恼 使用新的导航库和底部导航栏:

  • 使用底部栏更改选项卡会重置上一个选项卡/片段的状态和后退,因此我们的用户完全失去了他们的导航历史(这在Google Photos应用程序中得到了正确的实现)
  • 从一个选项卡的根上按back可显示初始选项卡/片段,而不是离开应用程序“


我通过搜索互联网发现了这个问题,但它在kotlin,有些事情我不能很好地理解,我不知道它是否正是我所需要的:

我不知道是否有更干净的方法来做到这一点,但也许你可以尝试保存重要的内容来重新创建视图(例如滚动位置和内联搜索)然后在重新打开时自动滚动到旧位置。
还可以保存旧实例(如果存在滚动数据,则使用滚动数据)然后,当您切换回时,您会将旧版本复制回,而不是生成新版本。请小心复制旧屏幕对象,而不是设置引用,因为在生成下一个屏幕对象时,它显然会被删除。

对该问题的回答更有价值tnah 50分,但我没有足够的分数尽管有很多答案可用于保存片段的状态或不销毁片段,以便再次选中时不会重新加载,但我相信这对您最有帮助。但是,请记住,如果您的片段将保持打开状态,您需要管理真正需要的内存资源,因为高内存消耗可能会导致系统内存扼杀您的应用程序谢谢你的回答,但是如果你在问题中看到,material desgin说行为可以被覆盖,我想知道怎么做