You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:24:06