本篇主要介绍一下 ViewPager2 + Fragment + BottomNavigationView , 上篇中把ViewPager2和Fragment 联动起来了, 本篇主要把 BottomNavigationView集成进去

BottomNavigationView 是一个底部导航控件, 现在要实现的效果就是 滑动ViewPager2 中的Fragment 并且底部BottomNavigationView 菜单部分跟着联动 同理反过来 点击BottomNavigationView 的时候 ViewPager2中的Fragment 也对应滑动, 下面来看看如何实现的吧
编写menu文件 提供给BottomNavigationView 用于展示编写Adapter 实现 FragmentStateAdapter下面就来按照上面的思路一步步实现代码啦!
<?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>
图标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>
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>
<?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>
编写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();
}
}
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;
}
});
}
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;
}
}
});
}

本篇主要介绍了 如何把ViewPager2 + Fragment + BottomNavigationView 集成起来并且实现ViewPager2和BottomNavigationView的双向联动
ViewPager和ViewPager2 一些区别:
欢迎大家访问 个人博客 Johnny小屋
欢迎关注个人公众号

先给大家看看最终效果首先我们来定义数据data(){ return{ lsit:[ 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic118.nipic.com%2Ffile%2F20161216%2F24271963_122609717000_2.jpg&refer=http%3A%2F%2Fpic118.nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1656923017&t=183ece148b13b64e9dd503afd1b15c91'
我一直在尝试使用Rails的缓存功能,但我无法使某些缓存片段过期,尽管它们似乎已过期。使用Rails教程站点中指出的“俄罗斯娃娃缓存”,我正在使用此配置我在release_controller.rbController中使外部缓存过期,我在其中使用expire_fragment("all_available_releases")使片段过期。我在更新、删除或添加条目的Controller的每个方法中都使用它。这是WEBrick的日志,尽管过期片段已在其中注册,但5行后过期片段被读取并使用,而这是不应该的。这个例子是在destroy调用之后。ProcessingbyReleasesCont
我几乎什么都试过了,但似乎无法使用来自模型的expire_fragment?我知道你不应该这样做非MVC,但肯定有很多方法可以做到。我在lib/cache_helper.rb中用我所有的过期助手创建了一个模块,在每个中只是一堆expire_fragment调用。我有我所有的/app/sweepers下的缓存清扫器设置,并有一个“includeCacheHelper”在我的应用程序Controller中,因此在通过Controller调用时应用程序工作正常。然后事情是我有一些外部守护进程,尤其是一些循环的cron任务调用一个调用特定任务的rake任务方法。此方法进行一些处理并将条目输入到
我正在使用three.js运行资源匮乏的片段着色器。我已将渲染大小设置为800*600,以保持着色器即使在低端卡上也能流畅运行。我正在这样设置我的渲染Canvas:varcanvas1=document.getElementById('canvas1');renderer=newTHREE.WebGLRenderer(canvas1);renderer.setSize(800,600);renderer.autoClear=false;document.body.appendChild(renderer.domElement);在body元素上我有然后我在cssheader中做widt
当按下后退按钮时,我的fragment正在更改为主页,但底部图标没有改变。我在这里发布了我的所有代码。如果我从底部导航View项目中选择了两个以上的导航按钮,那么当我按下后退按钮时,它将重定向到最后选择的按钮项目。但现在发生的事情是,假设我在最后一个项目上说“通知”[如您在屏幕截图中所见],现在当我按下后退按钮时,它会直接带我到“主页”按钮,但是我想要的是它应该首先带我到“搜索”按钮项目然后到“主页”而不是直接到“主页”。我怎样才能做到这一点?这是布局:这是Activity:publicclassMainActivityextendsAppCompatActivity{privates
在我的布局底部,我有一个包含三个fragment的BottomNavigationView。如果我单击后退按钮,fragment会切换,但不会切换底部图标。我该如何解决?addToBackStack()有效。也许您对代码的美化有一些建议。在Activity或fragment中使用fragment标签是一种好的做法吗?publicclassMainActivityextendsAppCompatActivity{privateFragmentManagermFragmentManager;privateBottomNavigationViewmBottomNavigationView;p
当我点击fragment中的线性布局时,它不会给出任何错误,但不会开始新的Activity。我的代码有什么错误吗?请有人帮助我。我的项目的这个fragmentxml文件代码。Fragment_one.xml我的项目的这段java类代码。FragmentOne.javainfo.androidhive.listviewfeed;importandroid.app.Fragment;importandroid.content.Intent;importandroid.os.Build;importandroid.os.Bundle;importandroid.view.LayoutInfl
我在tv.setMovementMethod(newScrollingMovementMethod());上遇到了NullPointerException但我完全不知道为什么!我已经在XML文件中声明了textView并在onCreateView中对其进行了初始化。任何帮助,将不胜感激。这里是java代码的相关部分:publicclassTestConnectionextendsFragment{publicTestConnection(){}JSONParserjParser=newJSONParser();//buttonpressedtogettheitemsButtongetA
我使用GoogleMapsAndroidv1API创建了我的应用程序的第一个版本。但是现在当我发布第二个版本的应用程序时,谷歌地图停止工作。我认为这是因为它已被弃用。所以现在我正在尝试创建示例Android应用程序以使用链接使用Googlemaphttps://developers.google.com/maps/documentation/android/start#getting_the_google_maps_android_api_v2但是我遇到了强制关闭错误FATALEXCEPTION:mainjava.lang.RuntimeException:Unabletostarta
我正在尝试开发一个时间线,就像下面的facebook一样。你看,我有一个ViewPager可以在“fragment”(如提要、个人资料、关于等)之间导航用户。我有“main.xml”,它上面只有viewpager;我还有fragmenta.xml、fragmentb.xml、fragmentc.xml。让我们检查一下fragmenta.xml,我把它放在里面;并制作了singlerow.xml来将这些框创建成这样的时间线;我让它只使用一个静态框。但是当我尝试运行这个结构时,我在Debug模式下遇到错误“找不到来源编辑源查找路径”在我尝试像这样将我的适配器和其他关于listview的东西