2.4 Синхронизация ViewPager2 и BottomNavigationView

Последний шаг - синхронизация виджетов ViewPager2 и BottomNavigationView. Синхронизация происходит достаточно просто - мы должны обработать событие выбора пункта в BottomNavigationView и событие пролистывания в ViewPager2. При выборе пункта мы меняем активный фрагмент в ViewPager2, а при пролистывании в ViewPager2 мы меняем активный пункт BottomNavigationView.

Перейдем в класс MainActivity.java и получим ссылку на объект BottomNavigationView.

MainActivity.java
public class MainActivity extends AppCompatActivity {

    private ViewPager2 viewPager;
    private BottomNavigationView bottomNavigationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Window w = getWindow();
        w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

        viewPager = findViewById(R.id.container);
        bottomNavigationView = findViewById(R.id.bottom_navigation);

        Adapter adapter = new Adapter(this);
        adapter.addFragment(new WintersunFragment());
        adapter.addFragment(new InsomniumFragment());
        adapter.addFragment(new BelakorFragment());
        viewPager.setAdapter(adapter);
    }
    
    ...
}

Сначала напишем обработчик нажатия на пункт BottomNavigationView. В зависимости от пункта меню, на который нажал пользователь, мы будем выбирать нужный фрагмент в ViewPager2. Для этого необходимо вызвать метод setOnNavigationItemSelectedListener().

MainActivity.java
public class MainActivity extends AppCompatActivity {

    private ViewPager2 viewPager;
    private BottomNavigationView bottomNavigationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        ...
        
        bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
            switch (item.getItemId()) {
                case R.id.wintersun:
                    viewPager.setCurrentItem(0, true);
                    break;
                case R.id.insomnium:
                    viewPager.setCurrentItem(1, true);
                    break;
                case R.id.belakor:
                    viewPager.setCurrentItem(2, true);
                    break;
            }
            return true;
        });
    }

    ...
    
}

Теперь напишем обработчик для пролистывания ViewPager2. При выборе i-го фрагмента мы должны изменить активный пункт в BottomNavigationView. Для этого вызовем метод registerOnPageChangeCallback().

MainActivity.java
public class MainActivity extends AppCompatActivity {

    private ViewPager2 viewPager;
    private BottomNavigationView bottomNavigationView;

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

        viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                switch (position) {
                    case 0:
                        bottomNavigationView.setSelectedItemId(R.id.wintersun);
                        break;
                    case 1:
                        bottomNavigationView.setSelectedItemId(R.id.insomnium);
                        break;
                    case 2:
                        bottomNavigationView.setSelectedItemId(R.id.belakor);
                        break;
                }
            }
        });
    }

    ...
    
}

Проверим работу приложения и убедимся, что работа BottomNavigationView и ViewPager2 синхронизирована.

Листинг класса MainAcitivty.java, макета окна, а также остальных ресурсов представлены ниже.

public class MainActivity extends AppCompatActivity {

    private ViewPager2 viewPager;
    private BottomNavigationView bottomNavigationView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Window w = getWindow();
        w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

        viewPager = findViewById(R.id.container);
        bottomNavigationView = findViewById(R.id.bottom_navigation);

        Adapter adapter = new Adapter(this);
        adapter.addFragment(new WintersunFragment());
        adapter.addFragment(new InsomniumFragment());
        adapter.addFragment(new BelakorFragment());
        viewPager.setAdapter(adapter);

        bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
            switch (item.getItemId()) {
                case R.id.wintersun:
                    viewPager.setCurrentItem(0, true);
                    break;
                case R.id.insomnium:
                    viewPager.setCurrentItem(1, true);
                    break;
                case R.id.belakor:
                    viewPager.setCurrentItem(2, true);
                    break;
            }
            return true;
        });

        viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                switch (position) {
                    case 0:
                        bottomNavigationView.setSelectedItemId(R.id.wintersun);
                        break;
                    case 1:
                        bottomNavigationView.setSelectedItemId(R.id.insomnium);
                        break;
                    case 2:
                        bottomNavigationView.setSelectedItemId(R.id.belakor);
                        break;
                }
            }
        });
    }

    private class Adapter extends FragmentStateAdapter {
        private List<Fragment> list = new ArrayList<>();

        public void addFragment(Fragment fragment) {
            list.add(fragment);
        }

        public Adapter(FragmentActivity fa) {
            super(fa);
        }

        @Override
        public Fragment createFragment(int position) {
            return list.get(position);
        }

        @Override
        public int getItemCount() {
            return list.size();
        }
    }
}

Last updated