Why is wrap content in multiple line TextView fill

2019-01-14 11:22发布

问题:

I have a multi line text view set to android:layout_width="wrap_content" that, when rendered, takes all available width of the parent. When the text can fit on one line, the wrap_content works fine, but at two or more lines, the text view seems to match the parents width, leaving what looks like padding on either side.

Because the text can not fit on one line, is the text view assuming to require all available width? I want the view to be bounded by the smallest possible dimensions.

Any ideas?

For reference, here is layout definition:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:singleLine="false"
    android:textSize="24sp"
    android:textStyle="bold"
    android:textColor="@color/white"
    android:gravity="center_horizontal"
/>

回答1:

I had the same problem also... 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) 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;
}
}


回答2:

A little bit optimized solution for the accepted answer above:

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
    int widthMode = MeasureSpec.getMode(widthSpec);

    // if wrap_content 
    if (widthMode == MeasureSpec.AT_MOST) {
        Layout layout = getLayout();
        if (layout != null) {
            int maxWidth = (int) Math.ceil(getMaxLineWidth(layout)) + 
                           getCompoundPaddingLeft() + getCompoundPaddingRight();
            widthSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
        }
    }
    super.onMeasure(widthSpec, heightSpec);
}