I have such layout (I\'ve removed some attributes, cause they really doesn\'t matter, full demo project is here):
This happens because when TextView calculates its width it measure all text as 1 line (in your case) and on this step it knows nothing about android:breakStrategy. So it is trying to utilize all available space to render as much text on first line as it can.
To get more details, please check method int desired(Layout layout)
here
To fix it you can use this class:
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;
}
}
which I took here - Why is wrap content in multiple line TextView filling parent?
You'll need to measure the width of the text in TextView
programatically, like so:
Rect bounds = new Rect();
textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), bounds);
Now, you can place a colored rectangle behind the TextView
, and set its width programatically after measuring the text (I'm using FrameLayout
to put the Views one on top of the other, but you can use RelativeLayout
as well):
XML:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="+@id/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>
Code:
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();
Code is untested, but I'm sure you get the point.
UPDATE
It may be possible to do this without using a second background view
, by setting the TextView
width to match bounds.width()
, but this trigger a change in how the text breaks, so need to be careful not to cause an infinite loop.