Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<hr> tag usage in android

I have a statement to for which I have to add up an horizontal line. But its not supported by android it seems is there any way to recreate the


tag effect in android using supported tags.
String message = "Hello <br> hai<br> I am fine <hr>";
tab.setText(Html.fromHtml(message));

It shows Hello
hai
I am fine

But no horizontal line.

Here the HTML tag of "hr" is not working. Are there any ways to add hr tag effect from the supported tags. Thanks in advance..

like image 451
xtreak Avatar asked Oct 18 '13 08:10

xtreak


Video Answer


1 Answers

Html.fromHtml() doesn't support the <hr> tag at the moment so you will need to write your own tag handler that implements Html.TagHandler. TextViews in Android are styled using Spans, so we will need to create a Span that draws a horizontal line as well, let's call it HrSpan.

Java

String html = "Hello <br> hai<br> I am fine <hr> And here's another line";

HtmlTagHandler tagHandler = new HtmlTagHandler();
Spanned styledText = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY, null, tagHandler);
textView.setText(styledText);

HtmlTagHandler.java

public class HtmlTagHandler implements Html.TagHandler {

    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
        if (tag.equals("hr")) {
            handleHrTag(opening, output);
        }
    }

    private void handleHrTag(boolean opening, Editable output) {
        final String placeholder = "\n-\n";
        if (opening) {
            output.insert(output.length(), placeholder);
        } else {
            output.setSpan(new HrSpan2(), output.length() - placeholder.length(), output.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }
}

HrSpan.java

public class HrSpan extends ReplacementSpan {

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

    @Override
    public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(8); // 8px tall line

        int middle = (top + bottom) / 2;
        // Draw a line across the middle of the canvas
        canvas.drawLine(0, middle, canvas.getWidth(), middle, paint);
    }
}

Kotlin

val html = "Hello <br> hai<br> I am fine <hr> Another line here <hr><hr>"
val tagHandler = HtmlTagHandler()

textView.text = HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY, null, tagHandler)

class HtmlTagHandler : Html.TagHandler {

    override fun handleTag(opening: Boolean, tag: String?, output: Editable?, xmlReader: XMLReader?) {
        if (output == null) return

        when (tag) {
            "hr" -> handleHrTag(opening, output)
            // Handle other tags if needed
        }
    }

    private fun handleHrTag(opening: Boolean, output: Editable) {
        val placeholder = "\n-\n" // Makes sure the HR is drawn on a new line
        if (opening) {
            output.insert(output.length, placeholder)
        } else {
            output.setSpan(HrSpan(), output.length - placeholder.length, output.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }
}

class HrSpan : ReplacementSpan() {

    override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?) = 0

    override fun draw(
        canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int,
        bottom: Int, paint: Paint
    ) {
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = 8f

        // Draw line in the middle of the available space
        val middle = ((top + bottom) / 2).toFloat()

        canvas.drawLine(0f, middle, canvas.width.toFloat(), middle, paint)
    }
}

This should give you a result something like this. It matches the width of your TextView so change the TextView width attribute to match_parent if you want the line to take up the full width.

like image 171
Vishnu M. Avatar answered Sep 21 '22 23:09

Vishnu M.