42

I have some text that have more than one paragraph (using "\n") and want to put a spacing between the paragraphs, but without using "\n\n". But the text from the same paragraph I want to keep them with a lower space.

I tried using lineSpacingExtra and lineSpacingMultiplier but it sets spaces to every line (insinde the paragraph too).

I want something like this:

Multiparagraph padding

IIRed-DeathII
  • 1,117
  • 2
  • 15
  • 34
  • If you are wanting that much control over the space between paragraphs, you might be better off putting the second paragraph in another TextView and spacing them with margins and padding. – NoChinDeluxe Oct 13 '15 at 14:30
  • The problem is that I dont know how many paragraphs will have the text. I wanted to know is there is any simpler way to add spaces without adding textviews dinamically with margins between them – IIRed-DeathII Oct 13 '15 at 14:31
  • Well the image you posted in your question is what you should get with `\n\n`. So if you're not getting that, then something else is wrong. – NoChinDeluxe Oct 13 '15 at 14:36
  • Image is simple representation... The problem is the way is asked. Please READ – IIRed-DeathII Oct 13 '15 at 15:19
  • Yes, and please READ my comment. If you want to add a line between paragraphs, then `\n` is the way to do it. If you are getting more space than a single line with that method, then something else is wrong with your text/formatting/code. – NoChinDeluxe Oct 13 '15 at 15:36
  • 4
    "I want to put spacing between the paragraphs, BUT WITHOUT USING \n\n". I think you are not READING my question. I want diferent spacing if its diferent lines from same paragraph or diferent paragraph. \n\n current spacing is too big, and want to edit it. CLEAR? – IIRed-DeathII Oct 14 '15 at 13:06
  • @Diie Any success on this? – user2520215 Apr 29 '16 at 13:07
  • @IIRed-DeathII is below answered not help you? Specially Spannable solution? – Jitesh Mohite Apr 11 '18 at 03:29
  • @bgolson the Ermat Alymbaev answer use Spannable and it working well. why you do not use it? – Linh Apr 12 '18 at 01:30

7 Answers7

35

You can use Spannable's to achieve this:

String formattedText = text.replaceAll("\n", "\n\n");
SpannableString spannableString = new SpannableString(formattedText);

Matcher matcher = Pattern.compile("\n\n").matcher(formattedText);
while (matcher.find()) {
    spannableString.setSpan(new AbsoluteSizeSpan(25, true), matcher.start() + 1, matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}

The code above replaces all line breaks with two line breaks. After that it sets absolute size for each second line break.

Ermat Alymbaev
  • 721
  • 6
  • 15
  • Not working for me. This reduces the size of the text in the line, but does not decrease the size of the line. – maXp Feb 15 '21 at 04:45
  • I used this solution and convert it into Kotlin extensions https://stackoverflow.com/a/76416438/10725071 – P1NG2WIN Jun 06 '23 at 16:02
4

You can use

Html.fromHtml(String);

This will help you to write string in form of html where you can use the html tags like <p>, <h1> etc

Eg:

myTextView.setText(Html.fromHtml("<p>This is it first<br>paragraph.</p><p>This is the second<br>paragraph.</p>"));
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
aswal94
  • 145
  • 2
  • 14
3

I have faced a similar problem. Finally, I fixed with spanable text for newline character. Here is the code goes.

    String text ="Lorem ipsum dolor sit amet, End of first line.\nBegining of the second line, Aenean justo mi, faucibus eu suscipit id, finibus gravida quam. End of Second Line.\nBegining of the third line, Aliquam ac diam tempus, pharetra nibh at, imperdiet diam.  End of Third Line.\n Begining of the fourth line, Fusce placerat erat dolor, id tristique lacus gravida ac. End of Fourth Line.\nBegining of the Fifth line, Sed id molestie est, sed elementum lectus.  End of Fifth Line.\n";

    text = text.replace("\n","\n\0");
    Spannable spannable = new SpannableString(text);
    for (int i = 0; i < text.length()-1; i++) {
        if (text.charAt(i) == '\n') {
            spannable.setSpan(new RelativeSizeSpan(1.5f), i+1, i+2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    }
    mTextMessage.setText(spannable, TextView.BufferType.SPANNABLE);
Sai Prasad
  • 286
  • 1
  • 2
  • 13
2

The answer above doesn't work for me, but the basic idea is correct, adding an empty line and changing its height gives the desired result. However, a working way of changing the line height in my case is as follows:

private fun insertParagraphSpacing(text: CharSequence, spacing: Int): CharSequence {
    val stringBuilder = SpannableStringBuilder(text)

    Regex(lineSeparator()).findAll(text).forEachIndexed { index, match ->
      val span = ParagraphSpacingSpan(lineHeight, spacing)

      val separator = SpannableString(lineSeparator())
      separator.setSpan(span, 0, separator.length, SPAN_EXCLUSIVE_EXCLUSIVE)

      stringBuilder.insert(match.range.last + 1 + index * separator.length, separator)
    }

    return stringBuilder
  }

And the implementation of ParagraphSpacingSpan is as follows:

class ParagraphSpacingSpan(
  @Px @IntRange(from = 1) val lineHeight: Int,
  @Px @IntRange(from = 0) val spacing: Int
) : LineHeightSpan {

  override fun chooseHeight(t: CharSequence, s: Int, e: Int, v: Int, l: Int, fm: FontMetricsInt) {
    val textHeight: Int = fm.descent - fm.ascent

    fm.descent = textHeight - lineHeight + spacing
    fm.ascent = 0
  }
}

lineHeight is the value of the TextView field in which the line is displayed.

maXp
  • 1,428
  • 1
  • 15
  • 23
1

I'm afraid it's not adjustable in TextView. Here is the document of all the TextView attributes: https://developer.android.com/reference/android/R.styleable#TextView I guess the best way of doing this could be using one TextView for each paragraph, and then define margin between TextView.

I think it's a similar design conception as p tag in html. Within the tag is a whole paragraph, then define the layout of p tag.

Won Lure
  • 11
  • 1
1

No need to manipulate spacing between paragraphs.

FROM_HTML_MODE_LEGACY: Separate block-level elements with blank lines (two newline characters) in between. This is the legacy behavior prior to N.

textView.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY)
    } else {
        Html.fromHtml(html)
    }
Juan Mendez
  • 2,658
  • 1
  • 27
  • 23
0

I used AbsoluteSizeSpan solution and convert it into Kotlin extensions

https://stackoverflow.com/a/76416438/10725071

P1NG2WIN
  • 764
  • 1
  • 9
  • 24