Android 获取View的高度和宽度
2015-06-14 15:43
507 查看
View宽高值为什么是0
如果我们想获取View的高度和宽度,通过在onCreate()或者
onStart()或者
onResume()等生命周期中直接获取,像下面这样处理会获取到View的高度吗?
[code]package com.wjj.imagepull; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ScrollView; import android.widget.TextView; public class MainActivity extends Activity { ScrollView scrollView; public static final String TAG = "VIEW_PARAM"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); scrollView = (ScrollView) findViewById(R.id.scroll_view); getHeightAndWidth("onCreate()"); } private void getHeightAndWidth(String method) { int height = 0; int width = 0; if (scrollView != null) { height = scrollView.getHeight(); width = scrollView.getWidth(); } Log.i(MainActivity.TAG, method + " has been called: " + System.currentTimeMillis() + " height: " + height + " width: " + width); } @Override protected void onStart() { super.onStart(); getHeightAndWidth("onStart()"); } @Override protected void onResume() { super.onResume(); getHeightAndWidth("onResume()"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
接下来在自定义的组件
PullScrollView中适当的方法中加入一些测试log:
[code]public class PullScrollView extends ScrollView { View view; int sacTopMargin; float lastY; float offsetY; public PullScrollView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.i(MainActivity.TAG, "onMeasure() has been called: " + System.currentTimeMillis()); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.i(MainActivity.TAG, "onDraw() has been called: " + System.currentTimeMillis()); } ... }
然后运行后看一下Log
通过上面的方法,显然不能获取到View的高度和宽度,关于为什么获取不到View的这些参数值,原因很简单,因为当前Activity中持有的WindowPhone实例还尚未将View添加到DecorView上来,所以无法获取View的高度和宽度,一般在onResume生命周期过后300ms左右时间才会将需要显示的View添加到DecorView上去,代码像下面这样处理:
如何获取View宽高值
[code]@Override protected void onResume() { super.onResume(); getHeightAndWidth("onResume()"); scrollView.postDelayed(new Runnable() { @Override public void run() { getHeightAndWidth("onResume()_postDelayed()"); } }, 300); }
这样就获取了View的宽高值,当然这个方法不太保险,因为你不能确保在onResume之后300ms 就能将View添加到DecorView中去,那么保险的方式是什么呢?相信读过Android源代码的同学对
ViewTreeObserver.OnGlobalLayoutListener并不陌生,当一个view的布局加载完成或者布局发生改变时OnGlobalLayoutListener可以监听到,利用这点我们可以在布局加载完成的瞬间获得一个view的宽高。
[code]public class PullScrollView extends ScrollView implements ViewTreeObserver.OnGlobalLayoutListener { public PullScrollView(Context context, AttributeSet attrs) { super(context, attrs); ViewTreeObserver observer = getViewTreeObserver(); if (null != observer) observer.addOnGlobalLayoutListener(this); } @Override public void onGlobalLayout() { MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); sacTopMargin = -params.topMargin; Log.d(MainActivity.TAG, "" + sacTopMargin); getViewTreeObserver() .removeGlobalOnLayoutListener(this); } ... }
OnGlobalLayoutListener的onGlobalLayout被回调之前是没有值的。由于布局状态可能会发生多次改变,因此OnGlobalLayoutListener的onGlobalLayout可能被回调多次,所以我们在 第一次获得值之后就将listener注销掉。
当然关于如何获取View的高度和宽度值,还有很多方法,这里仅仅测试了两种比较靠谱的方法,感兴趣的同学可以继续深究。
相关文章推荐
- Android.mk的用法和基础学习-----阿冬专栏
- Android Color的定义以及color.xml的使用
- 基于android的远程视频监控系统
- Android中SoundPool的使用
- android dns解析
- 【Android】进度条与线程之间的消息处理
- Android 4.4 AMS 学习笔记
- Android Ams浅析
- Android中Fragment+ViewPager的配合使用
- Android进程机制五大进程
- Android学习 StateMachine与State模式
- mark—android返回键
- Android之各种Adapter
- Android 学习笔记之SurfaceView的使用+如何实现视频播放...
- Android更改工程名称
- Android Service(一)
- Android自定义View 构造方法 遇到的一些问题
- android webservices使用教程及遇到问题总结
- android安卓Jni编译提示fatal error: vector: No such file or directory
- Android学习 6->浅谈界面显示与LayoutInflater