1

I would like to have a custom Spannable like below picture :

enter image description here

I would like to create a Zigzag line under a incorrect words.

How can I do?

S.M_Emamian
  • 17,005
  • 37
  • 135
  • 254
  • 1
    @blackbelt: That would only be true if the entire contents of the `EditText` needed to be undersquiggled. I would interpret the question as meaning only some words (the incorrect ones) need the undersquiggle. – CommonsWare Jun 07 '14 at 18:37
  • @CommonsWare yes, now how can I do? :-? – S.M_Emamian Jun 07 '14 at 18:40
  • I have no idea. :-( I have poked at the source code for some of the `*Span` classes, and none seem to apply an arbitrary effect like this. They all use stock capabilities of text painting. If you merely wanted a regular underline, but in color, you could see how `SuggestionSpan` works... but that uses a hidden method on `TextPaint`. Sorry! – CommonsWare Jun 07 '14 at 18:43
  • tnx, how can I create a Zigzag line under a text on textview ? – S.M_Emamian Jun 07 '14 at 18:54

1 Answers1

0

You most definitely want to do some checking on this implementation I hacked together. But still. It's in hopes it still manages to give some basis for implementing such a feature properly.

Actual span class, which, surprisingly ,doesn't replace anything. Only hopes that it really is possible to draw the original span text as-is given two lines of code. Plus additionally draws the 'underline'.

private class ErrorSpan extends ReplacementSpan {

    private Paint errorPaint;

    public ErrorSpan() {
        errorPaint = new Paint();
        errorPaint.setColor(Color.RED);
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end,
            FontMetricsInt fm) {
        return (int)paint.measureText(text, start, end);
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end,
            float x, int top, int y, int bottom, Paint paint) {
        // Render the red zigzag lines below text
        float width = paint.measureText(text, start, end);
        canvas.save();
        canvas.clipRect(x, bottom - 5, x + width, bottom);
        for (float lineX = x; lineX < x + width; lineX += 10) {
            canvas.drawLine(lineX, bottom - 5, lineX + 5, bottom, errorPaint);
            canvas.drawLine(lineX + 5, bottom, lineX + 10, bottom - 5, errorPaint);
        }
        canvas.restore();
        // Render the span text as-is
        canvas.drawText(text, start, end, x, y, paint);
    }    
};

Pardon me for using magic numbers in line drawing loop (which quite likely could be way more effective too) - but hopefully it manages to give good enough basis for creating production quality implementation at the end.

And usage would be somewhere around:

TextView tv = (TextView)findViewById(R.id.textview);
Spannable spannable = Spannable.Factory.getInstance()
                         .newSpannable("testtest\ntesttest");
spannable.setSpan(new ErrorSpan(), 4, 8, 0);
spannable.setSpan(new ErrorSpan(), 9, 13, 0);
tv.setText(spannable);
harism
  • 6,011
  • 1
  • 36
  • 31