【问题标题】:How to disable automatic line breaking in TextView?如何在 TextView 中禁用自动换行?
【发布时间】:2021-08-27 08:32:29
【问题描述】:

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

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

问题是在某些字符之后(例如@, &, %)我得到一个我不想要的自动换行符。

我想要的结果是每一行都被填满,并且没有随机的换行符。

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

如何防止这种情况发生?

更新:感谢@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"
  • 如果它适合一行当然没有换行问题:) 正如您在屏幕截图中看到的那样,它并不总是适合一行,我希望我的字符串完全可见。
  • 然后设置android:maxLines="1",设置合适的布局规则来控制宽度,并使用autosize属性根据字符串的长度自动减小字体大小。
  • 如果用户在 Android 设置中更改字体大小,Autoresize 会破坏可访问性。我真的不想使用它,也不想从 UI 角度来看它是单行的。我的问题不是如何避免换行,而是如何仅在行到达布局末尾时才换行。
  • “如果用户在 Android 设置中更改字体大小,自动调整大小会破坏可访问性”——我不知道如何。无论用户选择的字体比例如何,自动调整大小都会缩小文本以适应。如果您担心 60 个字符太小,请使用少于 60 个字符。 “从 UI 的角度来看,我不希望这是单行”——所以......您希望它不止一行,但不超过一行?这在数学上是如何工作的?

标签: android android-layout textview line-breaks


【解决方案1】:

实现所需结果的一种方法是使用monospace 字体、左重力和一点点编程。

<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() 或类似的东西之外。

【讨论】:

  • 谢谢,您的回答帮助我想出了一个解决办法。我已经用我的实施更新了我的问题。相同的想法,但执行方式略有不同。
【解决方案2】:

如果您的 API 级别为 26+,那么您可以使用以下 XML 标签在 android 中设置对齐方式。

android:justificationMode="inter_word"

或者您可以使用this GitHub 库来获取所有 API 级别

【讨论】:

  • 感谢您的回答。我已经尝试了这两种解决方案,但它们都不起作用,因为在这种情况下,我的字符串是一个很长的单词。它仍然会自动跳到字符 %,&,@ 的下一行!和其他一些人。
【解决方案3】:

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

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

【讨论】:

  • 感谢您的建议,但这不是我想要的。我宁愿使用“魔术”换行符来全面了解字符串。
猜你喜欢
  • 1970-01-01
  • 2012-07-27
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-28
  • 1970-01-01
  • 2013-12-20
相关资源
最近更新 更多