How to disable automatic line breaking in TextView?

Viewed 1204

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()
}
3 Answers

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

If your API level is 26+ then you can use the following XML tag to set the justification in android.

android:justificationMode="inter_word"

Or you can use this GitHub library for all the API levels

I know this solution is little bit odd but if anything is not desirable or if you did't find any solution in near future, then you can use:

        <HorizontalScrollView
            android:fillViewport="true"
            android:scrollbars="none"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >
            <TextView
                android:id="@+id/file_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:maxLines="1"
                android:textStyle="bold"
                android:text="@string/file_name"
                android:textColor="?attr/primaryText"/>

        </HorizontalScrollView>
Related