android中各种height和width总结

来源:互联网 发布:八字奶 知乎 编辑:程序博客网 时间:2024/06/06 06:46

1. getMeasuredWidth()和getWidth()

以这两个为例,高度与其相同。这两个是在自定义View中最常见到的,通过字面意思可以看出,前者是测量的宽度,后者是控件的实际宽度,下面看下官方文档对他们的描述:

//Return the width of the your view.public final int getWidth()
/**The width of this view as measured in the most recent call to measure().This should be used during measurement and layout calculations only. Use getWidth() to see how wide a view is after layout.*/public final int getMeasuredWidth()

The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().

The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().

看不懂的可以自行百度,主要就是说getMeasuredWidth()的值,是在最近声明的measure()方法后获得的,它定义了一个View想在parent中获得的空间大小,换句话说就是它原本的大小,并且建议只能在measurelayout的循环中使用。

getWidth()返回的是view在屏幕上显示的最终(实际)大小,建议在layout之后调用此方法获取一个view的宽度,并且它的值可能会与getMeasuredWidth()的测量值不同,但是在绝大部分情况下(不在layout中做无意义的改动)它们两个的值是相同的。


我看网上很多文章说在控件全部可见的时候,getMeasuredWidth()getWidth()返回值是相同的,这个基本算是正确,但是他们说在控件部分不可见的时候,getMeasuredWidth()返回值是控件原本的大小,而getWidth()返回的是可见区域的大小,这就有失公允了,下面看个例子:

我在布局文件中定义了一个Button,在Activity中的onWindowFocusChanged()获取Button的测量宽度和最终宽度,代码如下:

    //这里用的是dp,实际获得的是当前屏幕分辨率的px值    <Button        android:id="@+id/button"        android:layout_width="100dp"         android:layout_height="50dp"        android:gravity="center"        android:text="button" />
public class MainActivity extends AppCompatActivity {    public static final String TAG = "MainActivity";    Button button;    private boolean isFocus = false;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        button = findViewById(R.id.button);    }    @Override    public void onWindowFocusChanged(boolean hasFocus) {        super.onWindowFocusChanged(hasFocus);        if (!isFocus && hasFocus) {            Log.i(TAG, "button.getWidth="+button.getWidth());            Log.i(TAG, "button.getMeasuredWidth="+button.getMeasuredWidth());            isFocus = true;        }    }}

结果为:

这里写图片描述

接下来我将Buttonlayout_width改为1000,显然应该超出了屏幕宽度,结果如下:

这里写图片描述

确实不是网友说的那样,因为即使超出了屏幕,两个值还是相同的。


接下来从源码的角度分析这两者的区别:

首先是getMeasuredWidth():

public final int getMeasuredWidth() {      return mMeasuredWidth;  }  

mMeasuredWidth是从setMeasuredDimension传过来的参数,而setMeasuredDimension最上层的调用是measure(),也就是measure()方法执行以后getMeasuredWidth()就有返回值了:

 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {       mMeasuredWidth = measuredWidth;       mMeasuredHeight = measuredHeight;       mPrivateFlags |= MEASURED_DIMENSION_SET;   }  

接下来看下getWidth()的源码:

public final int getWidth() {      return mRight - mLeft;  }  

其中的mRightmLeft是在layout过程中传过去的参数:

    protected boolean setFrame(int left, int top, int right, int bottom) {          boolean changed = false;          if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {              changed = true;              。。。省略部分代码。。。              mLeft = left;              mTop = top;              mRight = right;              mBottom = bottom;              。。。省略部分代码。。。          }          return changed;      }  

其中的rightleftlayout方法的参数传下来的,代表的是子view相对于父view的左右坐标,两者的差值作为getWidth()的返回值,所以在layout之后就可以通过getWidth()获取子view的最终大小了。

正常情况下,如果没有手动修改layout方法中的参数,那么getMeasuredWidth()getWidth()两者的值是相等的,但是一般建议在measurelayout的过程中调用getMeasuredWidth(),其他情况下调用getWidth()

2. getSuggestedMinimumWidth()和getSuggestedMinimumHeight()

这两个属性是在onMeasure方法中被使用的:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),        getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));}

具体是在getDefaultSize方法中被使用的,该方法在widthMeasureSpecAT_MOSTEXACTLY两种情况下返回widthMeasureSpec中的specSize,也就是测量后的大小,而只有在UNSPECIFIED,一般用于系统内部的测量过程的情况下,才会返回getSuggestedMinimumWidth(),下面看下其源码:

protected int getSuggestedMinimumWidth() {    return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimunWidth());}

可以看出,如果View没有设置背景,那么View的宽度就是mMinWidth,其对应的是android:minWidth这个属性的值,这个属性的默认值为0;如果View指定了背景,那么View的宽度就是两者的最大值。而后者获取的是Drawable的原始宽度,如果不存在原始宽度就为0。

总结一下,这个建议最小宽度的值取决于View背景的有无,如果没有就返回android:minWidth的值,有就返回背景最小宽度和前面那个值之间的最大值。


暂时就这么多,以后遇到了再补充。

原创粉丝点击