Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Border in Clickable object in SpannableString

Tags:

android

Currently I have a SpannableString object with multiple Clickable objects set to it. So one string has many Clickable objects and depending on which word/section the User clicks the app will go on and do the processing of that click event. The other day I had asked here on stackoverflow about getting rid of the blue underline on part of the word in the SpannableString and the answer was to sub class the ClickableSpan class, and override the updateDrawState method and setting the underlineText to false which worked.

My Problem: Is it possible to put a border around the Clickable object in the SpannableString? So basically each Clickable object/string has to have there own border.

I thought maybe the updateDrawState method maybe able to help but it didn't. Does anybody know how this can be achieved?

Thanks.

like image 371
Ash Avatar asked Apr 15 '13 23:04

Ash


1 Answers

I extended ReplacementSpan to make an outlined span. Unfortunately, I can't manage to make them wrap, but if you're only looking to apply your outline to a couple words, it should work fine. To make this clickable, you'd just use the subclass you mentioned setSpan(ClickableSpanWithoutUnderline...) before you set this one.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_replacement_span);

    final Context context = this;
    final TextView tv = (TextView) findViewById(R.id.tv);


    Spannable span = Spannable.Factory.getInstance().newSpannable("Some string");
    span.setSpan(new BorderedSpan(context), 0, span.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 

    tv.setText(span, TextView.BufferType.SPANNABLE);
}


public static class BorderedSpan extends ReplacementSpan {
    final Paint mPaintBorder, mPaintBackground;
    int mWidth;
    Resources r;
    int mTextColor;

    public BorderedSpan(Context context) {
        mPaintBorder = new Paint();
        mPaintBorder.setStyle(Paint.Style.STROKE);
        mPaintBorder.setAntiAlias(true);

        mPaintBackground = new Paint();
        mPaintBackground.setStyle(Paint.Style.FILL);
        mPaintBackground.setAntiAlias(true);

        r = context.getResources();

        mPaintBorder.setColor(Color.RED);
        mPaintBackground.setColor(Color.GREEN);
        mTextColor = Color.BLACK;
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        //return text with relative to the Paint
        mWidth = (int) paint.measureText(text, start, end);
        return mWidth;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        canvas.drawRect(x, top, x + mWidth, bottom, mPaintBackground);
        canvas.drawRect(x, top, x + mWidth, bottom, mPaintBorder);
        paint.setColor(mTextColor); //use the default text paint to preserve font size/style
        canvas.drawText(text, start, end, x, y, paint);
    }
}
like image 190
adamdport Avatar answered Sep 30 '22 00:09

adamdport