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());
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:
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.