前言
通过几次的踩雷和摸索,完成了以上的操作,本教程写的详细全面,包教包会,对新手有好,看了不会的联系我,我倒立洗头给你看。
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 循环,分别对 stringList
和 integerList
进行迭代遍历,将列表中的元素逐个取出,并分别打印输出。
在第一个循环中,每次迭代将当前的字符串元素赋值给变量 str
,然后将其输出。因此,在循环的第一次迭代中,会输出 "Hello",在第二次迭代中,会输出 "World"。
在第二个循环中,每次迭代将当前的整数元素赋值给变量 num
,然后将其输出。因此,在循环的第一次迭代中,会输出 1,第二次迭代中,会输出 2。
所以最终的输出结果是:
Hello
World
1
2
2.准备工作
1.导入所需包
在build.gradle文件中引入implementation 'com.google.android.material:material:1.9.0'
当导入进去后,可能会有版本不一样的情况,如果报黄,点击alt+enter键,会出现修改版本的选项。当引入完以后,就可以点击sync进行数据操作同步。如果已经有了这个包就可以不用管他了。
2.创建三个fragment
根据我上述截图来操作,创建三个名字分别为homeFragment,moreFragment,userFragment。其对应布局文件名字为fragment_home,fragment_more,fragment_user。
创建好后三个fragment的class里面的暂时先不用管
3.创建menu
BottomNavigationView
可以来创建底部导航栏,而菜单项组合menu就在其中。
先在res文件夹中创建一个menu文件夹
然后创建一个名为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
文件里的<string name="user">用户</string>代码,这样,底部导航栏菜单项的标题就会显示为 "用户"。这里推荐使用阿里矢量图标库。drawable文件是用于存放图片的,把图复制粘贴进去就行。其中名字不能为中文等字符,不然会报错。
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 中展示相应的内容。通过重写 getItem
和 getCount
方法,适配器可以根据位置返回对应的 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问题不大,可以运行。得到的样子是这样的
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>
本次操作所需要所有文件:
效果如下:
是不是很简单,有手就行
会了的话就给个推荐之类的吧,各位兄弟们
----------------2023年11月23日修改----------------
拓展使用
随着软件的不断成熟,导航栏的样式也变得越来越多,各大APP顶部导航栏流行使用字体当做顶部导航栏,并在选中后实现放大等样式改变的效果。
我们来简单实现一下这种效果:
创建viewpagerActivity
创建一个新的activity,命名viewpagerActivity;
XML文件
他的布局代码如下:
<?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"
tools:context=".viewpagerActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView1"
android:text="动态"
android:textSize="20sp"
android:layout_marginLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/textView2"
android:text="排行榜"
android:textSize="20sp"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:ignore="SpeakableTextPresentCheck">
</androidx.viewpager.widget.ViewPager>
</LinearLayout>
是这种效果:
再按上文创建两个fragment,一个oneFragment,一个twoFragment;
java文件
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import android.graphics.Color;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class viewpagerActivity extends AppCompatActivity {
TextView textView1;
TextView textView2;
ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewpager);
textView1 = findViewById(R.id.textView1);
textView2 = findViewById(R.id.textView2);
viewPager = findViewById(R.id.viewPager);
List<Fragment> fragments = new ArrayList<>();
fragments.add(new oneFragment());
fragments.add(new twoFragment());
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),fragments);
viewPager.setAdapter(viewPagerAdapter);
textView1.animate().scaleX(1.5f).scaleY(1.5f).setDuration(0).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
textView1.setTextColor(Color.BLACK);
textView1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView1.setTextColor(Color.BLACK);
viewPager.setCurrentItem(0);
}
});
textView2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewPager.setCurrentItem(1);
}
});
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:
textView1.animate().scaleX(1.5f).scaleY(1.5f).setDuration(100).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
textView2.animate().scaleX(1f).scaleY(1f).setDuration(100).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
textView1.setTextColor(Color.BLACK);
textView2.setTextColor(Color.GRAY);
break;
case 1:
textView2.animate().scaleX(1.5f).scaleY(1.5f).setDuration(100).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
textView1.animate().scaleX(1f).scaleY(1f).setDuration(100).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
textView2.setTextColor(Color.BLACK);
textView1.setTextColor(Color.GRAY);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
完成后的效果如下:文章来源:https://www.toymoban.com/news/detail-719273.html
文章来源地址https://www.toymoban.com/news/detail-719273.html
到了这里,关于Android studio中使用ViewPager和BottomNavigationView实现底部导航栏和碎片的同步切换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!