一,内部类及分析其关系:
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
//