Android 自定义 TextView 实现垂直渐变字体颜色(支持 XML 配置)
在 Android UI 设计中,字体颜色的渐变效果能让界面看起来更加精致与现代。常见的渐变有从左到右、从上到下等方向,但 Android 的 TextView
默认并不支持垂直渐变。
本文将带你从原理到实现,一步步完成一个支持 上到下颜色渐变 的 TextView
,并且支持在 XML 中直接配置渐变颜色,无须每次写 Java 代码去设置。
本文最终实现效果:文字颜色可从顶部到底部渐变,颜色、方向均可在 XML 中自定义,支持阴影效果,性能开销低,可直接在项目中复用。
文章目录
1. 渐变字体效果原理
在 Android 中,要实现渐变文字的关键是使用 Shader(着色器),其中 LinearGradient
是最常用的线性渐变工具。
LinearGradient
的构造函数如下:
LinearGradient(
float x0, float y0, // 渐变起点坐标
float x1, float y1, // 渐变终点坐标
int color0, // 起始颜色
int color1, // 结束颜色
Shader.TileMode tile
)
当我们把 LinearGradient
设置给 TextView
的 Paint
时,文字在绘制时就会自动按照渐变色进行渲染。
例如,如果我们想要让文字从红色渐变到蓝色,由上到下,可以这么写:
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
,并且支持读取自定义属性(startColor
、endColor
、gradientOrientation
)。
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: horizontal
public 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();
}
@Override
protected 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.VerticalGradientTextView
android: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、主题标题,还是特殊提示文字,都可以让界面更具视觉冲击力,同时保持代码的灵活性与可维护性。