防止多行TextView无必要地扩展到其最大宽度

14

一个可以扩展到多行的TextView似乎会自动扩展以适应其最大可能宽度。我该如何防止这种情况发生?

以下是一个示例布局(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>

TextView shown with maximum width

如果我在左侧添加边距,它会正确地缩小TextView的宽度(而不重新格式化内容),但边距的大小必须根据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>

TextView show with margin

4个回答

10

你可以使用自定义的TextView并覆盖onMeasure()方法,从而计算宽度:

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

1

如果你想使用@Vitaliy Polchuk(顶级答案)的建议,重写代码或查看他在为什么多行TextView包装内容会填充父级?中的回答:

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

在将此类插入XML时,重新构建项目。否则,它找不到此类。

0

使用android:padding="32dp"可以帮助您设置填充,如果您想要从左侧设置填充,请使用android:paddingLeft="32dp"


1
问题不在于填充。我希望TextView实际上可以自动换行,但是当它有多行时,它会扩展到父视图的宽度。 - Vijay Raghunathan

0

我尝试了 Vitaliy Polchuk 的解决方案,它很好用。我还想添加一点小修正:

...
@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);
}
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接