读源码:TabLayout

一,内部类及分析其关系:

这里写图片描述
Tab类和TabView类和SlidingTabStrip类为TabLayout提供了三个基本的元素。
TabLayoutOnPageChangeListener和ViewPagerOnTabSelectedListener实现了ViewPager类的两个接口,作用是监听ViewPager页面改变和Tab选中状态。
PagerAdapterObserver为观察者监控PagerAdapter数据变化。
所以在自定义TabLayout前,先设计好Tab模式,并且官方扩展了一个TabView子控件件。
自定义TabLayout的工作,还要通过接口完成和ViewPager的交互,通过PagerAdapterObserver,确保TabLayout能够正常工作。

二,内部类:Tab模型

Tab内部类定义了Tab的成员变量,并set和get方法,然后又封装了Tab的属性设置方法,如:

 @NonNull
        public Tab setIcon(@Nullable Drawable icon) {
            mIcon = icon;
            if (mPosition >= 0) {
                mParent.updateTab(mPosition);
            }
            return this;
        }

        /**
         * Set the icon displayed on this tab.
         *
         * @param resId A resource ID referring to the icon that should be displayed
         * @return The current instance for call chaining
         */
        @NonNull
        public Tab setIcon(@DrawableRes int resId) {
            return setIcon(AppCompatDrawableManager.get().getDrawable(mParent.getContext(), resId));
        }

三,内部类:自定义的TabView

这个子view在应用中很方便,经常用到,设计它的作用是让Tab同时显示文字和图片,继承自LinearLayout。
其构造器设置了TabView在TabLayout中的状态,这些状态属性都是固定的不可变的,所以也决定TabView设置受到限制。

public TabView(Context context) {
            super(context);
            if (mTabBackgroundResId != 0) {
setBackgroundDrawable(AppCompatDrawableManager.get().getDrawable(context, mTabBackgroundResId));//设置背景
            }
            ViewCompat.setPaddingRelative(this, mTabPaddingStart, mTabPaddingTop,mTabPaddingEnd, mTabPaddingBottom);//设置边距
            setGravity(Gravity.CENTER);//设置位置
            setOrientation(VERTICAL);//设置方向
        }

四,SlidingTabStrip:Tab下面的滑线

这个自定义view SlidingTabStrip是私有内部类,它继承自LinearLayout,作用为获取tab的最宽宽度,设置SlidingTabStrip的宽度,并设置一个动画,随着tab的改变绘制SlidingTabStrip。它有一个构造器:

SlidingTabStrip(Context context) {
            super(context);
            setWillNotDraw(false);//重写draw()不起作用时,需要添加这么一句
            mSelectedIndicatorPaint = new Paint();
        }

单看这个构造器就知道使用SlidingTabStrip超级简单,在这个构造器源码中,有一个地方需要注意,因为在我们自定义view中会用到,就是setWillNotDraw(false);但看这句的字面意思就不难猜到,双重否定等于肯定,让它进行绘制。当我们自定义的view在onDrow()不起作用时,一种方法是在构造器里设置背景颜色,一种就是添加这句语句。原因可以进一步参考ViewGroup为什么不会调用onDraw
代码结构极易一目了然。在onMeasure()获取最宽tab宽度,并设置为此控件的宽度;在onLayout()进行动画并更新Indicator位置;最后draw()。

五,ViewPager的监听器:TabLayoutOnPageChangeListener

这个类是实现ViewPager.OnPageChangeListener的一个内部类,作用是监听到ViewPager页面改变的时候,更新tab和Indicator。首先注意这个类是public,并且被static修饰,static一般用来修饰成员变量或或成员函数,有static修饰内部类有什么特别呢,那就是在外面使用这个类的时候,不需要先new内部类所在的类(如在这里为TabLayout)的实例,可以直接new这个内部类的实例,比如:

TabLayout.TabLayoutOnPageChangeListener listener=new TabLayout.TabLayoutOnPageChangeListener;

如果想进一步了解可以查看用static关键字修饰类
其它没啥可解释的,方便理解,贴出主要的代码块:

 @Override
        public void onPageScrolled(int position, float positionOffset,
                int positionOffsetPixels) {
            final TabLayout tabLayout = mTabLayoutRef.get();
            if (tabLayout != null) {
                // 只更新选中的 text  if we're not settling, or we are settling after
                //
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值