【问题标题】:Stopping text from splitting to multiple lines on the periods in web addresses阻止文本在网址中的句点上拆分为多行
【发布时间】:2010-11-17 12:23:51
【问题描述】:

我有一个显示一些文本的 Android TextView,它是多行的。但是,在文中,我有时会有域名;如何阻止 TextView 在其中的句点上拆分行?

例如,是否有 unicode 非中断句点?


要查看包装电子邮件地址的实际问题,请运行
android create project --target 16 --path demo --package com.example.demo --activity MainActivity
并将res/layout/main.xml 中的文本更改为“Hello World, MyActivity filler text + email foo@foo.com”。这会在 Galaxy S3(API 级别 16)上产生此输出:

(根据需要调整文本以在具有其他屏幕尺寸的设备上查看换行。值得注意的是,换行在 Intellij 的布局预览中正确完成,仅在设备上出现故障。)

【问题讨论】:

  • @blahdiblah,您的目标 SDK 版本是什么?我无法在 Nexus 4(API 级别 18)上重现此问题。
  • @shoerat 我在一些运行
  • @blahdiblah,介意放一些代码吗?也许这是一个依赖于实现的问题?
  • @blahdiblah 您的电子邮件地址是 mailto: 前缀吗?它们有超链接吗?
  • @blahdiblah 我看到 TextView 有一个 setAutoLinkMask,如果您查看 developer.android.com/reference/android/text/util/…,您可以看到您可以将其设置为链接电子邮件地址。另一方面,当我遇到问题时,我不希望地址可点击......我不记得我是否解决了这个问题。

标签: android unicode textview word-wrap


【解决方案1】:

TLDR;

@Matt McMinn 已经展示了这个问题的解决方案here,去抓住它。我只是在这里重复该解决方案。


请注意,此问题已在 Android 4.2.2 的平台级别修复。请参阅下面的屏幕截图,了解 Galaxy Nexus 上相同代码库但不同平台版本的自动换行比较。

因此,如果您不是针对旧版本的 Android,您可能根本不希望使用此修复程序。

代码

MainActivity.java

package com.example.nobr;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.TextView.BufferType;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView helloWorld = (TextView) findViewById(R.id.hello_world);
        helloWorld.setText(R.string.hello_world, BufferType.EDITABLE);

        TextView longText = (TextView) findViewById(R.id.long_text);
        longText.setText(R.string.long_text_with_url, BufferType.EDITABLE);
    }
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp" >

    <com.example.nobr.NonBreakingPeriodTextView
        android:id="@+id/hello_world"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <com.example.nobr.NonBreakingPeriodTextView
        android:id="@+id/long_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/hello_world"
        android:layout_below="@+id/hello_world"
        android:layout_marginTop="20dp" />

</RelativeLayout>

NonBreakingPeriodTextView.java

package com.example.nobr;

import android.content.Context;
import android.graphics.Paint;
import android.text.Editable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

public class NonBreakingPeriodTextView extends TextView {
    private static final String TAG = "NonBreakingPeriodTextView";

    public NonBreakingPeriodTextView(Context context) {
        super(context);
    }

    public NonBreakingPeriodTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Editable editable = getEditableText();
        if (editable == null) {
            Log.d(TAG, "non-editable text");
            return;
        }
        int width = getWidth() - getPaddingLeft() - getPaddingRight();
        if (width == 0) {
            Log.d(TAG, "zero-length text");
            return;
        }

        Paint p = getPaint();
        float[] widths = new float[editable.length()];
        p.getTextWidths(editable.toString(), widths);
        float curWidth = 0.0f;
        int lastWSPos = -1;
        int strPos = 0;
        final char newLine = '\n';
        final String newLineStr = "\n";
        boolean reset = false;
        int insertCount = 0;

        /*
         * Traverse the string from the start position, adding each character's width to the total
         * until: 1) A whitespace character is found. In this case, mark the whitespace position. If
         * the width goes over the max, this is where the newline will be inserted. 2) A newline
         * character is found. This resets the curWidth counter. curWidth > width. Replace the
         * whitespace with a newline and reset the counter.
         */

        while (strPos < editable.length()) {
            curWidth += widths[strPos];

            char curChar = editable.charAt(strPos);

            if (curChar == newLine) {
                reset = true;
            } else if (Character.isWhitespace(curChar)) {
                lastWSPos = strPos;
            } else if (curWidth > width && lastWSPos >= 0) {
                editable.replace(lastWSPos, lastWSPos + 1, newLineStr);
                insertCount++;
                strPos = lastWSPos;
                lastWSPos = -1;
                reset = true;
            }

            if (reset) {
                curWidth = 0.0f;
                reset = false;
            }

            strPos++;
        }

        if (insertCount != 0) {
            setText(editable);
        }
    }
}

结果

在 Android 4.1.2 (Galaxy Nexus) 上

在 Android 2.3.3(AVD、Nexus One 克隆)上

希望这会有所帮助。

【讨论】:

  • 顺便说一句,在 Galaxy S3 (Android 4.1.1) 上测试了上述修复,它也可以在那里工作。
  • 非常精心准备和解释的答案!这也适用于非常旧的 Android 版本吗?
  • 当我这样做时文本不可编辑,所以第一个 if 语句总是返回 false?想法?
  • @MattWolfe,您使用的BufferType 是否正确?您测试的目标设备、API 级别是什么?
  • 啊,不知何故我错过了上面的那部分代码!谢谢。
【解决方案2】:

要告诉 android 解析 TextView 中的域链接,请在 TextView 代码块中使用此代码:

android:autoLink="web"

这会将域名显示为应用程序中的链接,并且不会拆分行。

【讨论】:

  • 知道这一点非常有用;但是有没有办法避免它们被拆分而不将它们变成超链接? (域我的上下文显示为用户在 PC 上执行的指令的一部分......)
  • 您能发布您当前使用的代码吗?我可以根据您到目前为止所做的工作提出更好的建议。
  • 我实际上已经在 Honeycomb 设备上看到它与 android:autoLink="web" 分割线;长句末尾的文本“www.andromo.com”在“www”处被拆分。部分。
【解决方案3】:

使用这个:

android:singleLine="true" 在 xml 中

【讨论】:

    【解决方案4】:

    对我来说,@ozbek 和 @Matt McMinn 的解决方案都不起作用,我不得不换行

    else if(Character.isWhitespace(curChar))
    

    } else if (curChar == '\u00A0') {
    

    但其他很好的解决方案,谢谢

    【讨论】:

      猜你喜欢
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多