How can I draw a zigzag underline on a specific text of an EditText, similar to a spell-check underline?

119 Views Asked by At

Description: I want to be able to draw a zigzag line span on a text with a given start and end position of an EditText in Android. I have tried using a custom ReplacementSpan class to draw the zigzag line, but when I try to modify the underlined text (such as deleting one character), the whole underlined text is deleted and the cursor cannot be placed inside the underlined text.

Demo:

enter image description here

Code: Here's a code snippet of the ZigzagUnderlineSpan class I'm using.

public class ZigzagUnderlineSpan extends ReplacementSpan {
    private final int mColor;

    public ZigzagUnderlineSpan(int color) {
        this.mColor = color;
    }

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

    @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 endX = x + paint.measureText(text, start, end);

        //Create zigzag path
        Path path = createZigzagLine(x, endX, bottom, 5);

        //Save state of paint
        final int originalColor = paint.getColor();
        Paint.Style originalStyle = paint.getStyle();

        //Set color and stock
        paint.setColor(mColor);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawPath(path, paint);

        // Restore original state of paint
        paint.setColor(originalColor);
        paint.setStyle(originalStyle);

        // Draw the text
        canvas.drawText(text, start, end, x, y, paint);
    }

    /**
     * create zigzag path: /\/\/\/\/\/\
     * @param startX the start x
     * @param endX the end x
     * @param bottomY bottom y position
     * @param step half period of the zigzag line
     * @return path
     */
    private Path createZigzagLine(float startX, float endX, float bottomY, float step) {
        float topY = bottomY - step;
        Path path = new Path();
        path.moveTo(startX, bottomY);
        for (float x = startX; x< endX; x += step) {
            int i = (int) ((x - startX)/step);
            path.lineTo(x, i % 2 == 0 ? bottomY : topY);
        }
        return path;
    }
}

Here is how I use it:

SpannableStringBuilder spannable = new SpannableStringBuilder(editText.getText());
spannable.setSpan(new ZigzagUnderlineSpan(Color.RED), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spannable);

Question: Can you help me fix this issue so that I can modify the underlined text and put the cursor inside it? or even using another approach to achieve what i want.

0

There are 0 best solutions below