重学Android之View——TabLayoutMediator解析

这篇具有很好参考价值的文章主要介绍了重学Android之View——TabLayoutMediator解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

重学Android之View——TabLayoutMediator解析

1.前言

在使用TabLayout+ViewPager2+Fragment的时候,查询别人的使用例子,看到了

TabLayoutMediator这个类,撰写此文,仅当学习思考,本文是在引用material:1.7.0的版本基础上

2.测试效果

Tab + ViewPager2 + Fragment

重学Android之View——TabLayoutMediator解析

3.内部成员变量介绍

public final class TabLayoutMediator {
  @NonNull private final TabLayout tabLayout;
  @NonNull private final ViewPager2 viewPager;
  private final boolean autoRefresh;
  private final boolean smoothScroll;
  private final TabConfigurationStrategy tabConfigurationStrategy;
  @Nullable private RecyclerView.Adapter<?> adapter;
  private boolean attached;

  @Nullable private TabLayoutOnPageChangeCallback onPageChangeCallback;
  @Nullable private TabLayout.OnTabSelectedListener onTabSelectedListener;
  @Nullable private RecyclerView.AdapterDataObserver pagerAdapterObserver;
 ......

TabLayoutMediator类引用了tabLayout跟ViewPager2对象,另外内部定义定义了tabLayout跟Viewpager2的

监听回调类,还有adapter关于数据的监听类

4.TabLayoutOnPageChangeCallback

这个是viewPager2的监听类,主要目的是,在viewPager2发生页面变化的时候,去同步更新TabLaout的状态

,通过使用如下TabLaout的Api去更新tabLayout的状态

 tabLayout.selectTab()
 tabLayout.setScrollPosition()

并且通过如下方法,注册到viewPager的监听器中

viewPager.registerOnPageChangeCallback();

具体的ViewPager2.OnPageChangeCallback的监听类,在这里不仔细介绍

private static class TabLayoutOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
    @NonNull private final WeakReference<TabLayout> tabLayoutRef;
    private int previousScrollState;
    private int scrollState;

    TabLayoutOnPageChangeCallback(TabLayout tabLayout) {
      tabLayoutRef = new WeakReference<>(tabLayout);
      reset();
    }

    @Override
    public void onPageScrollStateChanged(final int state) {
      previousScrollState = scrollState;
      scrollState = state;
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
      TabLayout tabLayout = tabLayoutRef.get();
      if (tabLayout != null) {
        // Only update the text selection if we're not settling, or we are settling after
        // being dragged
        boolean updateText =
            scrollState != SCROLL_STATE_SETTLING || previousScrollState == 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 =
            !(scrollState == SCROLL_STATE_SETTLING && previousScrollState == SCROLL_STATE_IDLE);
        tabLayout.setScrollPosition(position, positionOffset, updateText, updateIndicator);
      }
    }

    @Override
    public void onPageSelected(final int position) {
      TabLayout tabLayout = tabLayoutRef.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 =
            scrollState == SCROLL_STATE_IDLE
                || (scrollState == SCROLL_STATE_SETTLING
                    && previousScrollState == SCROLL_STATE_IDLE);
        tabLayout.selectTab(tabLayout.getTabAt(position), updateIndicator);
      }
    }

    void reset() {
      previousScrollState = scrollState = SCROLL_STATE_IDLE;
    }
  }

5.ViewPagerOnTabSelectedListener

这个是TabLayout的监听类,主要目的是,在TabLayout发生页面变化的时候,去同步更新ViewPager2的状态

主要通过ViewPager2的Api,来更新状态viewPager2的状态

 viewPager.setCurrentItem

通过tabLayout的addOnTabSelectedListener 方法来添加监听

tabLayout.addOnTabSelectedListener()
  private static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
    private final ViewPager2 viewPager;
    private final boolean smoothScroll;

    ViewPagerOnTabSelectedListener(ViewPager2 viewPager, boolean smoothScroll) {
      this.viewPager = viewPager;
      this.smoothScroll = smoothScroll;
    }

    @Override
    public void onTabSelected(@NonNull TabLayout.Tab tab) {
      viewPager.setCurrentItem(tab.getPosition(), smoothScroll);
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
      // No-op
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
      // No-op
    }
  }

6.ViewPagerOnTabSelectedListener

通过viewPager2的适配器监听类来更新的tabLayout状态

private class PagerAdapterObserver extends RecyclerView.AdapterDataObserver {
    PagerAdapterObserver() {}

    @Override
    public void onChanged() {
      populateTabsFromPagerAdapter();
    }

    @Override
    public void onItemRangeChanged(int positionStart, int itemCount) {
      populateTabsFromPagerAdapter();
    }

    @Override
    public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
      populateTabsFromPagerAdapter();
    }

    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
      populateTabsFromPagerAdapter();
    }

    @Override
    public void onItemRangeRemoved(int positionStart, int itemCount) {
      populateTabsFromPagerAdapter();
    }

    @Override
    public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
      populateTabsFromPagerAdapter();
    }
  }

从上面的ViewPager2的适配器监听 ,收到数据的变化,就去更新tabLayout 状态,调用populateTabsFromPagerAdapter 函数

主要是根据数据的条目,更新tab的数量,然后,添加到tabLayout 中,注意,在这里通过接口回调的方式,回调了onConfigureTab方法,

调用者,就能够得到里面的tab的相关信息

@SuppressWarnings("WeakerAccess")
  void populateTabsFromPagerAdapter() {
    tabLayout.removeAllTabs();

    if (adapter != null) {
      int adapterCount = adapter.getItemCount();
      for (int i = 0; i < adapterCount; i++) {
        TabLayout.Tab tab = tabLayout.newTab();
        tabConfigurationStrategy.onConfigureTab(tab, i);
        tabLayout.addTab(tab, false);
      }
      // Make sure we reflect the currently set ViewPager item
      if (adapterCount > 0) {
        int lastItem = tabLayout.getTabCount() - 1;
        int currItem = Math.min(viewPager.getCurrentItem(), lastItem);
        if (currItem != tabLayout.getSelectedTabPosition()) {
          tabLayout.selectTab(tabLayout.getTabAt(currItem));
        }
      }
    }
  }

7.结合ViewPager2跟TabLayout

在这里去注册viewPager2跟Tablayout的各种监听,以及去初始化填充文章来源地址https://www.toymoban.com/news/detail-423958.html

public void attach() {
    if (attached) {
      throw new IllegalStateException("TabLayoutMediator is already attached");
    }
    adapter = viewPager.getAdapter();
    if (adapter == null) {
      throw new IllegalStateException(
          "TabLayoutMediator attached before ViewPager2 has an " + "adapter");
    }
    attached = true;

    // Add our custom OnPageChangeCallback to the ViewPager
    onPageChangeCallback = new TabLayoutOnPageChangeCallback(tabLayout);
    viewPager.registerOnPageChangeCallback(onPageChangeCallback);

    // Now we'll add a tab selected listener to set ViewPager's current item
    onTabSelectedListener = new ViewPagerOnTabSelectedListener(viewPager, smoothScroll);
    tabLayout.addOnTabSelectedListener(onTabSelectedListener);

    // Now we'll populate ourselves from the pager adapter, adding an observer if
    // autoRefresh is enabled
    if (autoRefresh) {
      // Register our observer on the new adapter
      pagerAdapterObserver = new PagerAdapterObserver();
      adapter.registerAdapterDataObserver(pagerAdapterObserver);
    }

    populateTabsFromPagerAdapter();

    // Now update the scroll position to match the ViewPager's current item
    tabLayout.setScrollPosition(viewPager.getCurrentItem(), 0f, tru

8.外界使用TabLayoutMediator的简单调用事例

adapter = new ViewPagerFragmentAdapter(this, labels);
        viewPager2.setAdapter(adapter);

        TabLayoutMediator mediator = new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                tab.setText(labels[position]);
            }
        });
        viewPager2.setCurrentItem(2, false);
        mediator.attach();

到了这里,关于重学Android之View——TabLayoutMediator解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android View动画整理

    View 动画相关内容可参考官网 动画资源 此前也有写 View 动画相关的内容,但都只是记录代码,没有特别分析。以此篇作为汇总、整理、分析。 Android View 动画有4中,分别是 平移动画 TranslateAnimation 缩放动画 ScaleAnimation 旋转动画 RotateAnimation 透明度动画 AlphaAnimation View 动画可以

    2024年02月11日
    浏览(46)
  • 【Android】之【View绘制】

    简单的可以说,如 measure,layout,draw 分别对应测量,布局,绘制三个过程。 ① measure:测量。系统会先根据xml布局文件和代码中对控件属性的设置,来获取或者计算出每个View和ViewGrop的尺寸,并将这些尺寸保存下来。 ② layout:布局。根据测量出的结果以及对应的参数,来确

    2024年02月08日
    浏览(36)
  • Android自定义View流程

    在开发中,View视图具有非常重要的作用,它是直接呈现给使用者的,因此向用户展示精美高效的View视图很有意义。Android系统提供了丰富的视图组件,如TextView、ImageView、Button等,还提供了RelativeLayout、LinearLayout、FrameLayout等组合组件,使用这些组件搭配能实现良好的视图效果

    2024年04月11日
    浏览(49)
  • Android View滑动处理大法

    原文链接 Android View滑动处理大法 对于触控式操作来说,滑动是一个特别重要的手势操作,如何做到让应用程序的页面滑动起来如丝般顺滑,让用户感觉到手起刀落的流畅感,是开发人猿需要重点解决的问题,这对提升用户体验是最为重要的事情。本文就将探讨一下,Android中

    2024年02月13日
    浏览(37)
  • android 自定义圆角View

    public class CustomView extends View {     private float cornerRadius;     public CustomView(Context context) {         super(context);         init();     }     public CustomView(Context context, AttributeSet attrs) {         super(context, attrs);         TypedArray typedArray = context.obt

    2024年02月11日
    浏览(49)
  • android开发之Android 自定义滑动解锁View

    自定义滑动解锁View 需求如下: 近期需要做一个类似屏幕滑动解锁的功能,右划开始,左划暂停。 需求效果图如下 实现效果展示 自定义view如下 /** Desc 自定义滑动解锁View Author ZY Mail sunnyfor98@gmail.com Date 2021/5/17 11:52 */ @SuppressLint(“ClickableViewAccessibility”) class SlideSwitchButton :

    2024年02月13日
    浏览(37)
  • Android View实现滑动的方式

    实现View的滑动有三种方式 通过View本身提供的scrollTo/scrollBy方法实现滑动 通过动画给View施加平移效果来实现滑动 通过改变View LayoutParams使得View重新布局从而实现滑动 scrollTo:通过传递的参数实现绝对滑动 scrollBy:通过传递的参数实现相对滑动 scrollTo和scrollBy只能改变View内容

    2024年02月16日
    浏览(50)
  • Android 遍历界面所有的View

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 我们继续总结学习,温故知新。 本文讲述如何遍历获取页面中所有的view,并输出对应的id,textview文

    2024年02月08日
    浏览(32)
  • Android 动态控制view的大小

    这样就实现了控件尺寸随着我们手指滑动变化了。 OnTouchListener中有event.getX(),event.getY(),和event.getRawX(),event.getRawY(),他们究竟有什么区别了? getX和getY代表相当于控件本身的位置,getRawX和getRawY相对屏幕的位置

    2023年04月08日
    浏览(103)
  • Android动画深入分析(View动画)

    Android的动画我其实在View的滑动里面写过,主要还是分为2点。 一个就是View动画,还有一个是属性动画 先讲述 View动画 View动画主要分为4种, 平移动画 , 缩放动画 , 旋转动画 , 透明度动画 。 还有一个叫 帧动画 ,但是表现方式和上面4种不太一样 一般情况下我们是在xml里面定义动

    2024年02月07日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包