Android View工作机制(4)— 我们该什么时候获取View的高宽?
来源:互联网 发布:java注释的作用 编辑:程序博客网 时间:2024/05/05 00:09
通过前面三篇总结,我们对View的measure有了一定的了解,那现在考虑一种情况,Activity启动的时候获取某个View的宽高值,该怎么取出呢?我们现在onCreate或者onStart方法中实验一下, 我们在布局文件中添加一个TextView,命名为tv1。在onCreate或者onStart中加入Log
Log.d("tvWidth", String.valueOf(tv1.getWidth()));Log.d("tvHeight", String.valueOf(tv1.getHeight()));
可以发现,结果打印出来的都是0。这是为什么呢?因为View的measure过程和Activity周期并不同步执行。所以Activity执行到它的生命周期中的某个方法的时候,并不能保证View已经measure完毕。只要measure过程没有结束,那么直接获取到的宽高值都将为0。那么有没有什么办法可以直接获取到View的宽高值呢?当然有,参考主席的《Android开发艺术探索》,总共有四种方法可以解决上面那个问题。
1. view.post(runnable)。
我们在onStart中加入以下代码:
tv1.post(new Runnable() { @Override public void run() { Log.d("tvWidth", String.valueOf(tv1.getWidth())); Log.d("tvHeight", String.valueOf(tv1.getHeight())); } });
我们可以看到,tv1的宽高值都被打印了出来。说明这个办法是可以获取到View的宽高值的。 这是因为view通过post可以将一个Runnable投递到消息队列的末尾,然后等待Looper调用此runnable,调用的时候View已经初始化完毕,可以获取到它的宽高值。
2 . Activity/View#onWindowFocusChanged
当Activity执行onWindowFocusChanged方法并且焦点出于获取状态的时候,View的初始化工作已经完成,此时获取View的宽高也不会有什么问题。 代码如下
@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int width = tv1.getMeasuredWidth(); int height = tv1.getMeasuredHeight(); Log.d("tv1Width", String.valueOf(width)); Log.d("tv1Height", String.valueOf(height)); } }
3 . ViewTreeObserver
使用ViewTreeObserver的回调也可以解决这个问题。添加如下代码:
ViewTreeObserver observer = tv1.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { tv1.getViewTreeObserver().removeOnGlobalLayoutListener(this); } int width = tv1.getMeasuredWidth(); int height = tv1.getMeasuredHeight(); Log.d("tv1Width", String.valueOf(width)); Log.d("tv1Height", String.valueOf(height)); } });
在View树发生布局变化的时候,此回调会响应,此时获取View的宽高也不会有什么问题。
4 . 手动measure
通过手动执行measure方法得到View的宽高。此办法需要考虑不同的情况。如果View的LayoutParams是MATCH_PARENT的话,那么可以直接放弃,因为子match_parnt需要获取父容器的宽高,此时子View的宽高都不能获取,获取父容器的宽高是一件不可能的事情。如果是直接的数值单位,如dp或者px,可以如下measure:
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTILY);int heightMeasureSpec = MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXATILY);tv1.measure(widthMeasureSpec, heightMeasureSpec);
如果是wrap_content,那么使用如下代码
int widthMeasureSpec = MeasureSpec.makeMeasureSpec((1 << 30) - 1, MeasureSpec.AT_MOST);int heightMeasureSpec = MeasureSpec.makeMeasureSpec((1 << 30) - 1, MeasureSpec.AT_MOST);tv1.measure(widthMeasureSpec,heightMeasureSpec);
使用wrap_content的时候,因为我们不知道如果使用size值,使用我们传入了最大的值2^30,即1 << 30 - 1。
1 0
- Android View工作机制(4)— 我们该什么时候获取View的高宽?
- Android view 的宽高到底什么时候确定与view生命周期
- Android获取View的宽高与View.measure详解
- Android获取View的宽高与View.measure详解
- Android获取View的高宽
- Android 如何获取view的宽高
- Android 获取View的宽高
- Android获取View的宽高
- Android获取View的宽高
- Android:获取View的宽高
- android 获取view的宽高
- android获取view宽高的时机
- Android 获取View的宽高
- Android 获取view的宽高方法
- Android-获取view的宽高
- 获取View的宽高
- Android 获取 View 的宽和高
- Android获取view的宽和高
- leetcode 234 Palindrome Linked List C++
- LeetCode:Longest Consecutive Sequence
- 星期几的不同脚本写法(推荐)和JS年月日格式
- G-Dezender批量解密
- 在Windows上编译Wireshark源代码
- Android View工作机制(4)— 我们该什么时候获取View的高宽?
- 模仿微信通讯录侧边栏快速索引
- cocos2d 性能优化1
- C++ 字符串字面值常量的问题
- 过遍数
- 不是闹鬼,是病毒!全球首个Golem(傀儡)病毒感染数万手机
- 数据库基础
- php memcache扩展
- cocos2d 性能优化2