使用 Android BottomNavigation 保存片段状态

Saving Fragment state with Android BottomNavigation

我是Android开发的新手,所以我不明白很多,也许是基本的东西,也许甚至陈述的主题也没有完全反映我的问题,我提前道歉,我无法制定更多恰恰。请帮我解答一些问题。

我的应用程序中有一个包含三个菜单项的 BottomNavigation。喜欢图片:

bottom nav

最初,我按照标准 Android Studio 示例进行操作:

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    private NavController navController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        BottomNavigationView navView = findViewById(R.id.nav_view);
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
                .build();

        navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);

        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(binding.navView, navController);
    }
}

在这段代码中,菜单项切换片段,保存每个片段的状态(我不知道具体如何,它似乎在导航控制器内部的某个地方)。

但现在我需要中间按钮来执行不同的功能,即不参与切换片段。

唯一合适的方法是使用 setOnItemSelectedListener。

那么我的代码将如下所示:

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    private NavController navController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        BottomNavigationView navView = findViewById(R.id.nav_view);
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_update, R.id.navigation_notifications)
                .build();

        navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);

        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(binding.navView, navController);

        navView.setOnItemSelectedListener(
                new NavigationBarView.OnItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        switch (item.getItemId()) {

                            case R.id.navigation_home:
                                navController.navigate(R.id.navigation_home);
                                break;
                            case R.id.navigation_update:
                                // work for middle menu item
                                break;
                            case R.id.navigation_notifications:
                                navController.navigate(R.id.navigation_notifications, savedInstanceState);
                                break;
                        }
                        return true;
                    }
                });
    }
}

它甚至可以工作,只是片段不再保存它们的状态。也就是说,例如,在第一个片段中我有一个 RecyclerView,如果我向下滚动它,切换到另一个片段,然后 return 返回,那么 RecyclerView 处于默认状态(未滚动),即状态尚未保存。

事实证明,在第一个版本的代码中,我不能对中间的菜单项进行单独的操作,而在第二个版本中,片段的状态没有被保存。

提示正确处理该问题的方法。这样可以给中间的菜单项分配一个单独的作业,并且可以保存片段的状态。

您可以使用 navController.addOnDestinationChangedListener 而不是使用 navView.setOnItemClickListener,并且在重写的 onDestinationChanged 方法中,您可以检查

if(destination.id ==  R.id.navigation_update) {
    //your custom action here
}

我能够使用导航使用标准工具解决问题。 我刚找到一个菜单项并向其添加了一个 OnClickListener。

BottomNavigationItemView updateBtn = findViewById(R.id.navigation_update);
updateBtn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
       // todo
   }
});  

因此,切换片段和单击中间菜单项都可以正常工作。