Сохранение состояния Fragment с Android BottomNavigation

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

У меня в приложении есть BottomNavigation c тремя пунктами меню. Как на картинке: вот такое меню

Первоначально я это сделал как в стандартном примере 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:
                                // тут работа для среднего пункта меню
                                break;
                            case R.id.navigation_notifications:
                                navController.navigate(R.id.navigation_notifications, savedInstanceState);
                                break;
                        }
                        return true;
                    }
                });
    }
}

Это даже работает, за исключением того, что фрагменты перестали сохранять свое состояние. То есть, к примеру, в первом фрагменте у меня есть RecyclerView, если его прокрутить вниз, переключиться на другой фрагмент, а потом вернуться обратно, то RecyclerView оказывается в дефолтном состоянии (не прокрученным), то есть состояние не сохранилось.

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

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


Ответы (1 шт):

Автор решения: Bagomot

Я смог решить проблему стандартными средствами с помощью Navigation. я просто нашел средний пункт меню и добавил ему OnClickListener.

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

Таким образом, если добавить этот код в конце метода onCreate (в первом варианте моего кода), то и переключение флагментов работает корректно (с сохранением состояния) и средняя кнопка меню реагирует на нажатие.

Всем спасибо!

→ Ссылка