Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/178.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 具有背景色和行距的文本视图_Android_Background_Textview_Html - Fatal编程技术网

Android 具有背景色和行距的文本视图

Android 具有背景色和行距的文本视图,android,background,textview,html,Android,Background,Textview,Html,我想展示下面这样的文本 我的编码如下: SpannableString sText = new SpannableString(text); sText.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, sText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); holder.txtText.setLineSpacing(0, 1.5f); textView.setText(sText); 您可

我想展示下面这样的文本

我的编码如下:

SpannableString sText = new SpannableString(text);
sText.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, sText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

holder.txtText.setLineSpacing(0, 1.5f);
textView.setText(sText);

您可以在XML文件中使用
lineSpacingExtra
lineSpacingMultiplier
。你可以在这里找到它:

对于背景色,您可以使用:

    <TextView
          android:background="#FFFF00" 
   />

试试这个。 创建自定义TextView并覆盖方法draw(画布)

公共类BgColorTextView扩展了TextView{
公共BgColorTextView(上下文){
超级(上下文);
}
公共BgColorTextView(上下文、属性集属性){
超级(上下文,attrs);
}
公共BgColorTextView(上下文上下文、属性集属性、int defStyleAttr){
super(上下文、attrs、defStyleAttr);
}
公共BgColorTextView(上下文上下文、属性集属性、int-defStyleAttr、int-defStyleRes){
super(context、attrs、defStyleAttr、defStyleRes);
}
@凌驾
公共空白绘制(画布){
int lineCount=getLayout().getLineCount();
Rect Rect=新的Rect();
油漆=新油漆();
setColor(getResources().getColor(R.color.YOUR_CUSTOM_color));
对于(int i=0;i
这已经有很长时间了,但我将在下面介绍静态方法。希望它能帮助其他人

public static void setTextWithSpan(final TextView textView, int backgroundColor, String text, float lineSpacingMultiplier) {
    class BackgroundColorSpanWithPaddingAndLineSpacing implements LineBackgroundSpan {
        private float roundedCornerSize;
        private int backgroundColor;
        private int paddingSize;
        private RectF rect;

        private BackgroundColorSpanWithPaddingAndLineSpacing(int backgroundColor, int paddingSize, float roundedCornerSize) {
            super();
            this.backgroundColor = backgroundColor;
            this.paddingSize = paddingSize;
            this.roundedCornerSize = roundedCornerSize;
            this.rect = new RectF();
        }

        @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 currentLineNumber) {
            final int textWidth = Math.round(p.measureText(text, start, end));
            final int paintColor = p.getColor();

            rect.set(left - paddingSize / 2, top - paddingSize / 4, left + textWidth + paddingSize / 2, top + textView.getTextSize() + paddingSize / 2);
            p.setColor(backgroundColor);
            c.drawRoundRect(rect, roundedCornerSize, roundedCornerSize, p);
            p.setColor(paintColor);
        }
    }

    int padding = textView.getPaddingLeft();
    int radius = padding / 2;

    SpannableStringBuilder builder = new SpannableStringBuilder(text);
    BackgroundColorSpanWithPaddingAndLineSpacing backgroundSpan = new BackgroundColorSpanWithPaddingAndLineSpacing(backgroundColor, padding, radius);
    builder.setSpan(backgroundSpan, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    textView.setShadowLayer(padding, 0, 0, 0);
    textView.setLineSpacing(0, lineSpacingMultiplier);

    textView.setText(builder, TextView.BufferType.SPANNABLE);
}
用法:

SpanUtils.setTextWithSpan(titleTv, android.graphics.Color.BLUE, textStr, 1.4f);

我相信您会根据自己的需要进行修改。

一个稍加修改的解决方案,基于,带有设置颜色的选项,在kotlin中:

//https://stackoverflow.com/a/30096905/878126
class BgColorTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) {
    @Suppress("MemberVisibilityCanBePrivate")
    var backgroundTextColor = -0x145bfb
        set(value) {
            field = value
            invalidate()
        }

    override fun draw(canvas: Canvas) {
        val currentLayout = layout
        if (currentLayout == null) {
            super.draw(canvas)
            return
        }
        val lineCount = currentLayout.lineCount
        val rect = Rect()
        val paint = Paint()
        paint.color = backgroundTextColor
        for (i in 0 until lineCount) {
            rect.top = currentLayout.getLineTop(i)
            rect.left = currentLayout.getLineLeft(i).toInt()
            rect.right = currentLayout.getLineRight(i).toInt()
            rect.bottom = currentLayout.getLineBottom(i) - (if (i + 1 == lineCount) 0 else currentLayout.spacingAdd.toInt())
            canvas.drawRect(rect, paint)
        }
        super.draw(canvas)
    }
}

对于存在相同问题的用户,可以创建一个扩展ReplacemntSpan类的新类,并重写它的draw方法,如下所示:


public class RoundedBackgroundSpan extends ReplacementSpan {

    private int backgroundColor = 0;
    private int textColor = 0;

    public RoundBackgroundSpan(Context context) {
        super();
        backgroundColor = ContextCompat.getColor(context , R.color.amber_600);
        textColor = ContextCompat.getColor(context , R.color.white);
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        float newBottom = bottom - 2;
        float newTop = top + 2;
        RectF rect = new RectF(x , newTop , x + measureText(paint, text, start, end), newBottom );
        paint.setColor(backgroundColor);
        int CORNER_RADIUS = 8;
        canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint);
        paint.setColor(textColor);
        canvas.drawText(text, start, end, x , y, paint);
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        return Math.round(paint.measureText(text, start, end));
    }

    private float measureText(Paint paint, CharSequence text, int start, int end) {
        return paint.measureText(text, start, end);
    }
}

并在您的Spanable中使用它。

基于@evren ozturk答案,无需文本视图链接和更好的排版支持

class RoundedBackgroundSpan(
    private val textColor: Int,
    private val backgroundColor: Int
) : ReplacementSpan() {

    private val additionalPadding = 4.toPx().toFloat()
    private val cornerRadius = 4.toPx().toFloat()

    override fun draw(
        canvas: Canvas,
        text: CharSequence,
        start: Int,
        end: Int,
        x: Float,
        top: Int,
        y: Int,
        bottom: Int,
        paint: Paint
    ) {
        val newTop = y + paint.fontMetrics.ascent
        val newBottom = y + paint.fontMetrics.descent
        val rect = RectF(x, newTop, x + measureText(paint, text, start, end) + 2 * additionalPadding, newBottom)
        paint.color = backgroundColor

        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)
        paint.color = textColor
        canvas.drawText(text, start, end, x + additionalPadding, y.toFloat(), paint)
    }

    override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: FontMetricsInt?): Int {
        return (paint.measureText(text, start, end) + 2 * additionalPadding).roundToInt()
    }

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

    private fun Int.toPx(): Int {
        val resources = Resources.getSystem()
        val metrics = resources.displayMetrics
        return Math.round(this * (metrics.densityDpi / 160.0f))
    }
}

面对同样的问题,我发现这个答案对我来说很好,应该也能解决你的问题。 在xml文本视图中配置此选项:

android:lineSpacingMultiplier=“2”

链接:

已经11个月了,我希望你已经完成了!
祝你好运

我仍然有同样的问题,我也面临同样的问题。您找到解决方案了吗?文本背景似乎在某些字母的底部被剪切,例如“y”的底部。这是可行的,但是“getLayout()”可能返回null并崩溃。在这种情况下应该怎么做?当布局为空时,可以跳过绘图迭代。如果android没有布局,它会画什么?=)对最后,我就是这么做的:。但我认为这里有一个不同的问题,即使有一条空线也能勾勒出背景……他说的是文字包装
class RoundedBackgroundSpan(
    private val textColor: Int,
    private val backgroundColor: Int
) : ReplacementSpan() {

    private val additionalPadding = 4.toPx().toFloat()
    private val cornerRadius = 4.toPx().toFloat()

    override fun draw(
        canvas: Canvas,
        text: CharSequence,
        start: Int,
        end: Int,
        x: Float,
        top: Int,
        y: Int,
        bottom: Int,
        paint: Paint
    ) {
        val newTop = y + paint.fontMetrics.ascent
        val newBottom = y + paint.fontMetrics.descent
        val rect = RectF(x, newTop, x + measureText(paint, text, start, end) + 2 * additionalPadding, newBottom)
        paint.color = backgroundColor

        canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)
        paint.color = textColor
        canvas.drawText(text, start, end, x + additionalPadding, y.toFloat(), paint)
    }

    override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: FontMetricsInt?): Int {
        return (paint.measureText(text, start, end) + 2 * additionalPadding).roundToInt()
    }

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

    private fun Int.toPx(): Int {
        val resources = Resources.getSystem()
        val metrics = resources.displayMetrics
        return Math.round(this * (metrics.densityDpi / 160.0f))
    }
}