【问题标题】:Detect where Android's TextView would insert a line break检测 Android 的 TextView 将在何处插入换行符
【发布时间】:2014-10-14 16:10:24
【问题描述】:

我有一个矩形图块,我想将图像和一些文本放入其中。图片不能与文字重叠,图片和文字的大小可以不同。

流程必须手动编码,因为我们必须根据客户的需求对其进行微调。

我尝试了首先使用getTextBounds()measureText() 测量渲染文本边界然后调整字体大小和图像大小使它们不重叠的方法。

如果文本只在一行上,这很好用。

但如果TextView 将文本换行成多行,我无法预测文本边界,因为我不知道TextView 会在哪里插入自动换行符。

如何找出文本中TextView 插入自动换行符的位置?

示例:给定文本

Lorem ipsum dolor sit amet

将被渲染为

| Lorem ipsum    |
| dolor sit amet |

我需要一个可以转换的函数

Lorem ipsum dolor sit amet

Lorem ipsum \ndolor sit amet

【问题讨论】:

  • 查看 StaticLayout 类

标签: android textview multiline


【解决方案1】:

TextView(布局对象)有一些有用的功能来完成你想要完成的工作:

http://developer.android.com/reference/android/text/Layout.html

看看:

getLineCount()

getLineEnd(int line)

您可以根据每个 lineEnd 字符的位置来获取 TextView 字符串的子字符串。

您需要使用getViewTreeObserver() 等到TextView 被绘制之后才能调用它们并从中获取有用的信息。

或者,您可以构建一个自定义 TextView,它可能通过内置方法或向其添加侦听器来提供数据。修改文本大小的自定义 TextView 示例如下:

android ellipsize multiline textview

我已经使用了它并做了类似的修改(就像你想要做的那样)。

【讨论】:

  • 如果 TextView 已经绘制,您必须从不同的线程调用它,否则行数将不正确。 textview.post(new Runnable{ int lineCount = textview.getLineCount(); });
【解决方案2】:

您可能希望将此逻辑包装到自定义视图中(覆盖onSizeChanged()),但您可以使用Layout 类来检查每行的结束位置:

textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Remove immediately so it only fires once
        textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        // View should be laid out, including text placement
        final Layout layout = textView.getLayout();
        float maxLineWidth = 0;

        // Loop over all the lines and do whatever you need with
        // the width of the line
        for (int i = 0; i < layout.getLineCount(); i++) {
            maxLineWidth = Math.max(maxLineWidth, layout.getLineWidth(i));
        }
    }
});

【讨论】:

    【解决方案3】:

    创建一个 TextWatcher 并提取单行

    @Override
    public void afterTextChanged(Editable editable) {
     String str =  editable.toString();
     Layout layout = textView.getLayout();
    
     ArrayList<String> lines = new ArrayList<>();
     for (int i = 0; i < textView.getLineCount(); i++) 
     {
        int lineStart = layout.getLineStart(i);
        int lineEnd = layout.getLineEnd(i);
    
        String lineString = str.substring(lineStart, lineEnd);
         lines.add(lineString);
       }
       // now you have the single lines
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      相关资源
      最近更新 更多