需求分析

1.一行文字显示两种颜色
2.颜色变化可以从右到左或者从左到右
3.能够随着view pager切换
思路:
a.继承View:需要重写onMeasure onDraw方法
b.继承Text View 不需要重写onMeasure方法 只要重写onDraw方法
需要定义字体变化的颜色

效果

自定义属性

<?xml version="1.0" encoding="utf-8"?>
<resources><!-- step1 定义组定义属性 --><declare-styleable name="MultiColorTextView"><attr name="originColor" format="color"/><attr name="changeColor" format="color"/></declare-styleable>
</resources>

在xml中使用自定义属性

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:chjApp="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:padding="16dp"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><com.example.chj.muticolortextview.MultiColorTextViewandroid:id="@+id/multi_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#ccc"chjApp:originColor="#000"chjApp:changeColor="@color/colorAccent"android:textSize="20sp"android:text="Hello World!"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="leftToRight"android:onClick="leftToRight"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="rightToLeft"android:onClick="rightToLeft"/></LinearLayout>

编写自定义view

package com.example.chj.muticolortextview;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.TextView;@SuppressLint("AppCompatCustomView")
public class MultiColorTextView extends TextView {private Paint mOriginPaint;private Paint mChangePaint;//绘制进度private float mCurrentProgress = 0.0f;//绘制方向private Direction mCurrentDirection = Direction.LEFT_TO_RIGHT;public enum Direction {RIGHT_TO_LEFT, LEFT_TO_RIGHT}public MultiColorTextView(Context context) {this(context, null);}public MultiColorTextView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public MultiColorTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initPaint(context, attrs);}//1.1读取xml的自定义属性 初始化画笔private void initPaint(Context context, AttributeSet attrs) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MultiColorTextView);int originPaintColor = array.getColor(R.styleable.MultiColorTextView_originColor, Color.GREEN);int changePaintColor = array.getColor(R.styleable.MultiColorTextView_changeColor, Color.GREEN);mOriginPaint = getPaintByColor(originPaintColor);mChangePaint = getPaintByColor(changePaintColor);array.recycle();}private Paint getPaintByColor(int originPaintColor) {Paint paint = new Paint();paint.setAntiAlias(true);//抗锯齿paint.setTextSize(getTextSize());//获取父类TextView定义的textSizepaint.setDither(true);//防抖动paint.setColor(originPaintColor);return paint;}//2 实现一行文字两种颜色 思路 利用canvas.clipRect的api 不断裁切 坐标用一个画笔绘制 右边是另一个画笔绘制@Overrideprotected void onDraw(Canvas canvas) {//不要使用TextView的onDraw方法//super.onDraw(canvas);//根据mCurrentProgress 计算两个画笔绘制的临界点int middle = (int) (getWidth() * mCurrentProgress);//        //抽成方法start
//        //裁切区域 保留以下区域
//        //canvas.clipRect(0,0,80,getHeight());
//        canvas.save();
//        Rect rect = new Rect(0, 0, middle, getHeight());//裁剪区域 只绘制0-middle 左半区域
//        canvas.clipRect(rect);
//
//        //获取文字 计算位置 绘制文字
//        String text = getText().toString();
//        //获取text宽度
//        Rect bounds = new Rect();
//        mOriginPaint.getTextBounds(text, 0, text.length(), bounds);
//        //计算绘制origin的x坐标
//        int originStartX = (getWidth() - bounds.width()) / 2;
//
//        //计算绘制origin的y坐标(baseline)
//        Paint.FontMetrics fontMetrics = mOriginPaint.getFontMetrics();
//        float baseline = (getHeight()-fontMetrics.top-fontMetrics.bottom) / 2;
//        canvas.drawText(text, originStartX, baseline, mOriginPaint);
//        canvas.restore();//canvas.save();保存画布  canvas.restore();释放画布 如果不调用 无法进行再次裁切 他们成对调用
//
//        canvas.save();
//        rect = new Rect(middle, 0, getWidth(), getHeight());//裁剪区域 只绘制middle-getWidth 右半区域
//        canvas.clipRect(rect);
//        canvas.drawText(text, originStartX, baseline, mChangePaint);
//        canvas.restore();
//        //抽成方法end//将绘制左边和绘制右边的部分抽成一个方法 调用两次 与上面注释部分等价if (Direction.LEFT_TO_RIGHT == mCurrentDirection) {clipRectThenDrawText(canvas, mChangePaint, 0, middle);//只绘制0-middle 左半区域clipRectThenDrawText(canvas, mOriginPaint, middle, getWidth());//裁剪区域 只绘制middle-getWidth 右半区域} else {clipRectThenDrawText(canvas, mChangePaint, getWidth()-middle, getWidth());//只绘制右区域clipRectThenDrawText(canvas, mOriginPaint, 0, getWidth()-middle);//裁剪区域 只绘制左半区域}}private void clipRectThenDrawText(Canvas canvas, Paint paint, int startClip, int endClip) {canvas.save();Rect rect = new Rect(startClip, 0, endClip, getHeight());//裁剪区域 只绘制这个区域canvas.clipRect(rect);//获取文字 计算位置 绘制文字String text = getText().toString();//获取text宽度Rect bounds = new Rect();paint.getTextBounds(text, 0, text.length(), bounds);//计算绘制origin的x坐标int originStartX = (getWidth() - bounds.width()) / 2;//计算绘制origin的y坐标(baseline)Paint.FontMetrics fontMetrics = paint.getFontMetrics();float baseline = (getHeight() - fontMetrics.top - fontMetrics.bottom) / 2;canvas.drawText(text, originStartX, baseline, paint);canvas.restore();//canvas.save();保存画布  canvas.restore();释放画布 如果不调用 无法进行再次裁切 他们成对调用}public void setCurrentProgress(float mCurrentProgress) {this.mCurrentProgress = mCurrentProgress;invalidate();}public void setCurrentDirection(Direction direction) {this.mCurrentDirection = direction;}
}

编写测试代码

package com.example.chj.muticolortextview;import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;public class MainActivity extends AppCompatActivity {private MultiColorTextView multiColorTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);multiColorTextView = findViewById(R.id.multi_tv);}public void leftToRight(View view) {multiColorTextView.setCurrentDirection(MultiColorTextView.Direction.LEFT_TO_RIGHT);ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,1);valueAnimator.setDuration(2000);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float mCurrentProgress = (float) animation.getAnimatedValue();multiColorTextView.setCurrentProgress(mCurrentProgress);}});valueAnimator.start();}public void rightToLeft(View view) {multiColorTextView.setCurrentDirection(MultiColorTextView.Direction.RIGHT_TO_LEFT);ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,1);valueAnimator.setDuration(2000);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float mCurrentProgress = (float) animation.getAnimatedValue();multiColorTextView.setCurrentProgress(mCurrentProgress);}});valueAnimator.start();}
}

源码:
https://github.com/caihuijian/learn_darren_android.git

红橙Darren视频笔记 一个控件显示两种颜色的文字 画笔的使用相关推荐

  1. 红橙Darren视频笔记 任意控件实现拖动消失爆炸效果

    效果 注意 本节内容基于上一篇博客的代码继续编写code https://blog.csdn.net/u011109881/article/details/112427623 本节知识点 1.如何创建 ...

  2. 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27

    本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...

  3. 红橙Darren视频笔记 UML图简介

    整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...

  4. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  5. 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站

    第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...

  6. 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复

    注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...

  7. 红橙Darren视频笔记 仿QQ侧滑效果

    这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...

  8. 红橙Darren视频笔记 Behavior的工作原理源码分析

    主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...

  9. excel日历弄到html,Excel中进行添加日历控件的两种方法

    有时我们在运用Excel表格的时候会运用到日历的控件,可是小伙伴们却不知道在哪里添加.那么我们来看一下,它到底躲藏在哪里,又该怎么添加呢?今天,学习啦小编就教大家在Excel中进行添加日历控件的两种方 ...

最新文章

  1. Cisco交换机路由器的部分命令解析(3)
  2. torch动态学习率代码
  3. QML识别模块identifiedmodules
  4. 计算机网络-思维导图(1)概述
  5. 11.17 模拟:总结
  6. Hadoop64位版本安装后遇到的警告处理
  7. 多个if和一个ifelse的区别
  8. 堆排序——top k问题
  9. 【机器学习】Logistic Regression逻辑回归原理与java实现
  10. 基于Cocos2d-x开发guardCarrot--1 《保卫萝卜》简介
  11. 安防的未来五年 如何把握机遇深耕市场?
  12. 【EVE模拟器是干什么的】
  13. android 程序界面美化,Android ROM定制——界面美化基础(framework-res、SystemUI修改)...
  14. 分享几个特别好用且免费的图片/视频/gif/mp3压缩网站
  15. java随机生成名字_java随机生成一个名字和对应拼音的方法
  16. 钢笔墨水能否代替打印机墨水_打印机墨水怎么分类?
  17. 简单的python爬取淘宝数据
  18. centos7根分区扩容(适用目前主流版本)
  19. visual studio2017登录时需要更新 microsoft edge 或当前浏览器的最新版本
  20. 5G NR - RLC协议阅读笔记 - 从LTE到NR的变化

热门文章

  1. django 允许跨域请求
  2. SQL数据库相关 FMDB框架的使用
  3. The use specified as definer('root'@'%') does not exist的解决办法
  4. 开源web应用防火墙 - Naxsi
  5. 卸掉IE8,降级使用
  6. asp.net中的加密方法
  7. centos在文本中搜索字符串_linux(centos8):用grep命令查找文件内容
  8. 北大OJ(POJ 3237)鸡兔同笼
  9. PAT乙级(1009 说反话)
  10. idea ssm框架 mysql_IDEA 2017 整合SSM框架(使用Maven创建工程)