【问题标题】:TextView breaks my word by lettersTextView 用字母打断我的话
【发布时间】:2017-08-16 18:31:39
【问题描述】:

我的要求:创建按内容宽度和最大宽度 90% 的“传入气泡”。

我有这个标记:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:weightSum="1.0"
    tools:background="@color/white_smoke">

    <LinearLayout
        android:id="@+id/flBubble"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="start"
        android:background="@drawable/bubble_in"
        android:layout_weight="0.9">

        <ImageView
            android:id="@+id/ivSay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="?android:attr/selectableItemBackground"
            android:contentDescription="@string/default_content_description"
            android:padding="8dp"
            android:src="@drawable/ic_play_circle_outline_black_24dp"
            android:tint="@color/primary"/>

        <TextView
            android:id="@+id/tvValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:padding="8dp"
            android:textColor="@color/black"
            android:textSize="16sp"
            tools:text="I would like to go to an Italian restaurant"/>
    </LinearLayout>

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="0.1"/>
</LinearLayout>

有时我会得到以下结果:

但我希望得到以下结果(Android Studio 预览版的屏幕截图令人鼓舞):

如何防止restaraunt被字母破坏?

更新

虽然我使用了 minSdk=15,但我尝试使用 breakStrategy,但没有得到预期的结果。 android:breakStrategy="simple":

android:breakStrategy="balanced":

我发现了一个相关问题:Force next word to a new line if the word is too long for the textview,但我不明白如何使用layout_width="wrap_content 获得 TextView 的最大可用宽度?

如果我可以覆盖 TextView.setText 并在需要时在此处放置换行符,那就太好了。

【问题讨论】:

  • 检查我的答案更新。
  • 也许this的回答对你有用
  • @AndrewZ 我在 UPDATE 中写过这个答案
  • 你试过android:hyphenationFrequency="none"属性吗?看看这个:stackoverflow.com/questions/4851659/…
  • 您使用的是空格还是  ?你能显示获取/设置文本的代码吗?

标签: java android textview


【解决方案1】:

天哪,我的字符串中有&amp;nbsp;

value.replaceAll("\\s", " ");

谢谢大家!

【讨论】:

  • 或者你可以有牢不可破的空间而不是简单的空间。
【解决方案2】:

为 textview 使用 MaxWidth 属性,否则您应该为 textview 提供 width

   <com.custom.views.CustomTextView
        android:id="@+id/txt_send_chat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical"
        android:maxWidth="250dp"
        android:textColor="@color/color_chat_sender"
        android:textSize="16sp"
        app:font_name="@string/font_roboto_regular" />

【讨论】:

  • 尝试自定义文本视图和可跨度设置文本
  • @Keerthivasan 你能举一个跨度文本的例子吗?
【解决方案3】:

您可以使用webview 来实现此行为。 在 webview 中,您可以使用 css 来调整文本。 看看this answer


更新

您可以计算字符串的宽度并将\n添加到字符串需要拆分的位置

Rect bounds = new Rect(); 
Paint textPaint = textView.getPaint(); 
 textPaint.getTextBounds(text, 0, text.length(), bounds); 
 int height = bounds.height(); 
int width = bounds.width();

结果以像素为单位,因此只需检查view 或屏幕的宽度并拆分字符串。


UPDAE2:示例代码

我刚刚在活动onCreate 中编写了一个简单布局的示例,您可以在适配器或任何适合您的方式中实现它。

    TextView textView = (TextView) findViewById(R.id.txt); //textview with empty text
    Rect bounds = new Rect();
    Paint textPaint = textView.getPaint();

    String text = "some long text here.....";// text data to work on
    textPaint.getTextBounds(text, 0, text.length(), bounds);
    int textWidth = bounds.width();// get text width in pixel
    int marginPadding = 100;// we have some padding and margin from xml layouts
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    int rootWidth = displayMetrics.widthPixels-marginPadding;// maximum width on screan

    if (textWidth > rootWidth) { // check if need to split the string.
        int lineMax = (text.length() * rootWidth) / textWidth; // maximum Characters for each line
        String result = text.replaceAll("(.{" + String.valueOf(lineMax) + "})", "$1\n"); // regex to replace each group(lineMax) of Chars with group of char + new line
        textView.setText(result);
    } else
        textView.setText(text);

更新#3:Listview 的固定代码

onCreate

    ArrayList<String> data = new ArrayList<>();

    data.add("000");
    data.add("aaaaaaaaaaa");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb cccccccccccccccc");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb cccccccccccccccc ddddddddddddd");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb cccccccccccccccc ddddddddddddd eeeeeeeeeeeee");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb cccccccccccccccc ddddddddddddd eeeeeeeeeeeee ffffffffffffffffff");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb cccccccccccccccc ddddddddddddd eeeeeeeeeeeee ffffffffffffffffff gggggggggggggggg");
    data.add("aaaaaaaaaaa bbbbbbbbbbbb cccccccccccccccc ddddddddddddd eeeeeeeeeeeee ffffffffffffffffff gggggggggggggggg hhhhhhhhhhhhhhhh");

    ListView listView = (ListView) findViewById(R.id.listview);
    MyAdapter adapter= new MyAdapter(data,this);
    listView.setAdapter(adapter);
    adapter.notifyDataSetChanged();

MyAdapter.java

public class MyAdapter extends BaseAdapter {

private LayoutInflater inflater = null;
Context context;
ArrayList<String> data;


public MyAdapter(ArrayList<String> data, Context context) {
    this.context = context;
    this.data = data;
    inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    return data.size();
}

@Override
public Object getItem(int i) {
    return data.get(i);
}

@Override
public long getItemId(int i) {
    return i;
}


@Override
public View getView(final int i, View convertView, ViewGroup viewGroup) {

    final View view = inflater.inflate(R.layout.item, null);
    final TextView tv_text = (TextView) view.findViewById(R.id.tvValue);
    if (data.get(i) != null) {
        tv_text.post(new Runnable() {
            @Override
            public void run() {
               //TextView is Ready to be used.
                fixText(data.get(i),tv_text);
            }
        });
    }
    return view;
}

    private void fixText(String text, TextView textView) {
    Rect bounds = new Rect();
    Paint textPaint = textView.getPaint();
    textPaint.getTextBounds(text, 0, text.length(), bounds);
    int textWidth = bounds.width();// get text width in pixel
    int marginPadding = 100;// we have some padding and margin from xml layouts
    DisplayMetrics displayMetrics = new DisplayMetrics();
    ((MainActivity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    int rootWidth =  textView.getWidth();//displayMetrics.widthPixels - marginPadding;// maximum width on screan

    if (textWidth > rootWidth) { // check if need to split the string.
        //int lineMax = (text.length() * rootWidth) / textWidth; // maximum Characters for each line
        //String result = text.replaceAll("(.{" + String.valueOf(lineMax-5) + "})", "$1\n"); // regex to replace each group(lineMax) of Chars with group of char + new line
        String result = wrapText(rootWidth,text);
        textView.setText(result);
    } else
        textView.setText(text);



}

private String wrapText(int textviewWidth,String mQuestion) {
    String temp = "";
    String sentence = "";
    String[] array = mQuestion.split(" "); // split by space
    for (String word : array) {
        if ((temp.length() + word.length()) < textviewWidth) {  // create a temp variable and check if length with new word exceeds textview width.
            temp += " "+word;
        } else {
            sentence += temp+"\n"; // add new line character
            temp = word;
        }
    }
    return (sentence.replaceFirst(" ", "")+temp);
}

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1.0"
tools:background="@color/colorAccent">

<LinearLayout
    android:id="@+id/flBubble"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_gravity="start"
    android:background="@color/colorPrimary"
    android:layout_weight="0.9">

    <ImageView
        android:id="@+id/ivSay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:contentDescription="default_content_description"
        android:padding="8dp"
        android:src="@android:drawable/ic_media_play"
        android:tint="@color/colorPrimaryDark" />

    <TextView
        android:id="@+id/tvValue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:padding="8dp"
        android:textColor="#000000"
        android:textSize="16sp"
        tools:text="I would like to go to an Italian restaurant jkjk l;'"/>
</LinearLayout>

<View
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_weight="0.1"/>
</LinearLayout>

【讨论】:

  • ListView 项似乎太重了
  • 我在我的项目中使用了WebView,即使他一个人,它也并不快,更不用说带有WebView-items的ListView了..
  • 我必须将这个 width 与 TextView 的最大可用宽度进行比较。如果 TextView.width == "wrap_content",我该怎么做?
  • 您可以获得屏幕宽度,如果 textview 父级上的任何边距/填充减去它们并且您拥有 textview 宽度
  • 我有一个包含许多小部件的复杂布局,TextView 位于其中。所有小部件都设置为width="wrap_content"width="match_parent",具有自己的填充和边距。我不知道如何获得确切的rootWidth,它等于我的 TextView 的最大可用宽度。我问了另一个问题:stackoverflow.com/questions/45858874/…
【解决方案4】:

试试这个

<TextView
        android:id="@+id/tvValue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:padding="8dp"
        android:textColor="@color/black"
        android:textSize="16sp"
        tools:text="I would like to go to an Italian restaurant"/>
</LinearLayout>

【讨论】:

  • 这个选项不符合我的要求“...with width by content”
【解决方案5】:

你可以试试 自动调整 TextViews

支持库 26.0 完全支持运行 Android 8.0(API 级别 26)之前的 Android 版本的设备上的自动调整 TextView 功能。该库提供对 Android 4.0(API 级别 14)及更高版本的支持。 android.support.v4.widget 包包含 TextViewCompat 类以向后兼容的方式访问功能

例如:

<TextView
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:autoSizeTextType="uniform" />

有关更多详细指南,请转到HERE

他们也是图书馆HERE

【讨论】:

  • 这个功能并不能解决我的断信问题
【解决方案6】:

试试这个

 private String getWidthFitString(String input) {
    Paint paint = text.getPaint();
    // you can define max width by your self
    int maxWidth = getContentMaxWidth();
    float width = paint.measureText(input);
    if (width > maxWidth) {
        List<String> words = Arrays.asList(input.split("\\s"));
        int breakLinePosition = 0;
        String toBreakLineText;
        List<String> toBreakLineWords = new ArrayList<>();
        while (breakLinePosition < words.size()) {
            toBreakLineWords.add(words.get(breakLinePosition));
            toBreakLineText = TextUtils.join(" ", toBreakLineWords);
            float currentWidth = paint.measureText(toBreakLineText);
            if (currentWidth > maxWidth) {
                break;
            }
            breakLinePosition ++;
        }
        if (breakLinePosition > 1) {
            toBreakLineWords.remove(toBreakLineWords.size() - 1);
            toBreakLineText = TextUtils.join(" ", toBreakLineWords);
            List<String> fromBreakLineWords = new ArrayList<>();
            for (int i = breakLinePosition; i < words.size(); i++) {
                fromBreakLineWords.add(words.get(i));
            }
            return toBreakLineText + "\n" + getWidthFitString(TextUtils.join(" ", fromBreakLineWords));
        } else {
            return input;
        }
    }
    return input;
}

【讨论】:

    【解决方案7】:

    对于那些字符串有不间断空格字符的人可以尝试以下:

    value.replace("\u00A0", " ")
    

    希望这可能会有所帮助

    【讨论】:

      【解决方案8】:

      将您的 TextView 更改为 EditText 并将这 2 行。它应该可以帮助你

          android:inputType="textMultiLine"
          android:enabled="false"
      

      这将正确放置您的文本,稍后您可以根据需要在应用程序中提供编辑功能。

      【讨论】:

      猜你喜欢
      • 2012-05-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多