= COUNT_DEFAULT_TAB;
? a.recycle();
? // 初始化画笔
? mPaint = new Paint();
? mPaint.setAntiAlias(true);
? mPaint.setColor(Color.parseColor("#ffffffff"));
? mPaint.setStyle(Style.FILL);
? mPaint.setPathEffect(new CornerPathEffect(3));
?}
看起来成员变量挺多的,其实主要就几类:?
最前面的6个都是和绘制那个三角形相关的,画笔决定了三角形的样式(颜色等),Path用于构造这个三角形(其实就是3条线的封闭合),然后就是三角形的宽度什么的。
接下来的两个:都带Translation,肯定是和三角形的位置相关的了~
剩下的就是Tab内容、数量神马的~~
看看我们构造方法里面:获得了自定义属性,即可见的Tab的数量,初始化了我们的画笔,这里设置了setPathEffect,就是为了画的线的连接处,有点圆角~~
我们的一些初始化工作,会在这两个方法里面做~~尺寸相关的,会在onSizeChanged回调里面进行设置~
/**
? * 设置布局中view的一些必要属性;如果设置了setTabTitles,布局中view则无效
? */
?@Override
?protected void onFinishInflate()
?{
? Log.e("TAG", "onFinishInflate");
? super.onFinishInflate();
? int cCount = getChildCount();
? if (cCount == 0)
? ?return;
? for (int i = 0; i < cCount; i++)
? {
? ?View view = getChildAt(i);
? ?LinearLayout.LayoutParams lp = (LayoutParams) view
? ? ?.getLayoutParams();
? ?lp.weight = 0;
? ?lp.width = getScreenWidth() / mTabVisibleCount;
? ?view.setLayoutParams(lp);
? }
? // 设置点击事件
? setItemClickEvent();
?}
这个其实是获取在布局文件中直接写好Tab的~~如果你在这写好了,就不需要去调用mIndicator.setTabItemTitles(mDatas);了~~?
大家可以下载文末的代码后,把mIndicator.setTabItemTitles(mDatas);这行代码注释进行测试~~不过注意下定义的Tab和ViewPager的页面数量最好一致。
代码很简单,就是获取ChildView,然后显示的重置一个宽度为getScreenWidth() / mTabVisibleCount;接下来设置一下点击事件。
/**
? * 设置点击事件
? */
?public void setItemClickEvent()
?{
? int cCount = getChildCount();
? for (int i = 0; i < cCount; i++)
? {
? ?final int j = i;
? ?View view = getChildAt(i);
? ?view.setOnClickListener(new OnClickListener()
? ?{
? ? @Override
? ? public void onClick(View v)
? ? {
? ? ?mViewPager.setCurrentItem(j);
? ? }
? ?});
? }
?}
这个就更简单了~~就是mViewPager.setCurrentItem(j);?
下面看看onSizeChanged
/**
? * 初始化三角形的宽度
? */
?@Override
?protected void onSizeChanged(int w, int h, int oldw, int oldh)
?{
? super.onSizeChanged(w, h, oldw, oldh);
? mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGEL);// 1/6 of
? ? ? ? ? ? ? ? ? // width
? mTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth);
? // 初始化三角形
? initTriangle();
? // 初始时的偏移量
? mInitTranslationX = getWidth() / mTabVisibleCount / 2 - mTriangleWidth
? ? / 2;
?}
?
?/**
? * 初始化三角形指示器
? */
?private void initTriangle()
?{
? mPath = new Path();
? mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2));
? mPath.moveTo(0, 0);
? mPath.lineTo(mTriangleWidth, 0);
? mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);
? mPath.close();
?}
onSizeChanged,我们主要是确定三角形的宽度和Path去构造这个三角形。
默认的我们的三角形的底边的宽度为,每个Tab宽度的1/6;当然有个上限是?(int) (getScreenWidth() / 3 * RADIO_TRIANGEL);【RADIO_TRIANGEL = 1.0f / 6】
这个其实无所谓,主要为了屏幕适配,你可以抽取为自定义属性让用户去设置;
initTriangle()中用Path去构造了一个三角形,这个很简单了~~
这里还初始化了mInitTranslationX,因为一开始显示的就在第一个Tab的中间位置。
三角形初始化完成了,是不是应该去看看它在哪进行绘制的~~
?/**
? * 绘制指示器
? */
?@Override
?protected void dispatchDraw(Canvas canvas)
?{
? canvas.save();
? // 画笔平移到正确的位置
? canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1);
? canvas.drawPath(mPath, mPaint);
? canvas.restore();
? super.dispatchDraw(canvas);
?}
在绘制子View之前,我们先绘制我们的三角形指示器~~?
可以看到,我们通过canvas.translate移动画布,来把指示器画到了指定的位置~~当然了,记得save和restore.
看到,我们这里还有个mTranslationX,这个是动态变化的,后面会介绍~~?
三角形绘制完成了,应该到了,跟随ViewPager移动了把~~当然了,这里肯定得先绑定ViewPager,不然怎么跟随
?// 设置关联的ViewPager
?public void setViewPager(ViewPager mViewPager, int pos)
?{
? this.mViewPager = mViewPager;
? mViewPager.setOnPageChangeListener(new OnPageChangeListener()
? {
? ?@Override
? ?public