在这里插入图片描述

Android 自定义 TextView 实现垂直渐变字体颜色(支持 XML 配置)

在 Android UI 设计中,字体颜色的渐变效果能让界面看起来更加精致与现代。常见的渐变有从左到右、从上到下等方向,但 Android 的 TextView 默认并不支持垂直渐变。

本文将带你从原理到实现,一步步完成一个支持 上到下颜色渐变TextView,并且支持在 XML 中直接配置渐变颜色,无须每次写 Java 代码去设置。

本文最终实现效果:文字颜色可从顶部到底部渐变,颜色、方向均可在 XML 中自定义,支持阴影效果,性能开销低,可直接在项目中复用。


文章目录

  • **Android 自定义 TextView 实现垂直渐变字体颜色(支持 XML 配置)**
    • 1. 渐变字体效果原理
    • 2. 自定义 VerticalGradientTextView(支持 XML 配置)
      • 2.1 添加自定义属性
      • 2.2 编写自定义 TextView 类
    • 3. 在 XML 中使用渐变字体 TextView
    • 4. 优化与扩展
      • 4.1 性能优化
      • 4.2 支持更多渐变类型
      • 4.3 与动画结合
    • 总结


1. 渐变字体效果原理

在 Android 中,要实现渐变文字的关键是使用 Shader(着色器),其中 LinearGradient 是最常用的线性渐变工具。

LinearGradient 的构造函数如下:

LinearGradient(float x0, float y0, // 渐变起点坐标float x1, float y1, // 渐变终点坐标int color0,         // 起始颜色int color1,         // 结束颜色Shader.TileMode tile
)

当我们把 LinearGradient 设置给 TextViewPaint 时,文字在绘制时就会自动按照渐变色进行渲染。

例如,如果我们想要让文字从红色渐变到蓝色,由上到下,可以这么写:

Shader shader = new LinearGradient(0, 0, 0, getHeight(),Color.RED,Color.BLUE,Shader.TileMode.CLAMP
);
paint.setShader(shader);

Shader.TileMode.CLAMP 表示渐变会被拉伸填充到末端,不会重复或镜像。


2. 自定义 VerticalGradientTextView(支持 XML 配置)

为了让渐变文字可以在布局 XML 中直接配置,我们需要自定义一个 TextView,并且支持读取自定义属性(startColorendColorgradientOrientation)。


2.1 添加自定义属性

首先,在 res/values/attrs.xml 中定义渐变颜色相关的属性:

<resources><declare-styleable name="VerticalGradientTextView"><!-- 渐变起始颜色 --><attr name="startColor" format="color" /><!-- 渐变结束颜色 --><attr name="endColor" format="color" /><!-- 渐变方向:vertical(默认)、horizontal --><attr name="gradientOrientation" format="enum"><enum name="vertical" value="0" /><enum name="horizontal" value="1" /></attr></declare-styleable>
</resources>

这样,XML 中就可以像设置 android:textColor 一样设置渐变颜色。


2.2 编写自定义 TextView 类

package com.example.gradienttextview;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;import androidx.appcompat.widget.AppCompatTextView;public class VerticalGradientTextView extends AppCompatTextView {private int startColor;private int endColor;private int orientation; // 0: vertical, 1: horizontalpublic VerticalGradientTextView(Context context) {this(context, null);}public VerticalGradientTextView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public VerticalGradientTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VerticalGradientTextView);startColor = ta.getColor(R.styleable.VerticalGradientTextView_startColor, 0xFFFF4081);endColor = ta.getColor(R.styleable.VerticalGradientTextView_endColor, 0xFF3F51B5);orientation = ta.getInt(R.styleable.VerticalGradientTextView_gradientOrientation, 0);ta.recycle();}@Overrideprotected void onDraw(Canvas canvas) {Paint paint = getPaint();Shader shader;if (orientation == 0) {// 垂直渐变shader = new LinearGradient(0, 0, 0, getHeight(),startColor,endColor,Shader.TileMode.CLAMP);} else {// 水平渐变shader = new LinearGradient(0, 0, getWidth(), 0,startColor,endColor,Shader.TileMode.CLAMP);}paint.setShader(shader);super.onDraw(canvas);}
}

3. 在 XML 中使用渐变字体 TextView

创建布局文件 activity_main.xml,直接使用我们的自定义控件:

<com.example.gradienttextview.VerticalGradientTextViewandroid:layout_width="112dp"android:layout_height="40dp"android:text="示例文本"android:textSize="28sp"android:gravity="center"android:shadowColor="#40000000"android:shadowDx="0dp"android:shadowDy="4dp"android:shadowRadius="3.0"app:startColor="#FF4081"app:endColor="#3F51B5"app:gradientOrientation="vertical"/>

这样,文字就会从粉红色(#FF4081)到蓝色(#3F51B5)垂直渐变,并且保留阴影效果。


4. 优化与扩展

4.1 性能优化

  • onDraw() 中每次都会创建 LinearGradient,对于频繁重绘的场景(如动画)可能会增加开销。可以将 LinearGradient 缓存到成员变量,并在 onSizeChanged() 时重新计算。
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);updateShader(w, h);
}private void updateShader(int w, int h) {if (orientation == 0) {shader = new LinearGradient(0, 0, 0, h, startColor, endColor, Shader.TileMode.CLAMP);} else {shader = new LinearGradient(0, 0, w, 0, startColor, endColor, Shader.TileMode.CLAMP);}
}

这样 onDraw() 里只需要 paint.setShader(shader);,无需每次创建对象。


4.2 支持更多渐变类型

  • 多色渐变:LinearGradient 支持传入颜色数组和对应位置数组,可以实现三色或更多颜色渐变。
  • 角度渐变:通过计算不同的起止坐标,可以实现任意角度渐变。

4.3 与动画结合

渐变字体可以和 ValueAnimator 结合,让颜色动态变化,实现炫酷的标题效果。

ValueAnimator animator = ValueAnimator.ofArgb(Color.RED, Color.BLUE);
animator.addUpdateListener(animation -> {startColor = (int) animation.getAnimatedValue();invalidate();
});
animator.setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.start();

总结

通过以上步骤,我们实现了一个:

  • 支持 XML 配置渐变颜色和方向
  • 保持阴影效果
  • 性能优化可选
  • 可扩展为多色渐变和动画

垂直渐变字体 TextView

无论是用于游戏 UI、主题标题,还是特殊提示文字,都可以让界面更具视觉冲击力,同时保持代码的灵活性与可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92896.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92896.shtml
英文地址,请注明出处:http://en.pswp.cn/web/92896.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CANopen Magic调试软件使用

一、软件安装与硬件连接1.1 系统要求操作系统&#xff1a;Windows 7/10/11 (64位)硬件接口&#xff1a;支持Vector/PEAK/IXXAT等主流CAN卡推荐配置&#xff1a;4GB内存&#xff0c;2GHz以上CPU1.2 安装步骤运行安装包CANopen_Magic_Setup.exe选择安装组件&#xff08;默认全选&…

前端css学习笔记3:伪类选择器与伪元素选择器

本文为个人学习总结&#xff0c;如有谬误欢迎指正。前端知识众多&#xff0c;后续将继续记录其他知识点&#xff01; 目录 前言 一、伪类选择器 1.概念 2.动态选择器&#xff08;用户交互&#xff09; 3.结构伪类 &#xff1a;first-child&#xff1a;选择所有兄弟元素的…

深入探索 PDF 数据提取:PyMuPDF 与 pdfplumber 的对比与实战

在数据处理和分析领域&#xff0c;PDF 文件常常包含丰富的文本、表格和图形信息。然而&#xff0c;从 PDF 中提取这些数据并非易事&#xff0c;尤其是当需要保留格式和颜色信息时。幸运的是&#xff0c;Python 社区提供了多个强大的库来帮助我们完成这项任务&#xff0c;其中最…

Springboot注册过滤器的三种方式(Order 排序)

一、使用 Component Order&#xff08;简单但不够灵活&#xff09; 适用于全局过滤器&#xff0c;无需手动注册&#xff0c;Spring Boot 会自动扫描并注册。 Component Order(1) // 数字越小&#xff0c;优先级越高 public class AuthFilter implements Filter {Autowired /…

电脑硬件详解

前几天我的风扇转的很快&#xff0c;而且cpu占用率很高&#xff0c;然后我在想怎么回事&#xff0c;然后就浅浅研究了一下电脑的硬件。 笔记本主板&#xff1a; 台式机主板&#xff1a; 图1&#xff1a; 图2&#xff1a; 电脑硬件详解 电脑的硬件是组成计算机系统的物理设…

力扣47:全排列Ⅱ

力扣47:全排列Ⅱ题目思路代码题目 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 思路 又是任意顺序和所有不重复的排列&#xff0c;显而易见我们要使用回溯的办法。 首先是回溯的结束条件即新数组的长度等于nums的长度。这道题的难点…

学习笔记091——如何实现web登录时,密码复杂度校验?(后端)

1、创建工具类 /*** 密码复杂度校验* param password 密码*/ public static void validatePassword(String password) {// 至少8位if (password.length() < 8) {throw new IllegalArgumentException("密码长度至少为8位");}// 包含大小写字母if (!password.matche…

雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论

一、前言在日趋复杂的分布式系统中&#xff0c;数据量越来越大&#xff0c;数据库分库分表是一贯的垂直水平做法&#xff0c;但是需要一个全局唯一ID标识一条数据或者MQ消息&#xff0c;数据库id自增就显然不能满足要求了。因为场景不同&#xff0c;分布式ID需要满足以下几个条…

【PCB设计经验】去耦电容如何布局?

0805 和 0603 以及更小 封装的电容用作于对中高频的去耦,其摆放位置是有要求的: 一、建议尽可能的靠近主控芯片的 电源管脚放置。 二、使用较宽和短的引线连接到电源和地过孔可以采用如下 图 4–1 中的图 ( 2 )、( 3)、 ( 4 )任意一种方式,避免使用长线或者较细的…

自动化运维实验

目录 一、实验拓扑 二、实验目的 三、实验步骤 实验思路&#xff1a; 代码部分&#xff1a; 四、实验结果&#xff1a; 一、实验拓扑 二、实验目的 利用python脚本&#xff0c;在本地&#xff0c;或者虚拟机里实现&#xff0c;设备CRC数量统计&#xff0c;并输出成表格 三、实验…

Wed前端第二次作业

一、作业1&#xff1a;完成自己学校的官网&#xff0c;动忘内容直接贴&#xff0c;至少三个不同的页面1、界面1&#xff08;1&#xff09;相关代码<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&quo…

第5节 大模型分布式推理通信优化与硬件协同

前言 在分布式推理中,多设备(如GPU、CPU)之间的数据传输(通信)是连接计算的“桥梁”。如果通信效率低下,即使单设备计算能力再强,整体性能也会大打折扣。想象一下:如果工厂之间的物流卡车跑得比生产速度还慢,再多的工厂也无法提高整体产量。 本节将从最基础的单设备内…

XGBoost 的适用场景以及与 CNN、LSTM 的区别

XGBoost 的核心优势与适用场景XGBoost 是一种梯度提升决策树算法&#xff0c;属于集成学习方法。它在处理结构化/表格化数据方面表现极其出色&#xff0c;是 Kaggle 竞赛和工业界广泛应用的“冠军”模型。其核心优势和应用场景包括&#xff1a;1. 结构化/表格化数据数据形式&a…

快速设计简单嵌入式操作系统(3):动手实操,基于STC8编写单任务执行程序,感悟MCU指令的执行过程

引言 前面我们陆续学习了操作系统常见的基础概念&#xff0c;接着简单了解了一下8051单片机的内存结构和执行顺序切换的相关概念。接下来&#xff0c;我们就开始进行实操&#xff0c;基于8051单片机STC8来编写一个简单的操作系统&#xff0c;这里我们先实现一个单任务的执行程…

Spring AI Alibaba - 聊天机器人快速上手

本节对应 Github&#xff1a;https://github.com/JCodeNest/JCodeNest-AI-Alibaba/tree/master/spring-ai-alibaba-helloworld 本文将以阿里巴巴的通义大模型为例&#xff0c;通过 Spring AI Alibaba 组件&#xff0c;手把手带你完成从零到一的构建过程&#xff1a;首先&#…

串口通信学习

不需要校验位就选8位&#xff0c;需要校验位就选9位&#xff01;USRTUSART框图STM32的外设引脚这是USART的基本结构。数据帧&#xff0c;八位是这个公式还是很重要的&#xff01;如果在编辑器里面使用printf打印汉字的话&#xff0c;会出现乱码的话&#xff0c;前提是你的编码格…

面试经典150题[001]:合并两个有序数组(LeetCode 88)

合并两个有序数组&#xff08;LeetCode 88&#xff09; https://leetcode.cn/problems/merge-sorted-array/?envTypestudy-plan-v2&envIdtop-interview-150 1. 题目背景 你有两个已经排好序的数组&#xff1a; nums1&#xff1a;前面是有效数字&#xff0c;后面是空位&…

快速安装达梦8测试库

计划&#xff1a;数据库名实例名PORT_NUMMAL_INST_DW_PORTMAL_HOSTMAL_PORTMAL_DW_PORTDMDWDBINST_1533615101192.168.207.612510135101*****[2025-08-11 15:14:34]***** Last login: Fri Jul 25 17:36:04 2025 from 192.168.88.48 [rootdm01 ~]# ip a 1: lo: <LOOPBACK,UP,…

Hive中优化问题

一、小文件合并优化Hive中的小文件分为Map端的小文件和Reduce端的小文件。(1)、Map端的小文件优化是通过CombineHiveInputFormat操作。相关的参数是&#xff1a;set hive.input.formatorg.apache.hadoop.hive.ql.io.CombineHiveInputFormat;(2)、Reduce端的小文件合并Map端的小…

tlias智能学习辅助系统--Maven高级-继承

目录 一、打包方式与应用场景 二、父子工程继承关系 1. 父工程配置 2. 子工程配置 三、自定义属性与引用属性 1. 定义属性 2. 在 dependencyManagement 中引用 3. 子工程中引用 四、dependencyManagement 与 dependencies 的区别 五、项目结构示例 六、小结 在实际开…