Android ViewPager2 + TabLayout + BottomNavigationView
创始人
2024-03-12 03:27:44

Android ViewPager2 + TabLayout + BottomNavigationView 实际案例

本篇主要介绍一下 ViewPager2 + TabLayout + BottomNavigationView 的结合操作

2022-11-25 18.09.09

概述

相信大家都看过今日头条的的样式 如下: 顶部有这种tab 并且是可以滑动的, 这就是本篇所介绍的 ViewPager2 + TabLayout 的组合 下面来看看如何实现把

image-20221125174731255

实现思路

1.Activity 布局文件中引入BottomNavigationView 和 FragmentContainerView控件
2.编写 TabLayoutHomeFragment 布局文件
3.编写 Fragment 用于集成ViewPager2 和TabLayout
4. 编写 RecFragment 用于继承RecycleView 展示
5.实现 ViewPager2TabLayoutActivity

代码实现

1.Activity 布局文件中引入BottomNavigationView 和 FragmentContainerView控件

其中 menu 使用上一篇中的指定的 menu



image-20221125175220781

2.编写 TabLayoutHomeFragment 布局文件

主要想在这个 Home首页 Fragment 中 实现TabLayout 和 ViewPager2滑动功能


3. 编写 TabLayoutHomeFragment代码部分 用于集成ViewPager2 和TabLayout

package com.johnny.slzzing.tablayout;import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.johnny.slzzing.BottomFragment;
import com.johnny.slzzing.R;
import com.johnny.slzzing.RecFragment;import java.util.Arrays;
import java.util.List;public class TabLayoutHomeFragment2 extends Fragment {private static final String ARG_PARAM1 = "param1";private static final String ARG_PARAM2 = "param2";private static final String TAG = "TabLayoutHomeFragment";// TODO: Rename and change types of parametersprivate String mParam1;private String mParam2;private ViewPager2 viewPager2;private TabLayout tabLayout;public TabLayoutHomeFragment2() {}public static TabLayoutHomeFragment2 newInstance(String param1, String param2) {TabLayoutHomeFragment2 fragment = new TabLayoutHomeFragment2();Bundle args = new Bundle();args.putString(ARG_PARAM1, param1);args.putString(ARG_PARAM2, param2);fragment.setArguments(args);return fragment;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() != null) {mParam1 = getArguments().getString(ARG_PARAM1);mParam2 = getArguments().getString(ARG_PARAM2);}}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_tab_layout_home2, container, false);}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);viewPager2 = view.findViewById(R.id.myviepage2);viewPager2.setSaveEnabled(false);tabLayout = view.findViewById(R.id.mytablayout2);List titleList = initPageTitleList();TabLayoutChildViewPager tabLayoutChildViewPager =new TabLayoutChildViewPager(getActivity(),initChildFragmentList());//重点!! ViewPager2绑定AdapterviewPager2.setAdapter(tabLayoutChildViewPager);//重点!! 关联 TabLayout 和 ViewPager2new TabLayoutMediator(tabLayout, viewPager2, true,(tab, position) -> tab.setText(titleList.get(position))).attach();}private List initPageTitleList() {return Arrays.asList("推荐","关注","娱乐","游戏","电影", "电视剧","实时新闻");}private List initChildFragmentList() {//在tablayout 的第一个fragment 中使用 RecycleView 优化一下页面RecFragment recFragment = new RecFragment();//BottomFragment bottomFragment = BottomFragment.newInstance("推荐", "");BottomFragment bottomFragment2 = BottomFragment.newInstance("关注", "");BottomFragment bottomFragment3 = BottomFragment.newInstance("娱乐", "");BottomFragment bottomFragment4 = BottomFragment.newInstance("游戏", "");BottomFragment bottomFragment5 = BottomFragment.newInstance("电影", "");BottomFragment bottomFragment6 = BottomFragment.newInstance("电视剧", "");BottomFragment bottomFragment7 = BottomFragment.newInstance("实时新闻", "");return Arrays.asList(recFragment,bottomFragment2,bottomFragment3,bottomFragment4,bottomFragment5,bottomFragment6,bottomFragment7);}static class TabLayoutChildViewPager extends FragmentStateAdapter{private List fragmentList;public TabLayoutChildViewPager(@NonNull FragmentActivity fragmentActivity, List fragmentList) {super(fragmentActivity);this.fragmentList = fragmentList;}@NonNull@Overridepublic Fragment createFragment(int position) {return fragmentList.get(position);}@Overridepublic int getItemCount() {return fragmentList.size();}}
}

4. 编写 RecFragment 用于继承RecycleView 展示

主要是优化TabLayout 的第一个fragment 样式

package com.johnny.slzzing;import static com.johnny.slzzing.R.drawable.discountberry;
import static com.johnny.slzzing.R.drawable.discountbrocoli;
import static com.johnny.slzzing.R.drawable.discountmeat;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;
import java.util.List;/*** A simple {@link Fragment} subclass.* Use the {@link RecFragment#newInstance} factory method to* create an instance of this fragment.*/
public class RecFragment extends Fragment {// TODO: Rename parameter arguments, choose names that match// the fragment initialization parameters, e.g. ARG_ITEM_NUMBERprivate static final String ARG_PARAM1 = "param1";private static final String ARG_PARAM2 = "param2";// TODO: Rename and change types of parametersprivate String mParam1;private String mParam2;private RecyclerView discountRecyclerView;private DiscountedProductAdapter discountedProductAdapter;public RecFragment() {// 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 RecFragment.*/// TODO: Rename and change types and number of parameterspublic static RecFragment newInstance(String param1, String param2) {RecFragment fragment = new RecFragment();Bundle args = new Bundle();args.putString(ARG_PARAM1, param1);args.putString(ARG_PARAM2, param2);fragment.setArguments(args);return fragment;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() != null) {mParam1 = getArguments().getString(ARG_PARAM1);mParam2 = getArguments().getString(ARG_PARAM2);}}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_rec, container, false);}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);discountRecyclerView = view.findViewById(R.id.discountedRecycler);setDiscountedRecycler(initDiscountList());}private List initDiscountList() {List discountedProductsList = new ArrayList<>();discountedProductsList.add(new DiscountedProducts(1, discountberry, "草莓", "草莓,多年生草本植物。高10-40厘米,茎低于叶或近相等,密被开展黄色柔毛"));discountedProductsList.add(new DiscountedProducts(2, discountbrocoli, "花菜","花椰菜(是十字花科、芸薹属植物野甘蓝的变种。"));discountedProductsList.add(new DiscountedProducts(3, discountmeat, "西红柿", "番茄 是茄科茄属 [2]  一年生或多年生草本植物,体高0.6-2米,全体生粘质腺毛,有强烈气味,茎易倒伏,叶羽状复叶或羽状深裂"));discountedProductsList.add(new DiscountedProducts(4, discountberry, "西瓜","西瓜 一年生蔓生藤本;茎、枝粗壮,具明显的棱。卷须较粗壮,具短柔毛,叶柄粗,密被柔毛"));discountedProductsList.add(new DiscountedProducts(5, discountbrocoli,  "南瓜","南瓜 葫芦科南瓜属的一个种,一年生蔓生草本植物"));discountedProductsList.add(new DiscountedProducts(6, discountmeat, "猕猴桃", "中华猕猴桃 是猕猴桃科、猕猴桃属大植物。大型落叶藤本;幼一枝或厚或薄地被有灰白色茸毛或褐色长硬毛或铁锈色硬毛状刺毛,老时秃净或留有断损残毛"));discountedProductsList.add(new DiscountedProducts(7, discountberry, "草莓", "草莓,多年生草本植物。高10-40厘米,茎低于叶或近相等,密被开展黄色柔毛"));discountedProductsList.add(new DiscountedProducts(8, discountbrocoli, "花菜","花椰菜 是十字花科、芸薹属植物野甘蓝的变种。"));discountedProductsList.add(new DiscountedProducts(9, discountmeat, "西红柿", "番茄 是茄科茄属 [2]  一年生或多年生草本植物,体高0.6-2米,全体生粘质腺毛,有强烈气味,茎易倒伏,叶羽状复叶或羽状深裂"));discountedProductsList.add(new DiscountedProducts(10, discountberry, "西瓜","西瓜 一年生蔓生藤本;茎、枝粗壮,具明显的棱。卷须较粗壮,具短柔毛,叶柄粗,密被柔毛"));discountedProductsList.add(new DiscountedProducts(11, discountbrocoli,  "南瓜","南瓜 葫芦科南瓜属的一个种,一年生蔓生草本植物"));discountedProductsList.add(new DiscountedProducts(12, discountmeat, "猕猴桃", "中华猕猴桃 是猕猴桃科、猕猴桃属大植物。大型落叶藤本;幼一枝或厚或薄地被有灰白色茸毛或褐色长硬毛或铁锈色硬毛状刺毛,老时秃净或留有断损残毛"));return discountedProductsList ;}private void setDiscountedRecycler(List dataList) {RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);discountedProductAdapter = new DiscountedProductAdapter(getContext(),dataList);discountRecyclerView.setLayoutManager(layoutManager);discountRecyclerView.setAdapter(discountedProductAdapter);}
}

5.实现 ViewPager2TabLayoutActivity

package com.johnny.slzzing;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.MenuItem;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentContainerView;import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;
import com.johnny.slzzing.tablayout.TabLayoutHomeFragment2;import java.util.HashMap;
import java.util.Map;public class ViewPager2TabLayoutActivity extends AppCompatActivity {BottomNavigationView bottomNavigationView;FragmentContainerView fragmentContainerView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_view_pager2_tab_layout);bottomNavigationView = findViewById(R.id.bootomnav3);fragmentContainerView  = findViewById(R.id.container_view);Map fragmentMap = new HashMap<>();TabLayoutHomeFragment2 tabLayoutHomeFragment2 = new TabLayoutHomeFragment2();//这里 第一个home fragment 使用上面编写的 TabLayoutHomeFragment2fragmentMap.put(R.id.home_item,tabLayoutHomeFragment2);fragmentMap.put(R.id.type_item,Bottom2Fragment.newInstance("我是typefragment", ""));fragmentMap.put(R.id.add_item,Bottom2Fragment.newInstance("我是addfragment", ""));fragmentMap.put(R.id.setting_item,Bottom2Fragment.newInstance("我是settingfragment", ""));//bottomNavigationView 点击用于替换 FragmentContainerViewbottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {@SuppressLint("NonConstantResourceId")@Overridepublic boolean onNavigationItemSelected(@NonNull MenuItem item) {int itemId = item.getItemId();switch (itemId){case R.id.home_item:getSupportFragmentManager().beginTransaction().replace(R.id.container_view, fragmentMap.get(R.id.home_item)).commit();break;case R.id.type_item:getSupportFragmentManager().beginTransaction().replace(R.id.container_view, fragmentMap.get(R.id.type_item)).commit();case R.id.add_item:getSupportFragmentManager().beginTransaction().replace(R.id.container_view, fragmentMap.get(R.id.add_item)).commit();case R.id.setting_item:getSupportFragmentManager().beginTransaction().replace(R.id.container_view, fragmentMap.get(R.id.setting_item)).commit();}return true;}});getSupportFragmentManager().beginTransaction().replace(R.id.container_view, fragmentMap.get(R.id.home_item)).commit();}
}

效果

可以看到 顶部有类似 今日头条的 Tab 并且可以滑动哟

image-20221125180539423

总结

本篇主要介绍了 ViewPager2 + TabLayout 的一个集成 实现类似今日头条的顶部Tab 并且支持滑动

核心联动代码

不同于ViewPager , ViewPager2 使用 TabLayoutMediator 来联动TabLayout 和ViewPager2 以及 tab的标题,注意最后要 attach()

viewPager2.setAdapter(tabLayoutChildViewPager);
new TabLayoutMediator(tabLayout, viewPager2, true,(tab, position) -> tab.setText(titleList.get(position))).attach();

欢迎大家访问 个人博客 Johnny小屋
欢迎关注个人公众号

欢迎关注个人公众号

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...