Android自定义View之文本变色

2024-05-12 10:48

本文主要是介绍Android自定义View之文本变色,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • 1. 概述
        • 1.1 缘由
        • 1.2 效果图
      • 2. 开撸
        • 2.1 分析
        • 2.2 自定义属性
        • 2.3 编写View
        • 2.4 测试
      • 3. 小结

1. 概述

1.1 缘由

在项目中,经常会遇到文字色值渐变效果,比如在ViewPage中的页面指示器,这种实现起来也比较简单,无非是计算偏移量、使用Paint以及Canvas提供的方法即可。

1.2 效果图

在这里插入图片描述

2. 开撸

2.1 分析

该文本有两种颜色,一种默认颜色,一种为要改变的颜色,因此需要两只画笔,根据偏移量,计算对应起始点、结束点使用相应画笔即可。

2.2 自定义属性

在这里,只简单定义三个属性

<declare-styleable name="ColorTrackTextView"><attr name="originColor" format="color" /><attr name="changeColor" format="color" /><attr name="direction" format="enum"><enum name="left2Right" value="1" /><enum name="right2Left" value="2" /></attr>
</declare-styleable>
2.3 编写View

根据分析,继承 TextView,重写onDraw方法即可。
详细注释见代码。

public class ColorTrackTextView extends TextView {private Paint mOriginPaint;private Paint mChangePaint;private float mProgress = 0.0f;private int mStartX = Integer.MIN_VALUE;private float mBaseLine = Float.MAX_VALUE;private Direction mDirection = Direction.LEFT2RIGHT;public ColorTrackTextView(Context context) {this(context, null);}public ColorTrackTextView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public ColorTrackTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initPaint(context, attrs);}private void initPaint(Context context, AttributeSet attrs) {TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorTrackTextView);int originColor = typedArray.getColor(R.styleable.ColorTrackTextView_originColor, getTextColors().getDefaultColor());int changeColor = typedArray.getColor(R.styleable.ColorTrackTextView_changeColor, getTextColors().getDefaultColor());int index = typedArray.getInt(R.styleable.ColorTrackTextView_direction, -1);if (index >= 1) {setDirection(index);}mOriginPaint = getPaintByColor(originColor);mChangePaint = getPaintByColor(changeColor);typedArray.recycle();}private Paint getPaintByColor(int color) {Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(color);paint.setDither(true);paint.setTextSize(getTextSize());return paint;}@Overrideprotected void onDraw(Canvas canvas) {int middle = (int) (mProgress * getWidth());// 从左到右if (mDirection == Direction.LEFT2RIGHT) {// 绘制变色区域drawText(canvas, mChangePaint, 0, middle);// 绘制不变色区域drawText(canvas, mOriginPaint, middle, getWidth());} else {// 从右到左// 绘制变色区域drawText(canvas, mChangePaint, getWidth() - middle, getWidth());// 绘制不变色区域drawText(canvas, mOriginPaint, 0, getWidth() - middle);}}/*** 绘制文本** @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);canvas.drawText(getText().toString(), getStartX(paint), getBaseLine(paint), paint);canvas.restore();}/*** 计算文字开始X坐标** @param paint* @return*/private int getStartX(Paint paint) {if (mStartX != Integer.MIN_VALUE) return mStartX;String text = getText().toString();Rect bounds = new Rect();paint.getTextBounds(text, 0, text.length(), bounds);mStartX = (getWidth() - bounds.width()) / 2;return mStartX;}/*** 计算baseLine** @param paint* @return*/private float getBaseLine(Paint paint) {if (mBaseLine != Float.MAX_VALUE) return mBaseLine;Paint.FontMetrics fontMetrics = paint.getFontMetrics();float dy = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;mBaseLine = getHeight() / 2 + dy;return mBaseLine;}public void setDirection(Direction direction) {this.mDirection = direction;}public synchronized void setProgress(float progress) {if (progress < 0) {throw new IllegalArgumentException("进度不能小于0哦");}this.mProgress = progress;invalidate();}private void setDirection(int index) {if (index == 1) {mDirection = Direction.LEFT2RIGHT;} else if (index == 2) {mDirection = Direction.RIGHT2LEFT;}}public enum Direction {LEFT2RIGHT, RIGHT2LEFT}
}    
2.4 测试

验证下效果吧

测试Activity

class ColorTrackActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_color_track)}fun left2Right(view: View) {cttv_content.setDirection(ColorTrackTextView.Direction.LEFT2RIGHT)val anim = ObjectAnimator.ofFloat(0.0f, 1.0f)anim.duration = 5000anim.addUpdateListener { animation ->val progress = animation.animatedValue as Floatcttv_content.setProgress(progress)}anim.start()}fun right2Left(view: View) {cttv_content.setDirection(ColorTrackTextView.Direction.RIGHT2LEFT)val anim = ObjectAnimator.ofFloat(0.0f, 1.0f)anim.duration = 5000anim.addUpdateListener { animation ->val progress = animation.animatedValue as Floatcttv_content.setProgress(progress)}anim.start()}}

activity_color_track布局文件:

<?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"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><com.happy.android.study.view.ColorTrackTextViewandroid:id="@+id/cttv_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="小洋人最happy"android:textSize="28dp"app:changeColor="@android:color/holo_red_dark"app:direction="right2Left" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="12dp"android:orientation="horizontal"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="left2Right"android:text="从左到右渐变" /><Buttonandroid:id="@+id/right2Left"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="right2Left"android:text="从右到左渐变" /></LinearLayout>
</LinearLayout>

3. 小结

实现代码比较简单,主要知识点如下:

  • Canvas.clipRect使用
  • 文本基准线计算
  • 偏移量计算

这篇关于Android自定义View之文本变色的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/982420

相关文章

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级