简单电子商务网站开发/企业网络推广方案
在进行 Android 项目开发时,经常需要获得某一控件的宽高以及位置信息,从而方便我们完成“外层 scrollview 的滚动”、“控件的动态摆放”等等处理。
然而每次想要获得控件的这些信息的时候,总是遇到有的时候能获取到,而有的时候获取到的宽高信息全是 0 的情况,搞得很不舒服。所以 本篇文章就将「获得控件宽高、以及位置信息」做了一个小汇总,说不上全面吧,但是肯定是够用的了。
那么废话就不多说了,直接上 demo 吧。
正如上面的动图展示的一样,我分别用了 5 种方式来获取了一下 控件名为 tv2 的高度、宽度、其顶部的位置信息,那么很明显,我们得到了这样的结果( 先看结果,这5个方法如何操作的见下文 ):
onCreate 中拿到的全部为 0
onResume 中拿到的全部为 0
onWindowFocusChanged 中拿到的所有信息都不为 0
forceMeasure 拿到了宽高不为 0,而顶部位置信息为 0
viewTree 拿到的所有信息都不为 0,但是计时却一直在跑
好了,那么我看到这个动图应该不难发现,比较好用的方法就是「onWindowFocusChanged」这个方法了,「viewTree」的这个方法虽然都拿到了,但是却一直在监听,感觉上来说并不是太好。
那么我们就逐步看下 5个方法都是怎么获取的吧
1、onCreate 对应的获取操作
2、onResume 对应的获取操作
3、onWindowFocusChanged 对应的获取操作
4、forceMeasure 对应的获取操作
5、viewTree 对应的获取操作
其中 onCreate 、onResume、onWindowFocusChanged 这三个方法都是在对应的方法中调用的获取的逻辑。
而 forceMeasure(强制测量)、viewTree(视图树)这两个方法都是在 onCreate 中调用的。只是内部进行了各自的处理,
接下来,我们先看下 onWindowFocusChanged 方法吧
通过上方的 demo 结果我们知道了,在 onCreate 、onResume 里直接拿控件的相关信息是不行的,只要在 onWindowFocusChanged 方法中拿到了想要的控件属性。
onWindowFocusChanged 在 Android 官网的解释是这样的
即:当 Activity 获得或者失去焦点的时候会调用此方法,而我们可以理解为 Activity 第一次调用 onWindowFocusChanged(true) 时,就已经“计算好”了各个控件的大小以及摆放位置了,此时获取控件的大小和位置信息是最早获得的方法。
再看
红框中的区别可以看出,onWindowFocusChanged 方法比 onResume 方法的调用时间晚了100多毫秒。
而 onResume 官方指出是这样的
即表示 Activity 已经处于就绪状态,可以和用户进行交互了。但需要注意的是:这里的就绪状态并不是完全展示好界面的状态,而是具备完全展示界面的初始化状态。
当 Activity 第一次调用 onResume 的时候,其实界面还未进行测量和布局,只是具备了开始测量和布局的状态而已。
好了,那么如果我们想直接拿控件的位置和大小信息的话,直接在 onWindowfocusChanged 方法获取即可。
我们再来看下通过 forceMeasure 来获取控件大小的方式吧
forceMeasure 方法是我自己起的名字,因为这种方法有强制让控件再测量一下的意思。
我们来看下方法体
即:创建了宽和高的 MeasureSpec,注意测量大小都是0,模式都是未定义,然后使用新建的宽和高的 MeasureSpec 再对 tv2 进行了 measure。
这样,我们就保证了 tv2 被测量过了。所以此时再拿 tv2 的宽高就能通过
tv2.getMeasuredWidth()tv2.getMeasuredHeight()
去拿到他的宽高了。
但是,因为此时并没有强制对 tv2 进行 layout,所以 tv2.getTop() 还是拿不到值,仍然是 0。
好了,接下来,我们看最后一种方法:监听 viewTree 的方法
viewTree 直译过来是“视图树”的意思,很形象。
我们再来看下这个方法是怎么实现的
首先通过
tv2.getViewTreeObserver();
拿到了 tv2 的视图树的观察者:vto
然后通过
vto.addOnPreDrawListener()
方法,对 tv2 添加了预绘制的监听。因为绘制是后于 onMeasure 和 onLayout 的,所以此时可能能够拿到 tv2 的宽高和位置信息了。
只不过因为是对观察者的监听,所以这个预绘制的监听是一直轮询的,这里如果做一些耗时的操作,必然会导致程序崩溃。
综上,我们总结一下,强制测量方法、对视图树监听、在 onWindowFocusChanged 方法中都能拿到控件的宽高,但是其中的最优解就是在 onWindowFocusChanged 中直接拿了。
好了,本篇文章就到这里,如果帮助到了你,就点个赞,一个轻轻的点赞能让我高兴好几天~~