Android获取view宽高有误,获取View的宽高——Android工作记录

在Android开发中,由于界面绘制流程,直接在onCreate中获取View的宽高可能为0。正确的做法包括:使用view.measure()手动测量,添加ViewTreeObserver.OnGlobalLayoutListener监听布局变化,或通过view.post(Runnable)异步获取。文章详细介绍了这三种方法的实现及注意事项。
摘要由CSDN通过智能技术生成

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

###0.前言

在Android开发中,许多场景都需要获取指定View的宽高来进行业务操作。但,有些时候在View的宽高不为0的情况下,通过View.getHeight()或者View.getMeasuredHeight()获取到的数值为0。这是为什么呢?

其实,这种情况和Android的界面绘制流程有关,简单来说,就是View的宽高需要在测量(Measure)之后才确定。

###1.获取View的宽高的方法

大多数遇到数值为0的问题的,都是在获取在activity的onCreate中获取。而OnCreate方法的调用过程其实还没完成View的测量工作,所以获取数值为0.

此时,如果还需要获取view的宽高,有3种方式:自己调用view的测量方法(view.measure(…)),提前进行测量

使用ViewTreeObserve.OnGlobalLayoutListener进行视图树的监听,在监听回调中获取

取巧方式,使用view.post(Runnable)获取(异步获取)

####1.1 通过调用view.measure()实现/**

* 测量view

* @param view

*/

public static void measureView(View view) {

ViewGroup.LayoutParams p = view.getLayoutParams();

if (p == null) {

p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

}

int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);

int lpHeight = p.height;

int childHeightSpec;

if (lpHeight > 0) {

childHeightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, View.MeasureSpec.EXACTLY);

} else {

childHeightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

}

view.measure(childWidthSpec, childHeightSpec);

}

/**

* 获取view的高度

* @param view

* @return

*/

public static int getViewHeight(View view) {

measureView(view);

return view.getMeasuredHeight();

}

需要注意的是,如果LayoutParams中配置了宽高的值,那么需要传入此数值以保证测量的合理性和准确性。

###1.2 通过ViewTreeObserve.OnGlobalLayoutListener实现

当在一个视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变时,所要调用的回调函数的接口类int mHeaderViewHeight;

mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(

new OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

mHeaderViewHeight = mHeaderView.getHeight();

getViewTreeObserver()

.removeGlobalOnLayoutListener(this);

}

需要注意的是,OnGlobalLayoutListener会被多次调用,所以在获取宽高后需要移除监听。

###1.3 view.post(Runnable)获取

其实,此方法是一个比较取巧的方式,通过view.post(Runnable)将获取宽高的Runnable放到消息队列中并执行,异步执行了获取宽高的代码。int mHeaderViewHeight;

mHeaderView.post(new Runnable(){

@Override

public void run() {

mHeaderViewHeight = mHeaderView.getHeight();

}

});

###2.在自定义控件中获取自身宽高onlayout方法中获取(这个方法是在onMeasure之后的)

onSizeChanged也可以获取,这个方法只有在view改变之后才会回调,当然第一次也是会回调的。

###4.总结在Android获取视图(View)的宽高需要遵循视图树的绘制流程,所以获取宽高需要在view被测量之后。

使用view.measure(0, 0);可以非常简便的获取到view的宽高,但因为无视了view自身的配置和父类传入的限制,实际获取到的宽高可能存在一定的问题。

END

–Nowy

–2019.02.11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值