Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Individual line spacing for each line

Is it possible to define individual line spacings for each text line of a TextView?

Example:

TextView tv = new TextView(context);
tv.setText("line1\nline2\nline3");

The method setLineSpacing(float add, float mult) defines the line spacings for all text lines of the TextView. I would like to define another line spacing between line1 and line2 and a different line spacing between line2 and line3.

Any ideas how to do this ?

Does a spannable provide a solution ?

like image 978
Anne Droid Avatar asked Jun 20 '12 00:06

Anne Droid


3 Answers

Android 10 (API 29) added LineHeightSpan.Standard to do set an absolute line height. If you need backward compatibility, use the following implementation which I based on LineHeightSpan.Standard:

private static class AbsoluteHeightSpan implements LineHeightSpan {
    private final int _height;

    AbsoluteHeightSpan(int height) {
        _height = height;
    }

    @Override
    public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, FontMetricsInt fm) {
        final int originHeight = fm.descent - fm.ascent;
        // If original height is not positive, do nothing
        if (originHeight <= 0)
            return;
        final float ratio = _height * 1.0f / originHeight;
        fm.descent = Math.round(fm.descent * ratio);
        fm.ascent = fm.descent - _height;
    }
}
like image 52
grebulon Avatar answered Nov 16 '22 02:11

grebulon


Yes, you can do it by utilizing the LineHeightSpan interface. Here's a quick and dirty sample code on how to do this:

public class MyActivity extends Activity {

    private static class MySpan implements LineHeightSpan {
        private final int height;

        MySpan(int height) {
            this.height = height;
        }

        @Override
        public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v,
                FontMetricsInt fm) {
            fm.bottom += height;
            fm.descent += height;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final TextView tv = new TextView(this);
        setContentView(tv);

        tv.setText("Lines:\n", BufferType.EDITABLE);
        appendLine(tv.getEditableText(), "Line 1 = 40\n", 40);
        appendLine(tv.getEditableText(), "Line 2 = 30\n", 30);
        appendLine(tv.getEditableText(), "Line 3 = 20\n", 20);
        appendLine(tv.getEditableText(), "Line 4 = 10\n", 10);
    }

    private void appendLine(Editable text, String string, int height) {
        final int start = text.length();
        text.append(string);
        final int end = text.length();
        text.setSpan(new MySpan(height), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

}
like image 19
Joe Avatar answered Nov 16 '22 00:11

Joe


you can do these kind of specific styles to the textview using Html. Try this example,

tv.setText(Html.fromHtml("<h2>Text1</h2><br><p>Text2</p>"));

Different kind of tags allowed here are,

<a href="...">
<b>
<big>
<blockquote>
<br>
<cite>
<dfn>
<div align="...">
<em>
<font size="..." color="..." face="...">
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<i>
<img src="...">
<p>
<small>
<strike>
<strong>
<sub>
<sup>
<tt>
<u>
like image 1
Akilan Avatar answered Nov 16 '22 00:11

Akilan