Android中如何为TextView设置渐变文字颜色并同时添加文字描边
实现原理
你遇到的问题根源是同一个Paint的Shader优先级高于纯色设置,当你给Paint设置渐变Shader后,无论是描边模式还是填充模式,都会优先使用Shader的颜色,导致描边无法显示纯色。解决方案是分两次独立绘制:先画纯色描边层,再画渐变填充层。
完整实现代码
public class GradientStrokeTextView extends AppCompatTextView { private int[] mGradientColors; private int mStrokeColor = Color.BLACK; private float mStrokeWidth = 0f; private LinearGradient mTextGradient; public GradientStrokeTextView(Context context) { super(context); } public GradientStrokeTextView(Context context, AttributeSet attrs) { super(context, attrs); // 可自行扩展自定义属性读取逻辑,读取描边宽度、颜色、渐变色数组 } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (w > 0 && mGradientColors != null && mGradientColors.length >= 2) { // 尺寸变化时更新渐变Shader,避免在onDraw中频繁创建对象 mTextGradient = new LinearGradient(0f, 0f, w, getTextSize(), mGradientColors, null, Shader.TileMode.CLAMP); } } @Override protected void onDraw(Canvas canvas) { if (mStrokeWidth <= 0 || mGradientColors == null || mTextGradient == null) { // 未设置描边或渐变时走原生绘制逻辑 super.onDraw(canvas); return; } TextPaint paint = getPaint(); // 第一步:绘制纯色描边层 paint.setShader(null); // 清除渐变配置,优先显示纯色描边 paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(mStrokeWidth); setTextColor(mStrokeColor); super.onDraw(canvas); // 第二步:绘制渐变填充层 paint.setShader(mTextGradient); paint.setStyle(Paint.Style.FILL); super.onDraw(canvas); } // 对外提供参数设置方法 public void setGradientColors(int[] colors) { this.mGradientColors = colors; if (getWidth() > 0) { mTextGradient = new LinearGradient(0f, 0f, getWidth(), getTextSize(), mGradientColors, null, Shader.TileMode.CLAMP); } invalidate(); } public void setStrokeConfig(int color, float width) { this.mStrokeColor = color; this.mStrokeWidth = width; invalidate(); } }
注意事项
- 不要在
onDraw方法中创建LinearGradient对象,避免频繁触发GC导致卡顿,统一在onSizeChanged或者参数设置时初始化即可。 - 两次绘制都调用原生
super.onDraw(canvas),不会破坏TextView原生的换行、对齐、padding、行间距等特性。 - 如果需要圆角描边效果,可以给Paint增加
paint.setStrokeJoin(Paint.Join.ROUND)、paint.setStrokeCap(Paint.Cap.ROUND)配置。
内容的提问来源于stack exchange,提问作者Arslan
相关产品推荐
相关产品推荐

