2017-01-05 70 views
5

我有這樣的佈局(我已經刪除某些屬性,因爲他們真的沒關係,完全示範項目是here):TextView的工作錯breakStrategy =「平衡」和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> 

文本long_text很長,所以它會分開幾行。

兩條重要線是android:layout_width="wrap_content"android:breakStrategy="balanced"

我預計TextView會根據實際的文本寬度計算寬度,但它不會。

screenshot

是否有人知道如何解決這一問題?

UPDATE

屬性android:breakStrategy="balanced"僅適用於API 23高。在我的示例中,文本需要3行,而balanced策略使每行大致相同的寬度。

我預計在這種情況下,視圖本身的寬度將與最長的一行相同。

我正在尋找任何解決方法。我需要像環聊聊天中的解決方案。我無法弄清楚它是如何工作的。

更新2

不幸的是,公認的答案並不與RTL文本。

+1

怎麼辦你的意思是'我希望TextView會根據實際的文本寬度來計算寬度,但它不會' Als o你的實際看起來與本應該[像這樣]不同(https://imagebin.ca/v/38OTigaIafpF) – shadygoneinsane

+0

我已更新問題。 –

+0

@Oleksii Kropachov如果你期望突破線條,可以說它比1.5線更長..所以你的預期輸出是什麼? –

回答

7

發生這種情況是因爲當TextView計算寬度時,它會將所有文本都測量爲1行(在您的情況下),並且在此步驟中它對android:breakStrategy一無所知。因此,它試圖利用所有可用空間在第一行上儘可能多地呈現文本。

如需更多信息,請檢查方法int desired(Layout layout)here

要解決它,你可以使用這個類:

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

}

我把這裏 - Why is wrap content in multiple line TextView filling parent?

+0

這個效果很好。謝謝! –

+0

今天我意識到它不適用於RTL文本。 –

0

你需要測量文本的寬度TextView編程,就像這樣:

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

現在,你可以把TextView後面的彩色矩形,並測量文本編程後設置其寬度(我使用FrameLayout把意見一個在另一個之上,但您可以使用RelativeLayout以及):

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> 

代碼:

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(); 

代碼是未經測試,但我敢肯定,你明白了吧。

UPDATE

也許可以做到不使用第二個背景view,通過設置TextView寬度符合bounds.width(),但這種觸發如何文本分解的變化,所以要小心不會導致無限循環。

+0

我早些時候嘗試過,但是'textView.getPaint()。getTextBounds()'不能按預期工作。 –

相關問題