【问题标题】:How to get UnderlineSpan with another color in Android?如何在 Android 中获得另一种颜色的 UnderlineSpan?
【发布时间】:2018-11-26 21:28:21
【问题描述】:

我想要在 IDE 中看起来像错误的 Spannable - 用另一种颜色下划线。

我尝试创建扩展 android UnderlineSpanColorUnderlineSpan 类,但它使所有文本变成另一种颜色(我只需要添加彩色下划线):

/**
 * Underline Span with color
 */
public class ColorUnderlineSpan extends android.text.style.UnderlineSpan {

    private int underlineColor;

    public ColorUnderlineSpan(int underlineColor) {
        super();
        this.underlineColor = underlineColor;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setColor(underlineColor);
    }
}

我还找到了 DynamicDrawableSpan 类,但我看不到要绘制的画布边界。

如果使用带有边界参数的抽象绘制方法获得任何 Spannable 实现,那就太好了。

【问题讨论】:

    标签: android user-interface html spannable


    【解决方案1】:

    这不是最漂亮的解决方案,但它最终对我有用:

    public class CustomUnderlineSpan implements LineBackgroundSpan {
    
    int color;
    Paint p;
    int start, end;
    public CustomUnderlineSpan(int underlineColor, int underlineStart, int underlineEnd) {
        super();
        color = underlineColor;
        this.start = underlineStart;
        this.end = underlineEnd;
        p = new Paint();
        p.setColor(color);
        p.setStrokeWidth(3F);
        p.setStyle(Paint.Style.FILL_AND_STROKE);
    }
    
    @Override
    public void drawBackground(Canvas c, Paint p, int left, int right, int top, int baseline, int bottom, CharSequence text, int start, int end, int lnum) {
    
        if (this.end < start) return;
        if (this.start > end) return;
    
        int offsetX = 0;
        if (this.start > start) {
            offsetX = (int)p.measureText(text.subSequence(start, this.start).toString());
        }
    
        int length = (int)p.measureText(text.subSequence(Math.max(start, this.start), Math.min(end, this.end)).toString());
        c.drawLine(offsetX, baseline + 3F, length + offsetX, baseline + 3F, this.p);
    }
    

    这很奇怪,因为您必须指定字符索引来开始和结束下划线,但它对我有用。

    【讨论】:

    • 感谢您分享您的解决方案,我会尝试一下
    • 优秀的解决方案。自从每帧调用drawBackground以来,通过缓存offsetX和length可以大大提高性能。
    • 有没有 demoCode 可以检查这个?
    • 这就像一个魅力。我在 Kotlin 中发布了另一个基于此的答案,并支持多行 TextViews。谢谢!
    • 这是一个不错的解决方案,但我注意到该计算仅适用于左对齐文本。
    【解决方案2】:

    @korbonix 发布的答案效果很好。我对 Kotlin 进行了一些改进并支持多行 TextView:

    class ColorUnderlineSpan(val underlineColor: Int, val underlineStart: Int, val underlineEnd: Int): LineBackgroundSpan {
    
        val paint = Paint()
    
        init {
            paint.color = underlineColor
            paint.strokeWidth = 3.0f
            paint.style = Paint.Style.FILL_AND_STROKE
        }
    
        override fun drawBackground(c: Canvas?, p: Paint?, left: Int, right: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence?, start: Int, end: Int, lnum: Int) {
            if (!(underlineStart < underlineEnd)) {
                throw Error("underlineEnd should be greater than underlineStart")
            }
    
            if (underlineStart > end || underlineEnd < start) {
                return
            }
    
            var offsetX = 0
    
            if (underlineStart > start) {
                offsetX = p?.measureText(text?.subSequence(start, underlineStart).toString())?.toInt() ?: 0
            }
    
            val length: Int = p?.measureText(text?.subSequence(Math.max(start, underlineStart), Math.min(end, underlineEnd)).toString())?.toInt()
                ?: 0
    
            c?.drawLine(offsetX.toFloat(), baseline + 3.0f, (length + offsetX).toFloat(), baseline + 3.0f, paint)
        }
    }
    

    这是一个示例用法。 textText 是文本视图。文本长度为 127 个字符,下划线从位置 112 到 127。

    重要提示:由于我不完全理解的原因,跨度长度应设置为文本的全长。否则该组件甚至不会被调用。请随时告诉我为什么会这样。

        // Sets link color
        val spannable = SpannableString(getString(R.string.forgot_text))
        spannable.setSpan(
                ColorUnderlineSpan(Color.RED), 112, 127),
                0, 127, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        textText.text = spannable
    

    【讨论】:

    • 遗憾的是,当文本结束/右对齐时,此解决方案不起作用。 :(
    • 这不适用于多行。我在想你会使用 lnum Int 作为 offsetY
    猜你喜欢
    • 2013-01-10
    • 1970-01-01
    • 2019-01-29
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    相关资源
    最近更新 更多