简体   繁体   English

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

[英]Prevent a multiline TextView from unnecessarily expanding to it's maximum width

A TextView that expands to multiple lines seems to automatically expand to fit it's maximum possible width.扩展为多行的 TextView 似乎会自动扩展以适应其最大可能宽度。 How can I prevent that from happening?我怎样才能防止这种情况发生?

Here is an example layout (test.xml)这是一个示例布局(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

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.如果我在左侧添加边距,它会正确缩小 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 显示有边距

You may use custom TextView with overridden method onMeasure() where you calculate the width:您可以在计算宽度的地方使用带有覆盖方法 onMeasure() 的自定义 TextView:

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

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?如果您想使用@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;
    }
}

Rebuild a project when you insert this class into XML.将此类插入 XML 时重建项目 Otherwise it won't find this class.否则它不会找到这个类。

I've tried the solution of Vitaliy Polchuk and it works fine.我已经尝试过Vitaliy Polchuk的解决方案,效果很好。 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);
}
...

使用android:padding="32dp"它可以帮助你有填充,如果你想从左边使用android:paddingLeft="32dp"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM