Android 获得View宽高的几种方式总结
《android开发艺术探索》笔记:
在activity的oncreate()或者onresume()中去获得view的高度的时候不能正确获得宽度和高度信息,这是因为 view的measure过程和activity的生命周期不是同步执行的,因此无法保证activity执行了oncreate onstart onresume时,某个view已经测量完毕了,如果还没有测量完,那么获得的宽高就是0。可以通过下面几种方式来获得:
1、onwindowfocuschanged
onwindowfocuschanged:view已经初始化完毕,宽高已经有了,需要注意onwindowfocuschanged会被调用多次,activity得到焦点和失去焦点都会执行这个回调,见下图:
1、activity首次进入的时候执行的方法
2、跳转到另一个activity时
3、返回到当前activity时
可见当执行onresume和onpause时,onwindowfocuschanged都会被调用。
@override public void onwindowfocuschanged(boolean hasfocus) { super.onwindowfocuschanged(hasfocus); if (hasfocus) { //获得宽度 int width = view.getmeasuredwidth(); //获得高度 int height = view.getmeasuredheight(); } }
2、view.post(runnable)
通过post可以将一个runnable投递到消息队列的尾部,等待looper调用此runnable的时候,view也已经初始化好了,示例:
@override protected void onstart() { super.onstart(); view.post(new runnable() { @override public void run() { int width=view.getmeasuredwidth(); int height=view.getmeasuredheight(); } }) }
3、viewtreeobserver
使用viewtreeobserver的众多回调可以完成这个功能,比如使用ongloballayoutlistener这个接口,当view树的状态发生改变或者view树内部的view的可见性发生改变时,ongloballayout方法将会被回调,这是获取view宽高很好的一个时机,需要注意的是,伴随着view树的状态改变,ongloballayout会被调用多次,示例:
@override protected void onstart() { super.onstart(); viewtreeobserver observer=view.getviewtreeobserver(); observer.addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener() { @override public void ongloballayout() { view.getviewtreeobserver().removeongloballayoutlistener(this); int width=view.getmeasuredwidth(); int height=view.getmeasuredheight(); } }); }
4、view.measure(int widthmeasurespec, int heightmeasurespec)
通过手动对view进行measure来得到view的宽高,这里要分情况处理,根据view的layoutparams来分:
match-parent
无法测出具体的宽高,因为根据view的measure过程,构造此种measurespec需要知道parentsize,即父容器的剩余空间,而这个值我们是不知道的,所以不能测出view的大小。
具体的数值(dp/px)
比如宽高都是100px,如下measure:
int widthmeasurespec = view.measurespec.makemeasurespec(100, view.measurespec.exactly); int heightmeasurespec = view.measurespec.makemeasurespec(100, view.measurespec.exactly); view.measure(widthmeasurespec, heightmeasurespec);
wrap_content
如下measure:
int widthmeasurespec = view.measurespec.makemeasurespec((1 << 30) - 1, view.measurespec.at_most); int heightmeasurespec = view.measurespec.makemeasurespec((1 << 30) - 1, view.measurespec.at_most); view.measure(widthmeasurespec, heightmeasurespec);
view的specsize使用30位二进制表示,也就是说最大是30个1,也就是(1 << 30) - 1,在最大化模式下,我们用view理论上能支持的最大值去构造measurespec是合理的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。