如何在 TextView 中使用与文本颜色不同的颜色为文本添加下划线? [英] How to underline text in TextView with some different color than that of text?

查看:13
本文介绍了如何在 TextView 中使用与文本颜色不同的颜色为文本添加下划线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道如何在文本视图中为文本添加下划线.但是如何用一些不同的颜色给文本加下划线呢?下划线可以用:

I know how to underline text in a textview. But how to underline text with some different color ? Underline can be done with:

TextView t = (TextView) findViewById(R.id.textview);
t.setPaintFlags(t.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
t.setText("Underline Text");

假设我的 textcolor 是黑色,我想用蓝色下划线,怎么做?提前致谢.

Let say my textcolor is black and I want to underline the same with blue color, how to do it ? Thanks in advance.

推荐答案

我遇到了同样的问题,我偶然发现了 Layout 类,在阅读其他一些在 EditText 上执行此操作的帖子时.它通过在画布上手动绘制下划线,为您提供了实现这一目标所需的一切.

I had the same problem and I have stumbled upon Layout class when reading some other posts for doing this on EditText. It provides everything you need to make this happen by manually drawing underline with canvas.

首先我定义了自定义属性,以便在 XML 布局文件中轻松自定义

First I defined custom attributes for an easy customization in XML layout files

<declare-styleable name="UnderlinedTextView" >
    <attr name="underlineHeight" format="dimension" />
    <attr name="underlineOffset" format="dimension" />
    <attr name="underlineColor" format="color" />
    <attr name="underLinePosition" format="enum">
        <enum name="baseline" value="0" />
        <enum name="below" value="1" />
    </attr>
</declare-styleable>

还有一个自定义的TextView

   class UnderlinedTextView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : androidx.appcompat.widget.AppCompatTextView(context, attrs, defStyleAttr) {

    @Retention(AnnotationRetention.SOURCE)
    @IntDef(POSITION_BASELINE, POSITION_BELOW)
    annotation class UnderLinePosition {
        companion object {
            const val POSITION_BASELINE = 0
            const val POSITION_BELOW = 1
        }
    }

    private val linePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.FILL
    }

    var lineColor: Int
        get() = linePaint.color
        set(value) {
            if (linePaint.color != value) {
                linePaint.color = value
                invalidate()
            }
        }

    var lineHeight: Float
        get() = linePaint.strokeWidth
        set(value) {
            if (linePaint.strokeWidth != value) {
                linePaint.strokeWidth = value
                updateSpacing()
            }
        }

    var lineTopOffset = 0F
        set(value) {
            if (field != value) {
                field = value
                updateSpacing()
            }
        }

    @UnderLinePosition
    var linePosition = POSITION_BASELINE

    private val rect = Rect()

    private var internalAdd: Float = lineSpacingExtra

    private inline val extraSpace
        get() = lineTopOffset + lineHeight

    init {
        val density = context.resources.displayMetrics.density

        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.UnderlinedTextView, defStyleAttr, 0)
        lineColor = typedArray.getColor(R.styleable.UnderlinedTextView_underlineColor, currentTextColor)
        lineTopOffset = typedArray.getDimension(R.styleable.UnderlinedTextView_underlineOffset, 0f)
        lineHeight = typedArray.getDimension(R.styleable.UnderlinedTextView_underlineHeight, density * 1)
        linePosition = typedArray.getInt(R.styleable.UnderlinedTextView_underLinePosition, POSITION_BASELINE)
        typedArray.recycle()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(measuredWidth, measuredHeight + (extraSpace + 0.5f).toInt())
    }

    override fun onDraw(canvas: Canvas?) {
        canvas?.takeIf { !text.isNullOrEmpty() }?.let {
            val count = lineCount
            val layout = layout
            var xStart: Float
            var xStop: Float
            var yStart: Float
            var firstCharInLine: Int
            var lastCharInLine: Int
            var lastLine: Boolean
            var offset: Int
            val lineSpacing = lineSpacingExtra * lineSpacingMultiplier
            for (i in 0 until count) {
                val baseline = getLineBounds(i, rect)
                lastLine = i == count - 1
                offset = if (lastLine) 0 else 1
                firstCharInLine = layout.getLineStart(i)
                lastCharInLine = layout.getLineEnd(i)
                xStart = layout.getPrimaryHorizontal(firstCharInLine)
                xStop = layout.getPrimaryHorizontal(lastCharInLine - offset)
                yStart = when (linePosition) {
                    POSITION_BASELINE -> baseline + lineTopOffset
                    POSITION_BELOW -> (rect.bottom + lineTopOffset) - if (lastLine) 0F else lineSpacing
                    else -> throw NotImplementedError("")
                }
                canvas.drawRect(xStart, yStart, xStop, yStart + lineHeight, linePaint)
            }
        }
        super.onDraw(canvas)
    }

    private fun updateSpacing() {
        setLineSpacing(internalAdd, 1f)
    }

    override fun setLineSpacing(add: Float, mult: Float) {
        internalAdd = add
        super.setLineSpacing(add + extraSpace, 1f)
    }
}

那么它的用法就很简单了

Then it's usage is simple

<some.package.UnderlinedTextView
    android:id="@+id/tvTest"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_marginBottom="10dp"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="20dp"
    android:gravity="center"
    android:text="This is a demo text"
    android:textSize="16sp"
    app:underlineColor="#ffc112ef"
    app:underlineHeight="3dp"/>

最终结果

  • 多行

  • 单行

这篇关于如何在 TextView 中使用与文本颜色不同的颜色为文本添加下划线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆