Android Spannablecontent With Rounded Corners

前端 未结 8 791
无人及你
无人及你 2020-12-13 15:06

I am trying to change my string to make a badge with a number in the middle by using Spannable String. I can highlight the appropriate letter/number by setting the BackGrou

相关标签:
8条回答
  • 2020-12-13 15:53

    Here is my version based on @mvandillen answer. I also needed some margin at the beginning of span.

    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.support.annotation.NonNull;
    import android.text.style.ReplacementSpan;
    
    public class CoolBackgroundColorSpan extends ReplacementSpan {
    
        private final int mBackgroundColor;
        private final int mTextColor;
        private final float mCornerRadius;
        private final float mPaddingStart;
        private final float mPaddingEnd;
        private final float mMarginStart;
    
        public CoolBackgroundColorSpan(int backgroundColor, int textColor, float cornerRadius, float paddingStart, float paddingEnd, float marginStart) {
            super();
            mBackgroundColor = backgroundColor;
            mTextColor = textColor;
            mCornerRadius = cornerRadius;
            mPaddingStart = paddingStart;
            mPaddingEnd = paddingEnd;
            mMarginStart = marginStart;
        }
    
        @Override
        public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
            return (int) (mPaddingStart + paint.measureText(text.subSequence(start, end).toString()) + mPaddingEnd);
        }
    
        @Override
        public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
            float width = paint.measureText(text.subSequence(start, end).toString());
            RectF rect = new RectF(x - mPaddingStart + mMarginStart, top, x + width + mPaddingEnd + mMarginStart, bottom);
            paint.setColor(mBackgroundColor);
            canvas.drawRoundRect(rect, mCornerRadius, mCornerRadius, paint);
            paint.setColor(mTextColor);
            canvas.drawText(text, start, end, x + mMarginStart, y, paint);
        }
    }
    

    How to use:

    int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
    SpannableString staffTitleSpan = new SpannableString("staff: ");
    SpannableString staffNameSpan = new SpannableString("John Smith");
    staffNameSpan.setSpan(new StyleSpan(Typeface.BOLD), 0, staffNameSpan.length(), flag);
    staffNameSpan.setSpan(new CoolBackgroundColorSpan(mStaffNameSpanBgColor, mStaffNameSpanTextColor, mStaffNameSpanBgRadius, mStaffNameSpanBgPaddingStart, mStaffNameSpanBgPaddingEnd, mStaffNameSpanMarginStart), 0, staffNameSpan.length(), flag);
    SpannableStringBuilder builder = new SpannableStringBuilder();
    builder.append(staffTitleSpan);
    builder.append(staffNameSpan);
    
    staffTextView.setText(builder);
    

    Preview:

    0 讨论(0)
  • 2020-12-13 15:55

    Ok, so the question is a bit messy, here is my solution from DanieleB and mvandillen.

    public class RoundedBackgroundSpan extends ReplacementSpan {
    
        private static final int CORNER_RADIUS = 8;
        private static final int PADDING_X = 12;
    
        private int   mBackgroundColor;
        private int   mTextColor;
    
        /**
         * @param backgroundColor background color
         * @param textColor       text color
         */
        public RoundedBackgroundSpan(int backgroundColor, int textColor) {
            mBackgroundColor = backgroundColor;
            mTextColor = textColor;
        }
    
        @Override
        public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
            return (int) (PADDING_X + paint.measureText(text.subSequence(start, end).toString()) + PADDING_X);
        }
    
        @Override
        public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
            float width = paint.measureText(text.subSequence(start, end).toString());
            RectF rect = new RectF(x, top, x + width + 2 * PADDING_X, bottom);
            paint.setColor(mBackgroundColor);
            canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint);
            paint.setColor(mTextColor);
            canvas.drawText(text, start, end, x + PADDING_X, y, paint);
        }
    }
    

    Tip: you can remove the textColor and user the default TextView color:

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        Paint paint1 = new Paint(paint);
        float width = paint1.measureText(text.subSequence(start, end).toString());
        RectF rect = new RectF(x, top, x + width + 2 * PADDING_X, bottom);
        paint1.setColor(mBackgroundColor);
        canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint1);
        canvas.drawText(text, start, end, x + PADDING_X, y, paint);
    }
    
    0 讨论(0)
提交回复
热议问题