以前,viewpager+tablayout联动,只需要以下两行代码就解决,

        mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));mTabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

类似的,官方也为了我们提示了tablayout+viewpager2的联动工具类:TabLayoutMediator

使用的时候只需要以下几行代码,就实现了tablayout+viewpager2联动

        new TabLayoutMediator(tabLayout, viewPager2, true,new TabLayoutMediator.OnConfigureTabCallback() {@Overridepublic void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {//这里需要根据position修改tab的样式和文字等tab.setText("fragment"+position);}}).attach();

注:material1.1.0之前,material包是不包含TabLayoutMediator的,想使用需要复制TabLayoutMediator源码,源码在下面!!

示例:

xml代码:简单的界面,顶部tablayout,底部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=".Main2Activity"><com.google.android.material.tabs.TabLayoutandroid:id="@+id/tablayout"android:layout_width="match_parent"android:layout_height="wrap_content"app:tabIndicatorColor="@color/colorPrimary"app:tabTextColor="@color/colorAccent"app:tabSelectedTextColor="@color/colorPrimary"app:tabIndicatorFullWidth="false"app:tabMode="scrollable"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><androidx.viewpager2.widget.ViewPager2android:id="@+id/viewpager2"android:layout_width="match_parent"android:layout_height="0dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/tablayout" /></androidx.constraintlayout.widget.ConstraintLayout>

activity代码:

 @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);viewPager2 = findViewById(R.id.viewpager2);tabLayout = findViewById(R.id.tablayout);viewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);List<Fragment> fragments = new ArrayList<>();for (int i = 0; i < 20; i++) {fragments.add(BlankFragment.newInstance());}viewPager2.setAdapter(new FragmentStateAdapter(this) {@NonNull@Overridepublic Fragment createFragment(int position) {Fragment fragment = fragments.get(position);return fragment;}@Overridepublic int getItemCount() {return fragments.size();}});viewPager2.setOffscreenPageLimit(3);new TabLayoutMediator(tabLayout, viewPager2, true,new TabLayoutMediator.OnConfigureTabCallback() {@Overridepublic void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {//这里需要根据position修改tab的样式和文字等tab.setText("fragment"+position);}}).attach();//最后一定要attach()}
TabLayoutMediator源码:直接拷贝到你的项目里就能用
@RestrictTo(LIBRARY_GROUP)
public final class TabLayoutMediator {private final @NonNullTabLayout mTabLayout;private final @NonNullViewPager2 mViewPager;private final boolean mAutoRefresh;private final OnConfigureTabCallback mOnConfigureTabCallback;private RecyclerView.Adapter mAdapter;private boolean mAttached;private TabLayoutOnPageChangeCallback mOnPageChangeCallback;private TabLayout.OnTabSelectedListener mOnTabSelectedListener;private RecyclerView.AdapterDataObserver mPagerAdapterObserver;/*** A callback interface that must be implemented to set the text and styling of newly created* tabs.*/public interface OnConfigureTabCallback {/*** Called to configure the tab for the page at the specified position. Typically calls** @param tab The Tab which should be configured to represent the title of the item at the*        given position in the data set.* @param position The position of the item within the adapter's data set.*/void onConfigureTab(@NonNull TabLayout.Tab tab, int position);}/*** Creates a TabLayoutMediator to synchronize a TabLayout and a ViewPager2 together. It will* update the tabs automatically when the data set of the view pager's adapter changes. The link* will be established after {@link #attach()} is called.** @param tabLayout The tab bar to link* @param viewPager The view pager to link*/public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager,@NonNull OnConfigureTabCallback onConfigureTabCallback) {this(tabLayout, viewPager, true, onConfigureTabCallback);}/*** Creates a TabLayoutMediator to synchronize a TabLayout and a ViewPager2 together. If {@code* autoRefresh} is true, it will update the tabs automatically when the data set of the view* pager's adapter changes. The link will be established after {@link #attach()} is called.** @param tabLayout The tab bar to link* @param viewPager The view pager to link* @param autoRefresh If {@code true}, will recreate all tabs when the data set of the view*                   pager's adapter changes.*/public TabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager,boolean autoRefresh, @NonNull OnConfigureTabCallback onConfigureTabCallback) {mTabLayout = tabLayout;mViewPager = viewPager;mAutoRefresh = autoRefresh;mOnConfigureTabCallback = onConfigureTabCallback;}/*** Link the TabLayout and the ViewPager2 together.*         adapter.*/public void attach() {if (mAttached) {throw new IllegalStateException("TabLayoutMediator is already attached");}mAdapter = mViewPager.getAdapter();if (mAdapter == null) {throw new IllegalStateException("TabLayoutMediator attached before ViewPager2 has an "+ "adapter");}mAttached = true;// Add our custom OnPageChangeCallback to the ViewPagermOnPageChangeCallback = new TabLayoutOnPageChangeCallback(mTabLayout);mViewPager.registerOnPageChangeCallback(mOnPageChangeCallback);// Now we'll add a tab selected listener to set ViewPager's current itemmOnTabSelectedListener = new ViewPagerOnTabSelectedListener(mViewPager);mTabLayout.addOnTabSelectedListener(mOnTabSelectedListener);// Now we'll populate ourselves from the pager adapter, adding an observer if// autoRefresh is enabledif (mAutoRefresh) {// Register our observer on the new adaptermPagerAdapterObserver = new PagerAdapterObserver();mAdapter.registerAdapterDataObserver(mPagerAdapterObserver);}populateTabsFromPagerAdapter();// Now update the scroll position to match the ViewPager's current itemmTabLayout.setScrollPosition(mViewPager.getCurrentItem(), 0f, true);}/*** Unlink the TabLayout and the ViewPager*/public void detach() {mAdapter.unregisterAdapterDataObserver(mPagerAdapterObserver);mTabLayout.removeOnTabSelectedListener(mOnTabSelectedListener);mViewPager.unregisterOnPageChangeCallback(mOnPageChangeCallback);mPagerAdapterObserver = null;mOnTabSelectedListener = null;mOnPageChangeCallback = null;}@SuppressWarnings("WeakerAccess")void populateTabsFromPagerAdapter() {mTabLayout.removeAllTabs();if (mAdapter != null) {int adapterCount = mAdapter.getItemCount();for (int i = 0; i < adapterCount; i++) {TabLayout.Tab tab = mTabLayout.newTab();mOnConfigureTabCallback.onConfigureTab(tab, i);mTabLayout.addTab(tab, false);}// Make sure we reflect the currently set ViewPager itemif (adapterCount > 0) {int currItem = mViewPager.getCurrentItem();if (currItem != mTabLayout.getSelectedTabPosition()) {mTabLayout.getTabAt(currItem).select();}}}}/*** A {@link ViewPager2.OnPageChangeCallback} class which contains the necessary calls back to* the provided {@link TabLayout} so that the tab position is kept in sync.** <p>This class stores the provided TabLayout weakly, meaning that you can use {@link* ViewPager2#registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback)} without removing* the callback and not cause a leak.*/private static class TabLayoutOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {private final WeakReference<TabLayout> mTabLayoutRef;private int mPreviousScrollState;private int mScrollState;TabLayoutOnPageChangeCallback(TabLayout tabLayout) {mTabLayoutRef = new WeakReference<>(tabLayout);reset();}@Overridepublic void onPageScrollStateChanged(final int state) {mPreviousScrollState = mScrollState;mScrollState = state;}@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {TabLayout tabLayout = mTabLayoutRef.get();if (tabLayout != null) {// Only update the text selection if we're not settling, or we are settling after// being draggedboolean updateText = mScrollState != SCROLL_STATE_SETTLING|| mPreviousScrollState == SCROLL_STATE_DRAGGING;// Update the indicator if we're not settling after being idle. This is caused// from a setCurrentItem() call and will be handled by an animation from// onPageSelected() instead.boolean updateIndicator = !(mScrollState == SCROLL_STATE_SETTLING&& mPreviousScrollState == SCROLL_STATE_IDLE);setScrollPosition(tabLayout, position, positionOffset, updateText, updateIndicator);}}@Overridepublic void onPageSelected(final int position) {TabLayout tabLayout = mTabLayoutRef.get();if (tabLayout != null&& tabLayout.getSelectedTabPosition() != position&& position < tabLayout.getTabCount()) {// Select the tab, only updating the indicator if we're not being dragged/settled// (since onPageScrolled will handle that).boolean updateIndicator = mScrollState == SCROLL_STATE_IDLE|| (mScrollState == SCROLL_STATE_SETTLING&& mPreviousScrollState == SCROLL_STATE_IDLE);selectTab(tabLayout, tabLayout.getTabAt(position), updateIndicator);}}void reset() {mPreviousScrollState = mScrollState = SCROLL_STATE_IDLE;}}// region Reflective calls// Temporarily call methods TabLayout.setScrollPosition(int, float, boolean, boolean) and// TabLayout.selectTab(TabLayout.Tab, boolean) through reflection, until they have been made// public in the Material Design Components library.private static Method sSetScrollPosition;private static Method sSelectTab;private static final String SET_SCROLL_POSITION_NAME = "TabLayout.setScrollPosition(int, float,"+ " boolean, boolean)";private static final String SELECT_TAB_NAME = "TabLayout.selectTab(TabLayout.Tab, boolean)";static {try {sSetScrollPosition = TabLayout.class.getDeclaredMethod("setScrollPosition", int.class,float.class, boolean.class, boolean.class);sSetScrollPosition.setAccessible(true);sSelectTab = TabLayout.class.getDeclaredMethod("selectTab", TabLayout.Tab.class,boolean.class);sSelectTab.setAccessible(true);} catch (NoSuchMethodException e) {throw new IllegalStateException("Can't reflect into method TabLayout"+ ".setScrollPosition(int, float, boolean, boolean)");}}@SuppressWarnings("WeakerAccess")static void setScrollPosition(TabLayout tabLayout, int position, float positionOffset,boolean updateSelectedText, boolean updateIndicatorPosition) {try {if (sSetScrollPosition != null) {sSetScrollPosition.invoke(tabLayout, position, positionOffset, updateSelectedText,updateIndicatorPosition);} else {throwMethodNotFound(SET_SCROLL_POSITION_NAME);}} catch (Exception e) {throwInvokeFailed(SET_SCROLL_POSITION_NAME);}}@SuppressWarnings("WeakerAccess")static void selectTab(TabLayout tabLayout, TabLayout.Tab tab, boolean updateIndicator) {try {if (sSelectTab != null) {sSelectTab.invoke(tabLayout, tab, updateIndicator);} else {throwMethodNotFound(SELECT_TAB_NAME);}} catch (Exception e) {throwInvokeFailed(SELECT_TAB_NAME);}}private static void throwMethodNotFound(String method) {throw new IllegalStateException("Method " + method + " not found");}private static void throwInvokeFailed(String method) {throw new IllegalStateException("Couldn't invoke method " + method);}// endregion/*** A {@link TabLayout.OnTabSelectedListener} class which contains the necessary calls back to* the provided {@link ViewPager2} so that the tab position is kept in sync.*/private static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {private final ViewPager2 mViewPager;ViewPagerOnTabSelectedListener(ViewPager2 viewPager) {this.mViewPager = viewPager;}@Overridepublic void onTabSelected(TabLayout.Tab tab) {mViewPager.setCurrentItem(tab.getPosition(), true);}@Overridepublic void onTabUnselected(TabLayout.Tab tab) {// No-op}@Overridepublic void onTabReselected(TabLayout.Tab tab) {// No-op}}private class PagerAdapterObserver extends RecyclerView.AdapterDataObserver {PagerAdapterObserver() {}@Overridepublic void onChanged() {populateTabsFromPagerAdapter();}@Overridepublic void onItemRangeChanged(int positionStart, int itemCount) {populateTabsFromPagerAdapter();}@Overridepublic void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {populateTabsFromPagerAdapter();}@Overridepublic void onItemRangeInserted(int positionStart, int itemCount) {populateTabsFromPagerAdapter();}@Overridepublic void onItemRangeRemoved(int positionStart, int itemCount) {populateTabsFromPagerAdapter();}@Overridepublic void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {populateTabsFromPagerAdapter();}}
}

查看TabLayoutMediator代码,不难发现,内部也是实现了TabLayout.OnTabSelectedListener和ViewPager2.OnPageChangeCallback,参考官方的写法,我们可以写自己的tablayout和viewpager2的联动

这部分内容将在下一章讲解

TabLayout+ViewPager2联动相关推荐

  1. Android之TabLayout+ViewPager2+FragmentStateAdapter实现带数字变化的TAB选项

    1 问题 TabLayout+ViewPager2实现带数字变化的TAB选项,然后左边滑动或者点击上面的Tab切换fragment不能刷新 2 结果爆照 3 代码实现 layer_tab_indica ...

  2. RecyclerView与ViewPager2

    RecyclerView与ViewPager2 文章目录 RecyclerView与ViewPager2 1:RecyclerView 1.1:基本使用方法 1.1.1定制 RecyclerView ...

  3. android tab 切换动画,Android之ViewPager+TabLayout组合实现导航条切换效果(微信和QQ底部多标签切换)...

    前言 之前在另外一篇中用Fragment和button实现了点击切换Fragment的效果,比较简陋.这次改用ViewPager+TabLayout 实现联动的效果. 实现效果 ViewPager 多 ...

  4. Android ViewPager2总结

    文章目录 ViewPager2总结 概述 常用API ViewPager2基本使用 ViewPager2+TabLayout+Fragment 代码下载 ViewPager2总结 概述 ViewPag ...

  5. ViewPager2的使用

    文章目录 简介 源码简单了解 改动点 常用Api 引入implementation 官方demo介绍 ViewPager2 with Views ViewPager2 with Fragments V ...

  6. android解决 Button 和 TabLayout 英文自动大写的问题

    解决 Button 和 TabLayout 英文自动大写的问题 导言:今天在使用TabLayout + ViewPager2加载页面时发现TabLayout 标题威英文时,全部都是大写展示.为此苦恼许 ...

  7. 安卓知识体系搭建(持续更新)

    Java基础 日期操作类 [Android]DecimalFormat简单使用 Java语言编程规范--注释规范 Java内存分配之堆.栈和常量池 Java泛型详解 深入浅出Java中的增强 for ...

  8. 幻樱の安卓开发学习笔记(持续更新)

    安卓开发手册Java . 前言 . 本篇博客是我在开发过程中遇到的一些问题,我将这些问题记录了下来,以防踩重复的坑,希望对需要学习或者来看我踩坑的人有所帮助. . . . . 零.一些常用的依赖 1. ...

  9. Android 锁屏无法继续定位问题

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:我的梦z 链接:https://www.jianshu.com/p/956cbba64c53 声明:本文已获我的 ...

最新文章

  1. 排序算法7---快速排序算法
  2. object.create()
  3. 骚操作!用 CPU 烤肉,这位程序员做到了
  4. 电脑计算机内存不够怎么办,电脑内存不足怎么办 电脑内存不足怎么解决
  5. 如果有人再问你 Java 的反射,把这篇文章扔给他
  6. 查看cp进度,使用watch
  7. LeetCode刷题(13)
  8. uniapp 拍照 或者 相册 识别身份证信息
  9. c语言求布尔矩阵的乘积,离散数学 关系矩阵的布尔乘法的简便方法
  10. linux 好书推荐
  11. 2022年中南大学计算机考研复试内容是什么
  12. java 9宫格抽奖_九宫格抽奖
  13. 笔记本linux如何降低功耗,细说如何降低笔记本电脑功耗
  14. 解析大多数WordPress用户都选择托管虚拟主机的原因
  15. 【FXCG】落花有意随流水,流水无意恋落花
  16. 视频显示设备和光栅扫描系统
  17. layui做折线图_flask+layui+echarts实现前端动态图展示数据效果
  18. [大数据概念]-- 大数据的技术生态比喻
  19. 【DLL动态链接库】解决自己编写的程序在别人的电脑上无法运行的问题
  20. php微信支付结果通知接收,浅析PHP微信支付通知的处理方式

热门文章

  1. HTML5 新增的结构元素——能用不代表用对了
  2. Rtools 环境变量设置-windows
  3. python多维字典_python定义多维字典
  4. java jdbc 批量更新_java – JDBC PreparedStatement,批量更新和生成的密钥
  5. 用户行为分析(如何用数据驱动增长)-读书笔记1
  6. php apache win7,win7配置Apache24和PHP7.2.4开发环境
  7. 一篇文章通透理解序列号实现原理
  8. Google的60款开源项目
  9. [Unity][blender]在blender中新建标准两足人形骨骼模型动作导入到Unity中
  10. Java爬虫Jsoup的使用