如何使用与文本不同的颜色为TextView中的文本加下划线?

时间:2013-09-27 08:52:14

标签: android android-layout textview

我知道如何在textview中为文本加下划线。但是如何用不同颜色强调文字? 下划线可以通过以下方式完成:

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

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

9 个答案:

答案 0 :(得分:13)

我遇到了同样的问题,在EditText上阅读其他一些帖子时,我偶然发现了Layout课程。它通过手动绘制带有画布的下划线,提供了实现这一目标所需的一切。

首先,我为XML布局文件中的轻松自定义定义了自定义属性

<declare-styleable name="UnderlinedTextView" >
    <attr name="underlineWidth" format="dimension" />
    <attr name="underlineColor" format="color" />
</declare-styleable>

自定义TextView

public class UnderlinedTextView extends AppCompatTextView {

    private Rect mRect;
    private Paint mPaint;
    private float mStrokeWidth;

    public UnderlinedTextView(Context context) {
        this(context, null, 0);
    }

    public UnderlinedTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public UnderlinedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private void init(Context context, AttributeSet attributeSet, int defStyle) {

        float density = context.getResources().getDisplayMetrics().density;

        TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.UnderlinedTextView, defStyle, 0);
        int underlineColor = typedArray.getColor(R.styleable.UnderlinedTextView_underlineColor, 0xFFFF0000);
        mStrokeWidth = typedArray.getDimension(R.styleable.UnderlinedTextView_underlineWidth, density * 2);
        typedArray.recycle();

        mRect = new Rect();
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(underlineColor);
        mPaint.setStrokeWidth(mStrokeWidth);
    }

    public int getUnderLineColor() {
        return mPaint.getColor();
    }

    public void setUnderLineColor(int mColor) {
        mPaint.setColor(mColor);
        invalidate();
    }

    public float getUnderlineWidth() {
        return mStrokeWidth;
    }

    public void setUnderlineWidth(float mStrokeWidth) {
        this.mStrokeWidth = mStrokeWidth;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        int count = getLineCount();

        final Layout layout = getLayout();
        float x_start, x_stop, x_diff;
        int firstCharInLine, lastCharInLine;

        for (int i = 0; i < count; i++) {
            int baseline = getLineBounds(i, mRect);
            firstCharInLine = layout.getLineStart(i);
            lastCharInLine = layout.getLineEnd(i);

            x_start = layout.getPrimaryHorizontal(firstCharInLine);
            x_diff = layout.getPrimaryHorizontal(firstCharInLine + 1) - x_start;
            x_stop = layout.getPrimaryHorizontal(lastCharInLine - 1) + x_diff;

            canvas.drawLine(x_start, baseline + mStrokeWidth, x_stop, baseline + mStrokeWidth, mPaint);
        }

        super.onDraw(canvas);
    }
}

然后它的使用很简单

<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:underlineWidth="3dp"/>

最终结果

  • 多线



    enter image description here
  • 单行

    enter image description here

答案 1 :(得分:4)

您可以尝试如下:

  String styledText = "<u><font color='red'>Underline Text</font></u>.";
  textView.setText(Html.fromHtml(styledText), TextView.BufferType.SPANNABLE);

答案 2 :(得分:3)

如果您是XML的粉丝。看看我的解决方案:

在可绘制文件夹

中创建选择器selector_edittext_white.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:bottom="-15dp">
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromDegrees="0"
        android:pivotX="0.5"
        android:pivotY="0.5"
        android:toDegrees="0">
        <shape android:shape="line">
            <stroke
                android:width="0.5dp"
                android:color="@android:color/white" />
        </shape>
    </rotate>
  </item>
</layer-list>

然后,设置EditText

android:background="@drawable/selector_edittext_white"

在上面的设置中,下划线的颜色为白色,您可以通过更改上面的android:bottom来移动它&#34; -15dp&#34; 。如果它消失了,请尝试像这样设置EditText底部边距

android:layout_marginBottom="5dp"

答案 3 :(得分:2)

我还无法添加评论,所以我将其作为答案发布。

我只想说Bojan Kseneman的回答(https://stackoverflow.com/a/30717100/2771087)太棒了。但是有一个问题我想纠正。

它不是找到一行中最后一个字符的结束位置,而是抓住倒数第二个字符的结尾,然后在行中添加第一个字符的宽度。这两行:

source

而不是这个,getSecondaryHorizo​​ntal()可以用来抓住角色的另一面,如:

x_diff = layout.getPrimaryHorizontal(firstCharInLine + 1) - x_start;
x_stop = layout.getPrimaryHorizontal(lastCharInLine - 1) + x_diff;

但是,这也会为多行文本区域的每一行末尾的空格加下划线。因此,要解决该问题,请在计算x_stop之前使用以下代码跳过它:

x_stop = layout.getSecondaryHorizontal(lastCharInLine);

答案 4 :(得分:2)

另一个解决方案,这次没有扩展TextView(基于我很久以前写的一个问题,here):

有一个drawable可以显示为下划线,并且有一个文本本身的范围:

<强> text_underline.xml

<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line">
    <padding android:bottom="10dp"/>
    <stroke
        android:width="1dp"
        android:color="#3792e5"/>
</shape>

<强> DrawableSpan.kt

class DrawableSpan(private val drawable: Drawable) : ReplacementSpan() {
    private val padding: Rect = Rect()

    init {
        drawable.getPadding(padding)
    }

    override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
        val rect = RectF(x, top.toFloat(), x + measureText(paint, text, start, end), bottom.toFloat())
        drawable.setBounds(rect.left.toInt() - padding.left, rect.top.toInt() - padding.top, rect.right.toInt() + padding.right, rect.bottom.toInt() + padding.bottom)
        canvas.drawText(text, start, end, x, y.toFloat(), paint)
        drawable.draw(canvas)
    }

    override fun getSize(paint: Paint, text: CharSequence, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int = Math.round(paint.measureText(text, start, end))

    private fun measureText(paint: Paint, text: CharSequence, start: Int, end: Int): Float = paint.measureText(text, start, end)

}

用法:

    val text = getString(R.string.large_text)
    val spannable = SpannableString(text)
    spannable.setSpan(DrawableSpan(resources.getDrawable(R.drawable.text_underline)), 0, text.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    textView.setText(spannable, TextView.BufferType.SPANNABLE)

结果:

enter image description here

答案 5 :(得分:0)

imee.setText(Html.fromHtml("<font color=#9e4c4e>  <u>" + ime + "</u>  </font>"));
avtorr.setText(Html.fromHtml("<font color=#90494f>  <u>" + avtorr + "</u>  </font>"));

最好的解决方案是使用HTML。

答案 6 :(得分:0)

另一种解决方案,也具有跨度

ColoredUnderlineSpan.kt

/**
 * A span which draw a colored line below the text
 *
 * @property color The color of the underline
 * @property thickness The thickness of the line in pixels
 */
@RequiresApi(Build.VERSION_CODES.Q)
class ColoredUnderlineSpan(@ColorInt private val color: Int, @Px private val thickness: Float) : CharacterStyle(), UpdateAppearance {
    override fun updateDrawState(tp: TextPaint) {
        tp.underlineColor = color
        tp.underlineThickness = thickness
    }
}

/**
 * A span which draw a colored line below the text
 *
 * @param color The color of the underline
 * @property thickness The thickness of the line in pixels
 */
class ColoredUnderlineSpanPreQ(@ColorInt color: Int, @Px private val thickness: Float) : ReplacementSpan() {

    private val linePaint = Paint().apply {
        this.color = color
    }

    override fun draw(canvas: Canvas, text: CharSequence, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
        canvas.drawText(text, start, end, x, y.toFloat(), paint)
        canvas.drawRect(x, bottom - thickness, (x + paint.measureText(text, start, end)), bottom.toFloat(), linePaint)
    }

    override fun getSize(
        paint: Paint,
        text: CharSequence,
        start: Int,
        end: Int,
        fm: Paint.FontMetricsInt?
    ): Int = paint.measureText(text, start, end).roundToInt()
}

答案 7 :(得分:0)

这对我很有用:

terms.setText(Html.fromHtml("I have read and agree to the <u><font color='red'>Terms and Conditions</u>"));

答案 8 :(得分:-1)

    Paint p = new Paint();
    p.setColor(Color.RED);

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

制作新的油漆颜色。并将油漆分配给textview。