8

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..

xtreak
  • 1,376
  • 18
  • 42

6 Answers6

20

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.

Vishnu M.
  • 971
  • 1
  • 10
  • 18
  • Are these in the MainActivity where this code goes? Also, do you create another main class to do this? I'm new to Kotlin and Android studio, still learning. – Adan Vivero Nov 06 '21 at 20:45
1

Android Html.fromHTML does not support all tags.

If you want such tags I suggest you use a WebView instead

WebView webview = new WebView(this);

String summary = "<html><body>Sorry, <span style=\"background: red;\">Madonna</span> gave no results</body></html>";

webview.loadData(summary, "text/html", "utf-8");

A WebView will allow you to have HR or whatever tag you like

cjds
  • 269
  • 1
  • 3
  • 12
  • WOnt webview be long to load. I have hundred of lines to load. They are plain text except in some places I use the
    tag. Are there any way to recreate that effect with other tags like
    – xtreak Oct 18 '13 at 08:50
  • I don't think the delay will be THAT long. There are a lot of ways to do it without using the HTML such as splitting the text into an array of textviews. But I think WebView the best bet – cjds Oct 18 '13 at 09:08
  • I have to add hundreds of lines. So too many textviews will not be feasible. Any idea of using div tag? I tried this code . But doesn't display any line String dynamicText = "textGenerated"; String message = "" + dynamicText + ""; myTextView.setText(Html.fromHtml(message)); – xtreak Oct 18 '13 at 09:17
0

hr tag is not supported in Android. you will have to add a separate view for the horizontal line with background color as your text.

rachit
  • 1,981
  • 15
  • 23
  • Is there any way to recreate that effect with supported tags? like div tag? – xtreak Oct 18 '13 at 08:48
  • 1
    I tried div just now. Apparently it cant work as hr by using width 100% and background OR using border width. So you will have to use separate view only or you can go with WebView. it supports all html tags and you will have more flexibility. – rachit Oct 18 '13 at 09:05
  • Thanks rachit for trying. I load 100's of lines from a database from and then display in a single textView. Adding a view for each horizonal line won't be feasible. Also I need to increase textsize and decrease and many other things for which the option is to use TextView. Sadly it isn't supported. – xtreak Oct 18 '13 at 09:10
  • String dynamicText = "textGenerated"; String message = "" + dynamicText + ""; myTextView.setText(Html.fromHtml(message)); I tried this but it doesn't work. Any idea?? – xtreak Oct 18 '13 at 09:12
  • . also this one.. If it works for you or you find something tell me and I can add that code to the database statements where I want to add the horizontal line. – xtreak Oct 18 '13 at 09:13
0

Try this for horizontal line

View line = new View(this);
line.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 1));
line.setBackgroundColor(Color.rgb(51, 51, 51));
layout.addView(line);
Amit Prajapati
  • 13,525
  • 8
  • 62
  • 84
  • It might be easier to use something like `LinearLayout.LayoutParams` instead of `LayoutParams`. Also the width and height in the constructor are in pixel units, so you would probably need to convert "1" to "1 dip as pixels" using the technique from https://stackoverflow.com/questions/8399184/convert-dip-to-px-in-android – Mr-IDE Jul 29 '18 at 14:10
0

hr tag is not supported in Android, My suggestion is do like this if u want line

in Activity:

TextView tt = (TextView)findViewById(R.id.textView1);
LinearLayout LL = (LinearLayout)findViewById(R.id.ll1);

String message = "Hello <br> hai<br> I am fine <hr>";
tt.setText(Html.fromHtml(message));

View hLine = new View(this);
hLine .setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 1));
hLine .setBackgroundColor(Color.WHITE);
LL.addView(hLine );

in Xml:

 <LinearLayout
        android:id="@+id/ll1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="textView1"
            android:textAppearance="?android:attr/textAppearanceMedium" />
    </LinearLayout>
NareshRavva
  • 823
  • 3
  • 21
  • 50
  • I load data from database. 100s of lines. so the idea is to add the hr tag in appropriate places. But its not supported. So is there any tag that can recreate that effect? – xtreak Oct 18 '13 at 09:24
-1

You add a view of height 1 or 2, width set to match parent, and specify the background color. But that means you will have 3 text views.

This is from working code. As you see, any child of view will do:

        <!-- divider 1 -->
        <LinearLayout
            android:id="@+id/lineA"
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="#000000" />

Another option is to use a WebView which definitely does support <hr>, but that most likely will be an overkill.

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127