如何在TextView中禁用自动换行?

3

我有一个TextView,其中包含一个随机的60个字符的字符串。

该字符串是一个单词,不包含任何空格。

问题在于,在某些字符(例如@、&、%)之后,会出现自动换行,而我不想要这种情况。

我的期望结果是每一行都填满到结尾,并且没有随机的换行。

我尝试了设置breakStrategy并更新hyphenationFrequency,但这并没有帮助。

如何防止这种情况发生呢?

enter image description here

更新: 感谢 @Darkman,这是解决方案,我已经编写了代码。它检查每行可以容纳多少个字符而不需要换行,然后在结尾处添加\n

请注意,对于我的用例,字符串中没有空格,并且我使用的是等宽字体。

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

TextView上设置android:maxLines="1" - CommonsWare
自动调整大小会破坏Android设置中用户更改字体大小的可访问性。我真的不想使用它,也不希望从UI角度来看这是单行显示。我的问题不是如何避免换行,而是当行到达布局的末尾时如何进行换行。 - Jokubas Trinkunas
"如果用户在Android设置中更改字体大小,自动调整大小会破坏可访问性" -- 我不明白为什么。自动调整大小将缩小文本以适应用户选择的字体比例尺寸。如果您担心60个字符太小,那么请使用少于60个字符。"从UI角度来看,我不希望这是单行显示" -- 那么...你想要它超过一行,但又不能超过一行?这在数学上如何实现? - CommonsWare
"自适应大小将缩小文本以适应,无论用户选择的字体比例如何,这正是破坏可访问性的原因。如果将字体大小设置为最大(例如通过Android设置),则不会进行缩放。这对于视力受损的用户来说并不理想。我的问题是,我有一个没有空格的长字符串,例如“ifj21324%dsigfjsdig$ @ js%digjsdi”,这显然不能适合一行,我希望它完全可见,但它神奇地在某些字符处换行,例如%,&,@等,而不到达布局的末尾,正如您在屏幕截图中所看到的。" - Jokubas Trinkunas
我不介意我的TextView高度根据需要扩展,问题在截图中清晰可见,如果您查看第一行,您会发现它跳到下一行而没有到达布局的末尾,同样的情况也出现在第二行,虽然第三行长度是可以接受的,这也是我想要实现的每一行的效果。 - Jokubas Trinkunas
显示剩余4条评论
3个回答

1

要达到您想要的结果,一种方法是使用等宽字体、左对齐和一点编程。

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

或者

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

或者

// 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"));

在布局被测量之后,您需要调用其中的一个方法。这意味着在onCreate()onCreateView()或类似方法之外进行调用。

enter image description here


谢谢,你的回答帮助我解决了问题。我已经更新了我的问题并实现了它。虽然思路相同,但执行方式有所不同。 - Jokubas Trinkunas

0
如果您的API级别为26+,则可以使用以下XML标记在Android中设置对齐方式。
android:justificationMode="inter_word"

或者您可以使用this GitHub 库来处理所有的 API 级别


谢谢您的回答。我已经尝试了两种解决方案,但它们都不起作用,因为在这种情况下,我的字符串是一个非常长的单词。它仍然会自动跳到下一行,包括字符%、&、@、!和其他一些字符。 - Jokubas Trinkunas

0

我知道这个解决方案有点奇怪,但如果有什么不理想的地方或者在不久的将来找不到任何解决方案,那么你可以使用:

        <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>

谢谢您的建议,但这不是我想要的。我宁愿完全看到带有“神奇”换行符的字符串。 - Jokubas Trinkunas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接