Android ViewPager2 + Fragment + BottomNavigationView 聯動

Android ViewPager2 + Fragment + BottomNavigationView 聯動

本篇主要介紹一下 ViewPager2 + Fragment + BottomNavigationView , 上篇中把ViewPager2和Fragment 聯動起來了, 本篇主要把 BottomNavigationView集成進去

2022-11-25 17.31.02

概述

BottomNavigationView 是一個底部導航控件, 現在要實現的效果就是 滑動ViewPager2 中的Fragment 並且底部BottomNavigationView 菜單部分跟着聯動 同理反過來 點擊BottomNavigationView 的時候 ViewPager2中的Fragment 也對應滑動, 下面來看看如何實現的吧

實現思路

1.Activity 佈局文件中引入 ViewPager2 控件
2.編寫menu文件 提供給BottomNavigationView 用於展示
3.Activity 佈局文件中引入BottomNavigationView 控件
4.編寫 Fragment 用於填充到ViewPager2中
5.編寫Adapter 實現 FragmentStateAdapter
6.BottomNavigationView添加 setOnItemSelectedListener 聯動ViewPager2
7.ViewPager2 添加 registerOnPageChangeCallback 聯動 BottomNavigationView

代碼實現

下面就來按照上面的思路一步步實現代碼啦!

1.Activity 佈局文件中引入 ViewPager2 控件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ViewPager2BottomActivity">


    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager2bottom"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/bootomnav2"
        />


</androidx.constraintlayout.widget.ConstraintLayout>

2.編寫menu文件 提供給BottomNavigationView 用於展示

圖標icon 自己配置吧

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:title="首頁"
        android:id="@+id/home_item"
        android:icon="@drawable/ic_baseline_home_24"
        />

    <item
        android:title="類型"
        android:id="@+id/type_item"
        android:icon="@drawable/ic_baseline_merge_type_24"
        />

    <item
        android:title="添加"
        android:id="@+id/add_item"
        android:icon="@drawable/ic_baseline_add_24"
        />

    <item
        android:title="設置"
        android:id="@+id/setting_item"
        android:icon="@drawable/ic_baseline_settings_24"
        />
</menu>

3.Activity 佈局文件中引入BottomNavigationView 控件

package com.johnny.slzzing;

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.w3c.dom.Text;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link Bottom2Fragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class Bottom2Fragment extends Fragment {

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    public Bottom2Fragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment Bottom2Fragment.
     */
    // TODO: Rename and change types and number of parameters
    public static Bottom2Fragment newInstance(String param1, String param2) {
        Bottom2Fragment fragment = new Bottom2Fragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_bottom2, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        TextView textView = view.findViewById(R.id.textview2);
        //把動態傳入的參數設置到 textView上
        textView.setText(mParam1);
    }
}

fragment_bottom2.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ViewPager2BottomActivity">


    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager2bottom"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/bootomnav2"
        />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bootomnav2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/viewpager2bottom"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_item_menu"                                        
        app:labelVisibilityMode="labeled" 
        />
<!-- 這個要設置 app:labelVisibilityMode="labeled"  才能顯示圖標文字 因爲我這裏超過了3個-->        
</androidx.constraintlayout.widget.ConstraintLayout>

4.編寫 Fragment 用於填充到ViewPager2中

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".Bottom2Fragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:id="@+id/textview2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:gravity="center"
        android:textSize="25sp"
        android:textStyle="bold"
        android:textColor="@color/black"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

5.編寫Adapter 實現 FragmentStateAdapter

上篇已經說過了 直接繼承 FragmentStateAdapter

class MyViewPager2BottomAdapter extends FragmentStateAdapter {

    List<Fragment> fragmentList;
    public MyViewPager2BottomAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> list) {
        super(fragmentActivity);
        this.fragmentList = list;
    }

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

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

6.BottomNavigationView添加 setOnItemSelectedListener 聯動ViewPager2

bottomNavigationView.setOnItemSelectedListener核心方法

Acitivity 中實現如下代碼:

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager2_bottom);

        viewPager2 = findViewById(R.id.viewpager2bottom);
        bottomNavigationView = findViewById(R.id.bootomnav2);
        MyViewPager2BottomAdapter myViewPager2BottomAdapter =
                new MyViewPager2BottomAdapter(this,initFragmentList());
        viewPager2.setAdapter(myViewPager2BottomAdapter);
        //重點 設置 bottomNavigationView 的item 的點擊事件 設置viewPager2的聯動
        bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                int itemId = item.getItemId();
                switch (itemId){
                    case R.id.home_item:
                        viewPager2.setCurrentItem(0);
                        break;
                    case R.id.type_item:
                        viewPager2.setCurrentItem(1);
                        break;
                    case R.id.add_item:
                        viewPager2.setCurrentItem(2);
                        break;
                    case R.id.setting_item:
                        viewPager2.setCurrentItem(3);
                        break;
                }
                return true;
            }
        });

    }

7.ViewPager2 添加 registerOnPageChangeCallback 聯動 BottomNavigationView

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_view_pager2_bottom);

    viewPager2 = findViewById(R.id.viewpager2bottom);
    bottomNavigationView = findViewById(R.id.bootomnav2);
    MyViewPager2BottomAdapter myViewPager2BottomAdapter =
            new MyViewPager2BottomAdapter(this,initFragmentList());
    viewPager2.setAdapter(myViewPager2BottomAdapter);

    bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            int itemId = item.getItemId();
            switch (itemId){
                case R.id.home_item:
                    viewPager2.setCurrentItem(0);
                    break;
                case R.id.type_item:
                    viewPager2.setCurrentItem(1);
                    break;
                case R.id.add_item:
                    viewPager2.setCurrentItem(2);
                    break;
                case R.id.setting_item:
                    viewPager2.setCurrentItem(3);
                    break;
            }
            return true;
        }
    });
     //重點 實現滑動的時候 聯動 bottomNavigationView的selectedItem
    viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            switch (position){
                case 0:
                    bottomNavigationView.setSelectedItemId(R.id.home_item);
                    break;
                case 1:
                    bottomNavigationView.setSelectedItemId(R.id.type_item);
                    break;
                case 2:
                    bottomNavigationView.setSelectedItemId(R.id.add_item);
                    break;
                case 3:
                    bottomNavigationView.setSelectedItemId(R.id.setting_item);
                    break;
            }
        }
    });

}

image-20221125172800393

總結

本篇主要介紹了 如何把ViewPager2 + Fragment + BottomNavigationView 集成起來並且實現ViewPager2和BottomNavigationView的雙向聯動

ViewPager和ViewPager2 一些區別:

  • ViewPager 的 Adapter 繼承 FragmentStatePagerAdapter 而 ViewPager2 的Adapter 繼承 FragmentStateAdapter
  • ViewPager 滑動監聽是 viewPager.addOnPageChangeListener方法 而ViewPager2 滑動監聽是 registerOnPageChangeCallback 方法

歡迎大家訪問 個人博客 Johnny小屋
歡迎關注個人公衆號

歡迎關注個人公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章