2017-01-05 45 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()'不能按预期工作。 –

相关问题