分类分类
2015-07-08 11:45作者:zhao
getWidth()和getMeasuredWidth()两个方法在写法上非常相似,但是在用法上却大不相同。首先先总结一下:getWidth()代表的是view布局结束之后view所代表的宽度;getMeasuredWidth()代表的是view中内容的宽度。听起来有点绕口,我们直接从源码开始说起:
对于android源码中的getWidth()方法的源码如下:
public final int getWidth() {
return mRight - mLeft;
}
那么mRight和mLeft属性代表的又是什么呢?查看文档,我们可以发现在View类中有getLeft和getRight两个方法:
public final int getLeft() {
return mLeft;
}
public final int getRight() {
return mRight;
}
查看帮助文档,文档对于这两个方法的解释如下:
Left position of this view relative to its parent.
Right position of this view relative to its parent.
所以getWidth的宽度正好是view右边边框距离父组件的距离减去左边边框距离父组件的距离。正好就是view布局好之后的宽度。
对于getMeasuredWidth( ),我们查看源码,如下:
public final int getMeasuredWidth() {
return mMeasuredWidth & MEASURED_SIZE_MASK;
}
属性mMeasuredWidth使我们需要的,但是是在什么地方设置的这个属性呢?查阅源码,如下:
*/
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
boolean optical = isLayoutModeOptical(this);
if (optical != isLayoutModeOptical(mParent)) {
Insets insets = getOpticalInsets();
int opticalWidth = insets.left + insets.right;
int opticalHeight = insets.top + insets.bottom;
measuredWidth += optical ? opticalWidth : -opticalWidth;
measuredHeight += optical ? opticalHeight : -opticalHeight;
}
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}
mMeasuredWidth是在setMeasuredDimension()方法中设置的,而调用该方法是在onMeasure()方法中调用的,源码如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
所以mMeasuredWidth属性的设置是在measure阶段,通过widthMeasureSpec中的sieze值,经过一些判断(setMeasuredDimension中的optical的true or false),对size值进行一些操作,最后赋值给mMeasuredWidth,所以这个值就是measure阶段测量的view的内容宽度。
下面通过一个例子,设置TextView宽度为match_parent,观察getWidth和getMeasuredWidth值的变化。
package com.example.measuredwidthheight;
import android.R.color;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.TextView;
public class Main extends Activity {
public static final String TAG = "tag";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
MyTextView tv = new MyTextView(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(lp);
tv.setText("aaaa");
ll.addView(tv);
this.setContentView(ll);
}
}
class MyTextView extends TextView {
public static final String TAG = "tag";
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.v(TAG, "draw_width:" + this.getWidth());
Log.v(TAG, "draw_height:" + this.getHeight());
Log.v(TAG, "draw_measured_width:" + this.getMeasuredWidth());
Log.v(TAG, "draw_measured_height:" + this.getMeasuredHeight());
}
}
从结果可以看到:因为设置了textview的宽度为match_parent,所有getWidth的长度为屏幕宽度,而getMeasuredWidth返回的方法是textview内容的宽度60。
相关