Individual line spacing for each line
Asked Answered
G

7

10

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 ?

Geneviegenevieve answered 20/6, 2012 at 0:1 Comment(0)
B
19

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);
    }

}
Beast answered 20/6, 2012 at 13:3 Comment(4)
This seems to add extra space of size 40 after Line 4. Is there an elegant way to get rid of this extra space?Wastrel
@Wastrel I added tv.getEditableText().append("Line 5\nLine 6"); after the last appendLine() call in onCreate() and didn't see the extra space that you mentioned, maybe we are not talking about the same thing?Beast
You also have to set the BufferType back to BufferType.NORMAL, so the TextView's style persists. I had this issue in a recycler view, where the TextView lost its style because of that, so after you append every line, don't forget to setText(getText(), BufferType.NORMAL);Sigfrid
How can I do this with regular expressions? I'm not appending lines and on which line is the text matched by my regular expression. I'm using mutliple superscripts and my text is overlapping, so is there a way to do it?Rajah
N
3

Android 10 (API 29) added LineHeightSpan.Standard to 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;
    }
}
Nolde answered 26/11, 2019 at 10:4 Comment(0)
E
1

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>
Elanorelapid answered 20/6, 2012 at 2:59 Comment(1)
while this works it is very expensive since a whole bunch of xml parsing code gets invoked internally. be careful with thisJessicajessie
L
0

Recently I'm faced with a similar problem. I use a string resource from string.xml and display it in a dialog. I solve my issue by using <font> tag inside <string> and specify a font size for \n in it. The first \n is simply a line break, and the second is a new empty line, with height specified by <font size="YOUR_SIZE_FOR_THE_LINE"></font>.

Sample code:

    <string name="specification_msg"><b>1 Quick Action</b>
        \nQuick-Action is a small window which is supposed to be fast so it can offer you a convenient way of recording income and expenditure.
        <font size="4">\n\n</font><b>︎︎1.1 Brief Mode</b>
        \nDate and time will be hidden in window and set to current time. If you scarcely adjust them, turning on this feature will give you a cleaner view.
        <!-- Other lines -->
    </string>

Screenshot: Screenshot of TextView inside AlertDialog

enter image description here

(The line spaces are originally designed for Chinese characters, so the difference may seem less apparent in English.)

I know it's a dirty method but it can sometimes help...

Liverpudlian answered 22/4, 2021 at 4:46 Comment(0)
B
0

I did it via AbsoluteSizeSpan. Kotlin Extensions for add space between text in dip

Usage

buildSpannedString { 
    append("smth")
    spaceInDip(16)
    append("smth2")
}

Code

public fun SpannableStringBuilder.sizeInDip(
    size: Int,
    builderAction: SpannableStringBuilder.() -> Unit
): SpannableStringBuilder = inSpans(
    AbsoluteSizeSpan(size, true),
    builderAction = builderAction
)

public fun SpannableStringBuilder.spaceInDip(
    size: Int
): SpannableStringBuilder = sizeInDip(
    size = size,
    builderAction = {
        appendLine()
        sizeInDip(size) { appendLine() }
    }
)
Ballyhoo answered 6/6, 2023 at 16:1 Comment(0)
A
-3

Its not possible.This technique is use in c ,c++.What you use inside setText(),it shows the whole text you write .

Azevedo answered 20/6, 2012 at 3:3 Comment(0)
D
-3

Try this:

android:lineSpacingMultiplier = "3"

Line spacing can also be in decimal format.

Detour answered 31/3, 2015 at 9:15 Comment(2)
I haven't had a chance to verify this 100% but I think this actually solves the problem for my use case, not sure why it was down voted.Voorhees
@HuskyHuskie This changes the line spacing for the entire view, while OP wants to change the line spacing for individual lines.Deadfall

© 2022 - 2024 — McMap. All rights reserved.