Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Span Underline Text with Dotted line Android

I was tiring to underline a specific word in the text with a dotted or dashed line with and also Clickable Span.

I haven't found a solution can someone help me, please.

SpannableStringBuilder sb = new SpannableStringBuilder(text); List listmot = new ArrayList();

       listmot=db.getAlldef();

       for(int i=0;i<listmot.size();i++)
       {


            String mot = (listmot.get(i)).get_mot();
            final String def = (listmot.get(i)).get_definition();

       Log.v(null, mot);
       Pattern p = Pattern.compile(mot, Pattern.CASE_INSENSITIVE);
       Matcher m = p.matcher(text);
       while (m.find()){


         //  Typeface tf = Typeface.createFromAsset(getApplicationContext().getAssets(),"fonts/font.ttf");
           //sb.setSpan(new CustomTypefaceSpan("",tf), m.start(), m.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

      sb.setSpan(new ClickableSpan() {

        @Override
        public void onClick(View widget) {
        //  Toast.makeText(getApplicationContext(), def,Toast.LENGTH_LONG).show();



            int[] values = new int[2]; 
            widget.getLocationOnScreen(values);
            Log.d("X & Y",values[0]+" "+values[1]);
            AlertDialog.Builder alertDialog = new AlertDialog.Builder(
                    AndroidSQLiteTutorialActivity.this);
            alertDialog.setMessage(def);
            alertDialog.setCancelable(true);

            AlertDialog alert11 = alertDialog.create();
            alert11.setCanceledOnTouchOutside(true);

            alert11.show();

        }
    }, m.start(), m.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

       } 

       }



       textjson.setText(sb);
       textjson.setMovementMethod(LinkMovementMethod.getInstance());
like image 368
Sami Ben Lassoued Avatar asked Mar 31 '15 18:03

Sami Ben Lassoued


People also ask

How do you make a dash line on android?

Go to res > drawable > new > drawable resource file and create a new file and name it “dashed_underline. xml” and define all properties of the dashed line that we need.

How can I span text in Android?

If you need to attach a small number of spans to a single text object, and the text itself is read-only, use SpannableString . If you need to modify text after creation, and you need to attach spans to the text, use SpannableStringBuilder .

What is a Spannable in Android?

Text styling is one of the important aspects when it comes to enhancing the UI of an Android application. In Android, we can change the size, color, weight, style, etc of a text and make the text more attractive and appealing.


1 Answers

EDIT: I have updated solution. Sometimes that drawBackground method in solution with LineBackgroundSpan just haven't been called for no reasons. New version works all the time and looks much clearer.

I met the same problem and i solved it by combining this solutions:

  • this https://stackoverflow.com/a/21097663/5373069 and
  • this https://stackoverflow.com/a/6104138/5373069

The result code looks like this:

private static class DottedUnderlineSpan extends ReplacementSpan {
    private Paint p;
    private int mWidth;
    private String mSpan;

    private float mSpanLength;
    private boolean mLengthIsCached = false;

    public DottedUnderlineSpan(int _color, String _spannedText){
        p = new Paint();
        p.setColor(_color);
        p.setStyle(Paint.Style.STROKE);
        p.setPathEffect(new DashPathEffect(new float[]{mDashPathEffect, mDashPathEffect}, 0));
        p.setStrokeWidth(mStrokeWidth);
        mSpan = _spannedText;
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        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.drawText(text, start, end, x, y, paint);
        if(!mLengthIsCached)
            mSpanLength = paint.measureText(mSpan);

        // https://code.google.com/p/android/issues/detail?id=29944
        // canvas.drawLine can't draw dashes when hardware acceleration is enabled,
        // but canvas.drawPath can
        Path path = new Path();
        path.moveTo(x, y + mOffsetY);
        path.lineTo(x + mSpanLength, y + mOffsetY);
        canvas.drawPath(path, this.p);
    }
}

To make your underline look the same on all densities set that dimens in dp

mStrokeWidth = context.getResources().getDimension(R.dimen.stroke_width);
mDashPathEffect = context.getResources().getDimension(R.dimen.dash_path_effect);
mOffsetY = context.getResources().getDimension(R.dimen.offset_y);

And this is how you use it:

  DottedUnderlineSpan dottedUnderlineSpan = new DottedUnderlineSpan(0xFF00FF00, spannedText);
  spannableString.setSpan(dottedUnderlineSpan, startOfText, endOfText, Spanned.SPAN_INCLUSIVE_INCLUSIVE);

And be sure that you turn off hardware acceleration on textView that will show the underline span. https://stackoverflow.com/a/24467362/5373069

EDIT: if you see ways to improve this solution i would appreciate any good points.

like image 184
Illia K. Avatar answered Oct 17 '22 01:10

Illia K.