您的位置:首页 > 移动开发 > Android开发

Android——View宽高的设置和多种获取宽高的方法、layout_grivaty与grivaty的区别

2015-06-05 01:09 651 查看

一、设置控件宽高

设置Layout_width/height引发的宽高思考

方式一:







结果不符合预期。

运行结果:



方式二:





结果符合预期。

如下图:



Android控件宽高的规则

Android下的控件默认没有宽高,是由父控件给其宽高的。

其中一般的view控件是由(ViewGroup控件:LinearLayout、RelativeLayout 、TableLayout、FrameLayout 、AbsoluteLayou )五大布局给其宽高的。

而像LinearLayout、RelativeLayout等这些最外层的布局控件的宽高是由Android系统的FrameLayout控件设定的。可用android-sdk/tools下的工具hierarchyviewer.bat查看,如下图:



针对方式一的修改方案,如下代码:



运行结果如下:



二、Activity中获取控件的宽高

程序启动时想要获取特定视图组件的尺寸大小,在onCreate中可能无法取到,因为窗口Window对象还没创建完成,还没有执行onMeasure 和 onLayout方法,所以,此时getWidth返回值是0。那么如何或者说何时才能获取控件的大小呢?

方案1:在oncreate方法中, 发一个延迟消息,在handleMesaage中获取控件宽高。原理就是延时一段时间,等待控件测量、布局完成后再获取。(虽然有用但不优雅)

Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case GET_SIZE:
int width = listView.getWidth();
break;
}

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_conversation_ui);
handler.sendEmptyMessageDelayed(GET_SIZE, 500);
}


方案2:获得全局viewTree的观察者,并添加全局的layout监听。原理就是监听onlayout方法执行完成之后,就可以获取控件大小了。

// 获得全局viewTree的观察者,并添加 全局的layout监听
imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.
OnGlobalLayoutListener() {

@Override
public void onGlobalLayout() {
//由于此方法会执行多次,而我们只需要执行一次就可以了,
//所以,在执行一次的时候,将全局的layout监听取消,此处this指的是,内部的匿名对象
imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = imageView.getWidth();
}

});


方案3:主动通知系统去测量,调用measure(0,0)方法 。再用getMeasureWidth就可以得到测量的结果了。

imageView.measure(0, 0);// 主动通知系统去测量
LogUtils.d("========== imageView getMeasuredWidth: "+imageView.getMeasuredWidth());


方案4:重写Activity的onWindowFocusChanged方法。
在Activity窗口获得或失去焦点时被调用,例如创建时首次呈现在用户面前;当前Activity被其他Activity覆盖;当前Activity转到其他Activity或按Home键回到主屏,自身退居后台;用户退出当前Activity。以上几种情况都会调用onWindowFocusChanged。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
LogUtils.d("========== imageView getWidth: " + imageView.getWidth());
}


三、getWidth()与getMeasuredWidth()的区别

从上面代码可以看到,获取控件的宽高有时用getWidth()方法,有时用getMeasuredWidth()方法,这两个方法有什么区别呢?

getWidth()方法源码:

/**
* Return the width of the your view.
*
* @return The width of your view, in pixels.
*/
@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
return mRight - mLeft;
}

从源码可以看出,getwidth返回的是右边坐标减去左边坐标(也就是控件右边距屏幕Y轴的距离减去控件左边距屏幕Y轴的距离),这要在布局之后(也就是onLayout()方法执行完之后)才能确定它们的坐标。在布局后(也就是onLayout()方法执行完之后)才能调用getwidth来获取。

总结:getWidth()获得的宽度是View在设定好布局后整个View的宽度。 这个宽度是指在容器ViewGroup中,该view的宽度,可称为:布局宽度。

getMeasuredWidth()方法源码:

/**
* Like {@link #getMeasuredWidthAndState()}, but only returns the
* raw width component (that is the result is masked by
* {@link #MEASURED_SIZE_MASK}).
*
* @return The raw measured width of this view.
*/
public final int getMeasuredWidth() {
return mMeasuredWidth & MEASURED_SIZE_MASK;
}

注释:return The raw measured width of this view 获得的是原始的测量宽度。onMeasure()方法执行完之后就可以调用该方法获取。

总结:getMeasuredWidth()是对View上的内容进行测量后得到的View内容占据的宽度。这个宽度是根据view中的内容决定。可称为:组件宽度

当然要得到View内容占据的宽度,前提是你必须在父布局的onLayout()方法或者此View的onDraw()方法里调用measure(0,0);(measure中的参数的值你自己可以定义),否则你得到的结果和getWidth()得到的结果是一样的。

比如你定义一个组件的宽50、高50;但是你在布局文件中,硬是要把layout_width指定为match_parent(假设只有一个组件),那这个组件的宽度就被拉到全屏了。这时候getWidth()得到的就是布局宽度。如果要想得到原始宽度,必须调用该组件的measure(0,0)方法重新测量 。再用getMeasureWidth就可以得到了。

两者的使用场合:

getMeasuredWidth:在自定义view重写onLayout时、在我们用layoutinflater动态加载view后想获得view的原始宽度时。

getWidth:一般在view已经布局后呈现出来了,想获取宽度时

四、layout_grivaty与grivaty

layout_grivaty使用时的注意点:



结果如下图:





结果如下图:



区别:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: