(ST)自定义View - 玩转字体变色

1. 说明


前边我们学习了自定义View入门、自定义TextView、仿QQ运动步数效果,那么今天我们就来实现下这个效果 —— 玩转字体变色,效果图如下:


(ST)自定义View - 玩转字体变色_第1张图片
玩转字体变色.png

2. 思路


不能直接使用TextView来实现。因为系统提供的TextView只能够显示一种颜色,所以在这里需要自定义View;
自定义View该继承谁?
extends View:可以实现,但是需要我们手动去复写onMeasure()、onDraw()方法,比较麻烦;
extends TextView:可以实现,onMeasure()方法不需要实现,并且TextView自带有textSize()、textColor(),不需要我们自己去写自定义属性,可以减少一些逻辑,并且也可以减少代码量。

我们需要做的步骤就是:
1>:一个文字两种颜色,两个画笔去画;左边用红色画笔去画,右边用黑色画笔去画,需要切割;
2>:能够从左到右,从右到左;
3>:整合到ViewPager;

3. 代码如下


自定义ColorTrackTextView.java代码如下

/**
 * Email: [email protected]
 * Created by JackChen 2018/3/18 16:18
 * Version 1.0
 * Params:
 * Description:  玩转字体变色
*/
public class ColorTrackTextView extends TextView {
    // 1. 实现一个文字两种颜色 - 绘制不变色字体的画笔
    private Paint mOriginPaint;
    // 1. 实现一个文字两种颜色 - 绘制变色字体的画笔
    private Paint mChangePaint;
    // 1. 实现一个文字两种颜色 - 当前的进度
    private float mCurrentProgress = 0.0f;

    // 2.实现不同朝向
    private Direction mDirection = Direction.LEFT_TO_RIGHT;



    public enum Direction{
        LEFT_TO_RIGHT,RIGHT_TO_LEFT
    }


    public ColorTrackTextView(Context context) {
        this(context, null);
    }

    public ColorTrackTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ColorTrackTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint(context, attrs);
    }

    /**
     * 1.1 初始化画笔
     */
    private void initPaint(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);

        int originColor = array.getColor(R.styleable.ColorTrackTextView_originColor, getTextColors().getDefaultColor());
        int changeColor = array.getColor(R.styleable.ColorTrackTextView_changeColor, getTextColors().getDefaultColor());

        mOriginPaint = getPaintByColor(originColor);
        mChangePaint = getPaintByColor(changeColor);

        // 回收
        array.recycle();
    }

    /**
     * 1.根据颜色获取画笔
     */
    private Paint getPaintByColor(int color) {
        Paint paint = new Paint();
        // 设置颜色
        paint.setColor(color);
        // 设置抗锯齿
        paint.setAntiAlias(true);
        // 防抖动
        paint.setDither(true);
        // 设置字体的大小  就是TextView的字体大小
        paint.setTextSize(getTextSize());
        return paint;
    }

    // 1. 一个文字两种颜色
    // 利用clipRect的API 可以裁剪  左边用一个画笔去画  右边用另一个画笔去画  不断的改变中间值
    @Override
    protected void onDraw(Canvas canvas) {
        // 我们不要用系统的onDraw()方法来画,我们自己定义画文字的方法
        // super.onDraw(canvas);

        // 根据进度把中间值算出来
        int middle = (int) (mCurrentProgress * getWidth());

        // 从左变到右,左边是红色右边是黑色
        if(mDirection == Direction.LEFT_TO_RIGHT) {  //
            // 绘制变色
            drawText(canvas, mChangePaint , 0, middle);
            drawText(canvas, mOriginPaint, middle, getWidth());
        }else{
            // 右边是红色左边是黑色
            drawText(canvas, mChangePaint, getWidth()-middle, getWidth());
            // 绘制变色
            drawText(canvas, mOriginPaint, 0, getWidth()-middle);
        }
    }


    /**
     * 绘制Text
     * @param canvas
     * @param paint
     * @param start
     * @param end
     */
    private void drawText(Canvas canvas, Paint paint, int start, int end) {
        canvas.save();
        // 绘制不变色
        Rect rect = new Rect(start, 0, end, getHeight());
        canvas.clipRect(rect);  //裁剪区域


        /* 画文字的套路 */
        // 我们自己来画
        String text = getText().toString();
        Rect bounds = new Rect();
        paint.getTextBounds(text, 0, text.length(), bounds);

        /* 下边计算方法都是套路 */
        // 获取字体的宽度
        int x = getWidth() / 2 - bounds.width() / 2;

        Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
        // dy
        int dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;

        // 基线baseLine
        int baseLine = getHeight() / 2 + dy;
        canvas.drawText(text, x, baseLine, paint);
        canvas.restore();
    }

    public void setDirection(Direction direction){
        this.mDirection = direction;
    }

    public void setCurrentProgress(float currentProgress){
        this.mCurrentProgress = currentProgress;
        // 获取到当前进度后,不断的重绘
        invalidate();
    }

    public void setChangeColor(int changeColor) {
        this.mChangePaint.setColor(changeColor);
    }

    public void setOriginColor(int originColor) {
        this.mOriginPaint.setColor(originColor);
    }
}

ViewPagerActivity.java代码如下:

/**
 * Email: [email protected]
 * Created by JackChen 2018/3/18 17:07
 * Version 1.0
 * Params:
 * Description:   左右滑动的变色字体
*/
public class ViewPagerActivity extends AppCompatActivity {

    private String[] items = {"直播", "推荐", "视频", "图片", "段子", "精华"};
//    private LinearLayout mIndicatorContainer;// 变成通用的

    private List mIndicators ;
    private LinearLayout indicator_view;  // 变成通用的
    private ViewPager view_pager;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager);

        mIndicators = new ArrayList<>() ;
        // 顶部文字
        indicator_view = (LinearLayout) findViewById(R.id.indicator_view);
        view_pager = (ViewPager) findViewById(R.id.view_pager);

        // 初始化可变色的指示器
        initIndicator() ;
        initViewPager() ;
    }

    private void initViewPager() {
        view_pager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                return ItemFragment.newInstance(items[position]);
            }

            @Override
            public int getCount() {
                return items.length;
            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {

            }
        });

        view_pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {


            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // position: 代表当前位置  0、1、2
                // positionOffset: 代表滚动的百分比 值是 0-1、

                // 从左到右 滚动
                ColorTrackTextView left = mIndicators.get(position);
                left.setDirection(ColorTrackTextView.Direction.RIGHT_TO_LEFT);
                left.setCurrentProgress(1 - positionOffset);


                try {
                    // 从右到左 滚动
                    ColorTrackTextView right = mIndicators.get(position + 1);
                    right.setDirection(ColorTrackTextView.Direction.LEFT_TO_RIGHT);
                    right.setCurrentProgress(positionOffset);
                }catch (Exception e){

                }


            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

    }


    /**
     * 初始化可变色的指示器
     */
    private void initIndicator() {
        for (int i = 0; i < items.length; i++) {
            // 动态添加颜色跟踪的TextView
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            params.weight = 1;
            ColorTrackTextView colorTrackTextView = new ColorTrackTextView(this);
            // 设置颜色
            colorTrackTextView.setTextSize(20);
            colorTrackTextView.setChangeColor(Color.RED);
            colorTrackTextView.setText(items[i]);
            colorTrackTextView.setLayoutParams(params);
            // 把新的加入LinearLayout容器
            indicator_view.addView(colorTrackTextView);
            // 加入集合
            mIndicators.add(colorTrackTextView);
        }
    }
}

activity_View_pager.xml布局文件如下:




    

    

attrs.xml资源文件如下:



    
    

        
        
        
        
    

具体代码已上传至github:
https://github.com/shuai999/View_day04_2.git

你可能感兴趣的:((ST)自定义View - 玩转字体变色)