Reputation: 171
A TextView that expands to multiple lines seems to automatically expand to fit it's maximum possible width. How can I prevent that from happening?
Here is an example layout (test.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<TextView
android:background="@color/green"
android:layout_alignParentRight="true"
android:id="@+id/foo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:text="This is the message a much shorter message"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black" />
</RelativeLayout>
If I add a margin on the left, it correctly shrinks the width of the TextView (without reformatting the content), but the size of the margin would have to calculated given the contents of the TextView.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<TextView
android:layout_marginLeft="32dp"
android:background="@color/green"
android:layout_alignParentRight="true"
android:id="@+id/foo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:text="This is the message a much shorter message"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/black" />
</RelativeLayout>
Upvotes: 14
Views: 2846
Reputation: 1898
You may use custom TextView with overridden method onMeasure() where you calculate the width:
public class WrapWidthTextView extends TextView {
// ...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Layout layout = getLayout();
if (layout != null) {
int width = (int)FloatMath.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;
}
}
Upvotes: 10
Reputation: 28875
If you want to use a suggestion of @Vitaliy Polchuk (a top answer), rewrite so or see his answer at Why is wrap content in multiple line TextView filling parent?:
public class WrapWidthTextView extends AppCompatTextView {
public WrapWidthTextView(Context context) {
super(context);
}
public WrapWidthTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WrapWidthTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@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;
}
}
Rebuild a project when you insert this class into XML. Otherwise it won't find this class.
Upvotes: 1
Reputation: 476
I've tried the solution of Vitaliy Polchuk and it works fine. And I also want to add small correction:
...
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Layout layout = getLayout();
if (layout != null) {
int width = (int) FloatMath.ceil(getMaxLineWidth(layout))
+ getCompoundPaddingLeft() + getCompoundPaddingRight();
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// get already measured dimensions
int width = getMeasuredWidth();
int height = getMeasuredHeight();
setMeasuredDimension(width, height);
}
...
Upvotes: 0
Reputation: 10689
use android:padding="32dp"
It's help you to have padding, if you want to have padding from left use android:paddingLeft="32dp"
Upvotes: 0