Search code examples
androidandroid-layouttextviewline-breaks

How to disable automatic line breaking in TextView?


I have a TextView which contains a random string of 60 characters.

The string is a single word and does not contain any white spaces.

The problem is that after certain characters (e.g. @, &, %) I get an automatic line break which I do not want.

My desired outcome is that every line is filled up to the end and no random line breaks are present.

I have tried setting breakStrategy and updating hyphenationFrequency, but this has not helped.

How can I prevent this from happening?

enter image description here

UPDATE: Thanks to @Darkman, this is the solution, which I have written. It checks how many characters can fit into a single line without line-breaks and appends \n at the end.

Be aware that for my use case string has no blank spaces and I am using a monospace font.

fun TextView.toNonBreakingString(text: String?): String {
    if (text == null) return ""
    val container = parent as? ViewGroup ?: return text

    val lineWidth = (container.width - container.paddingStart - container.paddingEnd).toFloat()
    val maxCharsInOneLine = paint.breakText(text, 0, text.length, true, lineWidth, null)
    if (maxCharsInOneLine == 0) return text

    val sb = StringBuilder()
    var currentLine = 1
    var end = 0
    for (i in 0..text.count() step maxCharsInOneLine) {
        end = currentLine * maxCharsInOneLine
        if (end > text.length) end = text.length
        sb.append(text.subSequence(i, end))
        sb.append("\n")
        currentLine = currentLine.inc()
    }

    if (end < text.length) {
        val remainingChars = text.length - end
        sb.append(text.takeLast(remainingChars))
    }

    return sb.toString()
}

Solution

  • One way to achieve your desired result is by using monospace font, left gravity and a little bit programming.

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="200dp"
     
       android:text="akAOCYMKIpVmSwhHtWS%fBFK7eWi%19a590344gZqGQtkTcRv^1lFqH#F@Lhr"
        android:gravity="left"
        android:background="#708BCD"
        android:id="@+id/tv"
        android:textSize="20sp"
        android:typeface="monospace"/>
    
    //Note :: Auto-updated
    public final void wrapText(final TextView textView, final String text)
    {
        final float textSize = (textView.getTextSize() / 250F) * 150F;
        final int textLen = text.length();
        final int columns = (int)(textView.getWidth() / textSize);
        final int lines = (int)((float) textLen / columns);
        final StringBuilder sb = new StringBuilder(textLen + lines);
        for(int i=0, n=0; i < textLen; i+=columns, ++n) {
            sb.append(text.subSequence(i, Math.min(textLen, i + columns)));
            if(n<lines) sb.append("\n");
        }
        textView.setText(sb.toString());
    }
    

    Or

    //Note :: Auto-updated
    public final void wrapText(final TextView textView)
    {
        final float textSize = (textView.getTextSize() / 250F) * 150F;
        final CharSequence text = textView.getText();
        final int textLen = text.length();
        final int columns = (int)(textView.getWidth() / textSize);
        final int lines = (int)((float) textLen / columns);
        final StringBuilder sb = new StringBuilder(textLen + lines);
        for(int i=0, n=0; i < textLen; i+=columns, ++n) {
            sb.append(text.subSequence(i, Math.min(textLen, i + columns)));
            if(n<lines) sb.append("\n");
        }
        textView.setText(sb.toString());
    }
    

    Or

    // Note :: Self-update
    public final String wrapText(final TextView textView, final String text)
    {
        final float textSize = (textView.getTextSize() / 250F) * 150F;
        final int textLen = text.length();
        final int columns = (int)(textView.getWidth() / textSize);
        final int lines = (int)((float) textLen / columns);
        final StringBuilder sb = new StringBuilder(textLen + lines);
        for(int i=0, n=0; i < textLen; i+=columns, ++n) {
            sb.append(text.subSequence(i, Math.min(textLen, i + columns)));
            if(n<lines) sb.append("\n");
        }
        return sb.toString();
    }
    
    // Implementation:
    // textView.setText(wrapText(textView, "akAOCYMKIpVmSwhHtWS%fBFK7eWi%19a590344gZqGQtkTcRv^1lFqH#F@Lhr"));
    

    And you need to call either one of the methods after the layout has been measured. That means outside of onCreate(), onCreateView() or something similar.

    enter image description here