TextView with background color and line spacing

前端 未结 6 631
小蘑菇
小蘑菇 2020-12-06 11:06

I\'d like to show the text like the below...

\"enter

My coding is the followin

相关标签:
6条回答
  • 2020-12-06 11:31

    A bit modified solution based on this, with option to set the color, and in 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)
        }
    }
    
    0 讨论(0)
  • 2020-12-06 11:42

    You can use lineSpacingExtra or lineSpacingMultiplier in your XML file. You can find it here: http://developer.android.com/reference/android/widget/TextView.html#attr_android%3alineSpacingExtra

    And for background color you can use:

        <TextView
              android:background="#FFFF00" 
       />
    
    0 讨论(0)
  • 2020-12-06 11:46

    It has been a long time but I'll put the static method below. Hopefully it will help another.

    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);
    }
    

    Usage :

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

    I'm sure you'll manage to modify according to your needs.

    0 讨论(0)
  • 2020-12-06 11:47

    Based on @evren-ozturk answer without textView link and better typography support

    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))
        }
    }
    
    0 讨论(0)
  • 2020-12-06 11:48

    For those who have the same problem, you can Create a new class Extending ReplacemntSpan class and override it's draw method like this:

    
    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);
        }
    }
    

    And using it in your Spannable..

    0 讨论(0)
  • 2020-12-06 11:55

    try this. Create custom TextView and override method draw(Canvas canvas).

    public class BgColorTextView extends TextView {
        public BgColorTextView(Context context) {
            super(context);
        }
    
        public BgColorTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public BgColorTextView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public BgColorTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        public void draw(Canvas canvas) {
            int lineCount = getLayout().getLineCount();
            Rect rect = new Rect();
            Paint paint = new Paint();
            paint.setColor(getResources().getColor(R.color.YOUR_CUSTOM_COLOR));
            for (int i = 0; i < lineCount; i++) {
                rect.top = (getLayout().getLineTop(i));
                rect.left = (int) getLayout().getLineLeft(i);
                rect.right = (int) getLayout().getLineRight(i);
                rect.bottom = (int) (getLayout().getLineBottom(i) - ((i + 1 == lineCount) ? 0 : getLayout().getSpacingAdd()));
    
                canvas.drawRect(rect, paint);
            }
            super.draw(canvas);
        }
    }
    
    0 讨论(0)
提交回复
热议问题