2017-01-05 12 views
5

Tôi có bố trí như vậy (tôi đã xóa một số thuộc tính, nguyên nhân họ thực sự không quan trọng, dự án trình diễn đầy đủ là here):TextView làm việc sai trái với breakStrategy = "cân bằng" và layout_width = "wrap_content"

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <TextView 
     android:layout_width="wrap_content"  (* this is important) 
     android:layout_height="wrap_content" 
     android:breakStrategy="balanced"   (* this is important) 
     android:text="@string/long_text" /> 
</LinearLayout> 

Văn bản long_text là khá dài, do đó, nó sẽ được tách ra cho một vài dòng.

Hai dòng quan trọng là android:layout_width="wrap_content"android:breakStrategy="balanced".

Tôi hy vọng rằng TextView sẽ tính chiều rộng theo số thực tế văn bản chiều rộng, nhưng không.

screenshot

Có ai biết cách khắc phục điều này không?

CẬP NHẬT

Thuộc tính android:breakStrategy="balanced" chỉ hoạt động cho API 23 và cao hơn. Trong văn bản mẫu của tôi có 3 dòng và chiến lược balanced làm cho mỗi dòng có cùng chiều rộng.

Tôi hy vọng rằng trong trường hợp này, chiều rộng của chính chế độ xem sẽ giống với dòng dài nhất.

Tôi đang tìm cách giải quyết khác. Tôi cần giải pháp như trong trò chuyện trong Hangouts. Tôi không thể tìm ra cách nó hoạt động.

UPDATE 2

Thật không may, câu trả lời được chấp nhận không làm việc với RTL văn bản.

+1

gì bạn có nghĩa là bởi 'Tôi hy vọng rằng TextView sẽ tính chiều rộng theo chiều rộng văn bản thực tế, nhưng nó không' Als o thực tế của bạn có vẻ khác với những gì nên có được [như thế này] (https://imagebin.ca/v/38OTigaIafpF) – shadygoneinsane

+0

Tôi đã cập nhật câu hỏi. –

+0

@Oleksii Kropachov Làm thế nào bạn mong đợi để phá vỡ dòng, cho phép nói dài hơn 1,5 dòng của nó .. vì vậy whats đầu ra dự kiến ​​của bạn? –

Trả lời

7

Điều này xảy ra vì khi TextView tính chiều rộng của nó, nó đo tất cả văn bản dưới dạng 1 dòng (trong trường hợp của bạn) và bước này không biết gì về android: breakStrategy.Vì vậy, nó đang cố gắng tận dụng tất cả không gian có sẵn để hiển thị nhiều văn bản trên dòng đầu tiên nhất có thể.

Để biết thêm chi tiết, xin vui lòng kiểm tra phương pháp int desired(Layout layout)here

Để khắc phục nó, bạn có thể sử dụng lớp này:

public class MyTextView extends TextView { 
public MyTextView(Context context) { 
    super(context); 
} 

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

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

    Layout layout = getLayout(); 
    if (layout != null) { 
     int width = (int) Math.ceil(getMaxLineWidth(layout)) 
       + getCompoundPaddingLeft() + getCompoundPaddingRight(); 
     int height = getMeasuredHeight(); 
     setMeasuredDimension(width, height); 
    } 
} 

private float getMaxLineWidth(Layout layout) { 
    float max_width = 0.0f; 
    int lines = layout.getLineCount(); 
    for (int i = 0; i < lines; i++) { 
     if (layout.getLineWidth(i) > max_width) { 
      max_width = layout.getLineWidth(i); 
     } 
    } 
    return max_width; 
} 

}

mà tôi mất ở đây - Why is wrap content in multiple line TextView filling parent?

+0

Điều này hoạt động hoàn hảo. Cảm ơn! –

+0

Hôm nay tôi đã nhận ra rằng nó không hoạt động với văn bản RTL. –

0

Bạn sẽ cần để đo chiều rộng của văn bản trong TextView programatically, như vậy:

Rect bounds = new Rect(); 
textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bounds); 

Bây giờ, bạn có thể đặt một hình chữ nhật màu phía sau TextView, và thiết lập chiều rộng của nó programatically sau đo văn bản (tôi đang sử dụng FrameLayout đặt Views chồng lên người kia, nhưng bạn có thể sử dụng RelativeLayout cũng):

XML:

<FrameLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <View 
     android:id="[email protected]/background" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:background="@color/green" /> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:breakStrategy="balanced" 
     android:text="@string/long_text" /> 
</FrameLayout> 

Mã:

Rect bounds = new Rect(); 
textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bounds); 
View bg = findViewById(R.id.background); 
gb.getLayoutParams().width = bounds.width(); 

Mã chưa được kiểm tra, nhưng tôi chắc chắn bạn sẽ nhận được điểm.

CẬP NHẬT

Có thể để làm điều này mà không sử dụng một nền tảng thứ hai view, bằng cách thiết lập chiều rộng TextView để phù hợp với bounds.width(), nhưng kích hoạt này một sự thay đổi trong cách thức phá vỡ văn bản, do đó cần phải cẩn thận không gây ra một vòng lặp vô hạn.

+0

Tôi đã thử điều này trước đó, nhưng 'textView.getPaint(). GetTextBounds()' không hoạt động như mong đợi. –

Các vấn đề liên quan