1

I'm trying to create a textview within a bottomsheetdialog, with example layout as shown below. I've put my desired formatting notes in brackets Most of the spanned texts (bold, underlined etc.) are easy to create

Linespacing of 2 is easy with "\n\n", but how do I create 1.5 line spacing between certain lines? I'm adding text dynamically, using append(...), so I can't use the android:text atribute in the layout xml. Most of the examples I've seen have line spacing hard-wired into xml too which applies to all the text. I've found that you can apply different line spacings for paragraphs, but the "\n" would break the paragraph and the different line spacing won't work.

title (underlined, bold, very large)
(linespace 1.5)
blurb
(linespace 2)
sub-section1 (underlined, bold, large)
(linespace 1.5)
ClickableSubheading1 
(linespace 1.5)
clickableSubheading2
(linespace 1.5)
[could be many more subheadings here...]

(linespace 2)
sub-section2 (underlined, bold, large)
(linespace 1.5)
ClickableSubheading1a 
(linespace 1.5)
clickableSubheading2a
(linespace 1.5)
[could be many more subheadings here...]


etc - more subsections to be added as and when needed

NB: the clickable sub headings apply code implicit to the app, and are not hyperlinks (I thought about doing the whole lot as html and then reading that into my textview) Basically, what I need is a span, or similar that says "put a linebreak, m times '\n' here", where 'm' can be any value

user3713442
  • 478
  • 8
  • 22

2 Answers2

6

You can use RelativeSizeSpan to scale the size of the second '\n' to smaller value.

Like

// I try to find all '\n\n' in TextView then I resize the second \n size to 0.5
private fun beautifulParagraph(textView: TextView) {
    val text = textView.text
    var startIndex = 0
    val sb = SpannableString(text)
    var index: Int
    while (text.indexOf("\n\n", startIndex).also { index = it } != -1) {
        sb.setSpan(RelativeSizeSpan(0.5f), index + 1, index + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        startIndex = index + 2
    }
    textView.text = sb
}

Using

beautifulParagraph(yourTextView)

XML

<TextView
        android:id="@+id/tv_heelo"
        android:layout_width="150dp"
        android:layout_height="match_parent"
        android:text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\nbbbbbbbbbbbbbbbnbbbbbbbbbbbbbbbnbbbbbbbbbbbbbbbnbbbbbbbbbbbbbbb\n\nccccccccccccccccnccccccccccccccccnccccccccccccccccnccccccccccccccccncccccccccccccccc\n\nddd"
        android:textSize="15sp"
        android:layout_margin="20dp"
        android:background="#000"
        android:textColor="#fff"
/>

Result (without resize and with resize)

------>

Linh
  • 57,942
  • 23
  • 262
  • 279
  • Thanks, this i interesting. I didn't think Relative Size Span worked on "\n"? If thats the case, I could do: SpannableString string = new SpannableString("\n"); string.setSpan(new RelativeSizeSpan(1.5f), 0,1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); – user3713442 Jul 05 '19 at 12:12
  • I tried it and it not working well. It quite hard to explain, you can try it then you will see the problem and understand why ^^. It work in different way to our expectation – Linh Jul 05 '19 at 12:28
  • The only problem I have with your solution is that my text is full of spans to show underline, bold etc. and onClick operator, and I don't know how well this post-processing of text would work. – user3713442 Jul 05 '19 at 13:00
  • I still dont understand why you can not apply. You know how to set multiple type span to 1 span, now just add 1 more type (RelativeSpan) to your current span. In my answer I write a function which easy to use for this case only but the basic idea just relativespan – Linh Jul 05 '19 at 14:29
  • Actually, it looks like I can use this, or a variation of it. Thanks! – user3713442 Jul 06 '19 at 10:56
0
  1. You can use lineSpacingExtra and lineSpacingMultiplier in your XML file.
  2. You can use Span to customize what you want in textview https://developer.android.com/guide/topics/text/spans

  3. Or you can custom what you want in HTML and display HTML in TextView

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        textView.setText(Html.fromHtml(htmlString, Html.FROM_HTML_MODE_COMPACT));
    } else { 
        textView.setText(Html.fromHtml(htmlString));
    }
    

These what can i suggestion for you.

Mahmoud Waked
  • 357
  • 2
  • 8