自定义ViewPager的Tab指示器

    先看示例效果图:

    自定义View的核心为上半部分的指示器,该需求为的是实现等级列表的展示:每个ViewPager指向一个等级,当滑动到一个ViewPager时其指示的圆点变大,用户所达到的等级用黄色的线画圆点,未达到的等级则用白色来表示。

    下面考虑具体实现:指示器布局包含在一个宽度很长的线性布局中,然后就是画所有的线和圆点(注意线长度最好根据屏幕宽度和布局左边的margin综合计算得到,以保证除第二个圆点在屏幕水平居中的位置),接着根据传入的数据重新画选中部分的黄色的线和圆点以及对应的文字,最后根据当前选中的ViewPager加粗对应的圆点。详细代码如下:

    @Override
    protected void onDraw(Canvas canvas) {
        //底线
        rectF.left = startX;
        rectF.top = startY - lineHeight / 2;
        rectF.right = startX + lineLength * (number - 1);
        rectF.bottom = startY + lineHeight / 2;

        mPaint.setColor(lineDefColor);
        canvas.drawRect(rectF, mPaint);

        //选中线
        if(curPage - curCircle == 1){                                     //展示最后的不满一级的进度时以去掉两端半圆的中间矩形的长度为进度条的总长度计算
            rectF.right = startX + lineLength * curCircle + circleRadius + (lineLength - circleRadius * (MULTIPLE_RADIUS + 1)) * curPercent;
        }else {
            rectF.right = startX + lineLength * curCircle + circleRadius + (lineLength - circleRadius * 2) * curPercent;
        }
        mPaint.setColor(lineSelColor);
        canvas.drawRect(rectF, mPaint);

        //画圆点和圆点下方的字
        mFirstTextPaint.setColor(firstTextColor);
        mSecondTextPaint.setColor(secondTextColor);
        for(int i = 0; i < number; i++){
            if(i <= curCircle){ //达到等级的圆点
                mPaint.setColor(circleSelColor);
                canvas.drawCircle(startX + i * lineLength, startY, circleRadius, mPaint);
            }else { //未达到等级的圆点
                mPaint.setColor(circleDefColor);
                canvas.drawCircle(startX + i * lineLength, startY, circleRadius, mPaint);
            }
            //字
            //first Text
            textRectF.left = startX + i * lineLength - 2 * circleDiameter;
            textRectF.top = startY + circleDiameter;
            textRectF.right = startX + i * lineLength - 2 * circleDiameter + textLength;
            textRectF.bottom = startY + circleDiameter + circleRadius;
            canvas.drawRect(textRectF, mTranPaint);
            mFirstTextPaint.setTextSize(firstTextSize);
            if(firstStrings != null && i < firstStrings.length){
                //坐标:左下角
                canvas.drawText(firstStrings[i], textRectF.left, textRectF.bottom, mFirstTextPaint);
            }

            //second Text
            textRectF.left = startX + i * lineLength - circleDiameter - circleRadius * 1.1f;
            textRectF.top = startY + 2 * circleDiameter;
            textRectF.right = startX + i * lineLength - circleDiameter - circleRadius * 1.1f + textLength;
            textRectF.bottom = startY + 2 * circleDiameter + circleRadius;
            canvas.drawRect(textRectF, mTranPaint);
            mSecondTextPaint.setTextSize(secondTextSize);
            if (secondStrings != null && i < secondStrings.length) {
                //坐标:左下角
                canvas.drawText(secondStrings[i], textRectF.left, textRectF.bottom, mSecondTextPaint);
            }

            if(i == curPage){
                //选中圆点-->加大
                if(curPage > curCircle){
                    mPaint.setColor(circleDefColor);
                }else{
                    mPaint.setColor(circleSelColor);
                }
                canvas.drawCircle(startX + i * lineLength, startY, circleRadius * MULTIPLE_RADIUS, mPaint);
            }
        }
    }

    ViewPager用线性布局包含,注意两者都需要声明 android:clipChildren的属性为false,以允许ViewPager超出父控件来展示,布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:background="@color/colorPrimary"
    android:orientation="vertical"
    tools:context="com.sty.viewpager.tab.MainActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:clipChildren="false">

        <LinearLayout
            android:id="@+id/ll_level_bar"
            android:layout_width="10000dp"
            android:layout_height="0dp"
            android:layout_weight="1.3"
            android:orientation="vertical">
            <com.sty.viewpager.tab.view.CustomTabSliding
                android:id="@+id/cts_level_bar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:circleDefColor="@android:color/white"
                app:circleSelColor="#FFDF25"
                app:lineDefColor="#89D19B"
                app:lineSelColor="#FFDF25"
                app:firstTextColor="#FFDF25"
                app:secondTextColor="@android:color/white"
                app:firstTextSize="12sp"
                app:secondTextSize="12sp"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_view_pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="6"
            android:orientation="vertical"
            android:clipChildren="false">
            <android.support.v4.view.ViewPager
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginLeft="32dp"
                android:layout_marginRight="32dp"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="16dp"
                android:clipChildren="false" />
        </LinearLayout>

    </LinearLayout>
</LinearLayout>

    当ViewPager滑动时,给自定义View设置一个属性动画移动相应的距离,然后刷新布局:

    private void startAnimator(int movePage){
        float curTranslationX = ctsLevelBar.getTranslationX();
        final ObjectAnimator animator = ObjectAnimator.ofFloat(ctsLevelBar, "translationX",
                curTranslationX, curTranslationX - movePage * ctsLevelBar.getLineLength());
        animator.setDuration(150);
        animator.start();
    }

    源码传送门:https://github.com/tianyalu/ViewPagerTabSliding

    如果喜欢的话欢迎给个star。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值