前语

经过几回的踩雷和摸索,完成了以上的操作,本教程写的详细全面,包教包会,对新手友好,看了不会的联络我,我倒立洗头给你看。

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

1.需求了解的一些常识

所需控件:

fragment

作为Android中最常用的控件,它有自己的声明周期,能够粗略地等比为能够分屏的activity,可是和activity有差异,fragment有自己的生命周期和接纳、处理用户的事情。Fragment有必要是依存与Activity而存在的。所以他们能够有自己的xml文件(布局文件)和class文件(处理逻辑的java类文件)。

Viewpager

ViewPager是能够完成多个界面的左右滑动的控件。ViewPager最典型的运用场景首要包 括引导页导航,轮转广告和页面菜单。其间有两个ViewPager适配器需求运用:

  • FragmentStatePagerAdapter:

    它是 PagerAdapter 的子类,用于处理多个碎片,并支撑动态加载和毁掉碎片来节约内存。适用于需求处理大量页面、支撑动态刷新以及动态增加或删去页面的场景。例如图片浏览器、新闻阅读器等。

  • FragmentPagerAdapter:

    它也 是 PagerAdapter 的子类,与 FragmentStatePagerAdapter 类似,但有一些不同之处。与 FragmentStatePagerAdapter 相比,FragmentPagerAdapter 更适用于静态、数量有限的页面调集,并提供更好的滑动性能和用户体验,由于它不会毁掉已经创立的碎片实例。

咱们接下来要运用的是FragmentPagerAdapter。

java语法结构

List<>

List<> 是 Java 中的泛型类,一种动态数组,用于表明一个列表,能够存储任意类型的元素。在运用 List<> 时,需求在尖括号中指定详细的类型参数。能够完成增,删,替换等操作。举个例子

List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("World");
​
List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
​
for (String str : stringList) {
  System.out.println(str);
}
​
for (int num : integerList) {
  System.out.println(num);
}
​

首要,创立了一个 List<String> 类型的列表 stringList,并向其间增加两个字符串元素 “Hello” 和 “World”。

接下来,创立了一个 List<Integer> 类型的列表 integerList,并向其间增加两个整数元素 1 和 2。

然后,经过运用增强型 for 循环,分别对 stringListintegerList 进行迭代遍历,将列表中的元素逐一取出,并分别打印输出。

在第一个循环中,每次迭代将当前的字符串元素赋值给变量 str,然后将其输出。因而,在循环的第一次迭代中,会输出 “Hello”,在第2次迭代中,会输出 “World”。

在第二个循环中,每次迭代将当前的整数元素赋值给变量 num,然后将其输出。因而,在循环的第一次迭代中,会输出 1,第2次迭代中,会输出 2。

所以最终的输出结果是:

Hello
World
1
2

2.准备工作

1.导入所需包

在build.gradle文件中引入implementation 'com.google.android.material:material:1.9.0'

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

当导入进去后,或许会有版别不一样的状况,假如报黄,点击alt+enter键,会出现修正版别的选项。当引入完以后,就能够点击sync进行数据操作同步。假如已经有了这个包就能够不必管他了。

2.创立三个fragment

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

依据我上述截图来操作,创立三个姓名分别为homeFragment,moreFragment,userFragment。其对应布局文件姓名为fragment_home,fragment_more,fragment_user。

创立好后三个fragment的class里边的暂时先不必管

3.创立menu

BottomNavigationView 能够来创立底部导航栏,而菜单项组合menu就在其间。

先在res文件夹中创立一个menu文件夹

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换
然后创立一个名为menu的xml文件,将下列代码写进文件中:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
​
  <item
    android:id="@+id/item_home"
    android:icon="@drawable/home"
    android:title="@string/home"
    />
​
  <item
    android:id="@+id/item_more"
    android:icon="@drawable/more"
    android:title="@string/more"
    />
​
  <item
    android:id="@+id/item_user"
    android:icon="@drawable/user"
    android:title="@string/user"
    />
​
</menu>

其间@drawable/user是drawable下的user.png,一张图片,由 android:icon引用。同理”@string/user”是 res/values/strings.xml文件里的用户代码,这样,底部导航栏菜单项的标题就会显现为 “用户”。这儿引荐运用阿里矢量图标库。drawable文件是用于存放图片的,把图复制粘贴进去就行。其间姓名不能为中文等字符,否则会报错。

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

4.编写ViewPagerAdapter继承FragmentPagerAdapter

完成底部导航栏的切换咱们需求FragmentPagerAdapter的协助,所以创立并编写ViewPagerAdapter类(这是我取的姓名,想取什么姓名都行)继承FragmentPagerAdapter。

代码如下:

package com.example.bnvone.Adapter;
​
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
​
import java.util.List;
​
public class ViewPagerAdapter extends FragmentPagerAdapter {
  private List<Fragment> mfragmentList;
  public ViewPagerAdapter(@NonNull FragmentManager fm,List<Fragment> fragmentList) {
    super(fm);//调用父类构造函数,传递FragmentManager 参数
         //用于保证适配器类内部具有有用的 FragmentManager 实例,从而顺利完成片段管理和展现的任务
    this.mfragmentList = fragmentList;
​
   }//设置 ViewPager 的适配器。
​
​
  @NonNull
  @Override
  public Fragment getItem(int position) {
    return mfragmentList == null ? null: mfragmentList.get(position);
   }// mfragmentList == null ? null 判断mfragmentList是否为空,假如不为null,履行:后面的代码。
   //mfragmentList.get(position)获得第position个的fragment目标回来@Override
  public int getCount() {
    return mfragmentList == null ? null: mfragmentList.size();
    // 回来片段目标的数量,即mfragmentList列表中的元素个数
   }
}
​

这个适配器的作用是将 Fragment 列表与 ViewPager 相关起来,以便在 ViewPager 中展现相应的内容。经过重写 getItemgetCount 办法,适配器能够依据方位回来对应的 Fragment 目标,并在 ViewPager 中正确显现。其间重写的办法咱们会在MainActivity中调用。

前期准备的差不多了,能够开端完成了。

3.完成底部导航栏同步切换操作

1.创立MainActivity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
  android:orientation="vertical"
  >
​
  <androidx.viewpager.widget.ViewPager
    android:id="@+id/vp"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
   />
​
​
  <com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_bottom"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="#ffffff"
    app:menu="@menu/menu_nav"
    />
​
​
​
</LinearLayout>
​

运用的线性布局,也能够运用其他的。出现vp <androidx.viewpager.widget.ViewPager>: No speakable text present问题不大,能够运转。得到的样子是这样的

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

2.编写MainActivity

package com.example.bnvone;
​
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
​
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.MenuItem;
​
import com.example.bnvone.Adapter.ViewPagerAdapter;
import com.example.bnvone.Fragment.homeFragment;
import com.example.bnvone.Fragment.moreFragment;
import com.example.bnvone.Fragment.userFragment;
​
import com.google.android.material.bottomnavigation.BottomNavigationView;
​
import java.util.ArrayList;
import java.util.List;
​
public class MainActivity extends AppCompatActivity {
  private BottomNavigationView navigationView;
  private ViewPager viewPager;
​
​
  @Override
  protected void onCreate(Bundle savedInstanceState) {
​
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
​
    navigationView = findViewById(R.id.nav_bottom);
    viewPager = findViewById(R.id.vp);
​
    homeFragment homeFragment= new homeFragment();
​
    List<Fragment> fragments = new ArrayList<>();
    fragments.add(new homeFragment()); //新建一个homeFragment目标将这个目标加入到数组fragments中
    fragments.add(new moreFragment());
    fragments.add(new userFragment());
​
    ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),fragments);
    //创立目标并经过构造函数初始化,该适配器能够知道要显现哪些片段。
    viewPager.setAdapter(viewPagerAdapter);
    //将前面创立的 viewPagerAdapter 适配器设置给 viewPager 视图组件,以便在 ViewPager 中显现相应的页面。
    //底部导航栏监听事情
    navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
      @SuppressLint("NonConstantResourceId")
      @Override
      public boolean onNavigationItemSelected(@NonNull MenuItem item) {
      //依据菜单ID显现页面
        switch (item.getItemId()) {//监听事情中,点击菜单立马履行item.getItemId()办法
          //item.getItemId() 办法用于获取选中的 MenuItem 的仅有标识符(ID)
          case R.id.item_home://R.id.xxx是整数类型。
            viewPager.setCurrentItem(0);
            // 将 ViewPager 的当前页面显现成索引为 0 的页面
            return true;
          case R.id.item_more:
            viewPager.setCurrentItem(1);
            return true;
          case R.id.item_user:
            viewPager.setCurrentItem(2);
            return true;
         }
        return false;
       }
​
     });
​
    // 增加页面切换的监听器,依据页面切换完成菜单切换
  viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
​
     }
​
    @Override
    public void onPageSelected(int position) {
    switch (position){ // 依据页面方位更新导航栏的选中状况
      case 0:
        navigationView.setSelectedItemId(R.id.item_home);
        //将导航栏中的选中项设置为 R.id.item_home
        break;
      case 1:
        navigationView.setSelectedItemId(R.id.item_more);
        break;
      case 2:
        navigationView.setSelectedItemId(R.id.item_user);
        break;
     }
   }
​
    @Override
    public void onPageScrollStateChanged(int state) {}
   });//经过运用页面切换监听器,
    // 咱们能够依据页面切换的状况来更改导航栏的选中状况,
    // 从而完成页面切换时导航栏菜单的同步切换作用。
​
   }
}
​
​

完成了底部导航栏与 ViewPager 的联动作用。底部导航栏经过监听选中项的改动,然后依据选中项对应的页面索引,调用 ViewPager 的 setCurrentItem 办法来切换到相应的页面。一起,ViewPager 增加了页面切换的监听器,经过监听页面的切换事情,更新底部导航栏的选中状况,以完成同步切换作用。

完成以下操作就能够完成同步切换了。

补充

我的fragment代码:

<?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=".Fragment.moreFragment">
​
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">
​
    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="2"
      android:textSize="50sp" />
​
  </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

本次操作所需求所有文件:

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换
作用如下:

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

是不是很简单,有手就行

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换

会了的话就给个引荐之类的吧,各位兄弟们

Android studio中使用ViewPager和BottomnavigationView实现底部导航栏和碎片的同步切换