Android 中获取控件宽和高的方法

第一种:直接获取getWidth()和getHeight()

    我们都知道这两个方法在onCreate()方法中得到的数据都是0;

代码:

    mTextView = (TextView) findViewById(R.id.textview);    mWidth = mTextView.getWidth();    mHeight = mTextView.getHeight();    Log.d(TAG, "onCreate: width = " + mWidth + "   height = " + mHeight);

布局:

 

log打印:

  05:31:47.982 25750-25750/? D/MainActivity: onCreate: width = 0   height = 0

onResume()方法中得到的也是零;
代码:

 @Override    protected void onResume() {        super.onResume();        mWidth = mTextView.getWidth();        mHeight = mTextView.getHeight();        Log.d(TAG, "onResume: width = " + mWidth + "   height = " + mHeight);    }

log打印:

  05:31:47.982 25750-25750/? D/MainActivity: onResume: width = 0   height = 0

onStart()就不用多说了;我们都知道getWidth()和getHeight(),只有在View布局完成之后才会有值,那么在Activity的生命周期中的哪个方法中会有值呢?
答案是:
onWindowFocusChanged(boolean hasFocus){}:当Activity的焦点发生改变时调用,他会在onResume()方法执行之后调用,Activity的生命周期方法与 View的绘制流程方法的执行顺序到底是怎样的呢?参见大神博客点击跳转得到的结论是:

oncreate()→onResume()→onMeasure()→onLayout()→onWidnowFocusChanged()→.....→onDraw()...

可以看到onWindowFocusChanged()方法是在onLayout()之后执行的,所以getWidth()与getHeight()会得到具体的数值,测试代码如下:

@Overridepublic void onWindowFocusChanged(boolean hasFocus) {    super.onWindowFocusChanged(hasFocus);    mWidth = mTextView.getWidth();    mHeight = mTextView.getHeight();    Log.d(TAG, "onWindowFocusChanged: width = " + mWidth + "   height = " + mHeight);}

log打印:

D/MainActivity: onWindowFocusChanged: width = 600   height = 600

控件的实际宽高就是600,记住这个答案!!!(为什么不是200!不明白的可以看一下屏幕密度,dp与px相关的知识)

第二种:手动测量(自己调用measure()方法)

代码:

mTextView = (TextView) findViewById(R.id.textview);    mTextView.measure( 0,  0);    int measuredWidth = mTextView.getMeasuredWidth();    int measuredHeight = mTextView.getMeasuredHeight();    Log.d(TAG, "onCreate: measuredWidth =" + measuredWidth + "    measuredHeight = " + measuredHeight);

布局和之前一样,log打印如下:

   D/MainActivity: onCreate: measuredWidth =225    measuredHeight = 57

什么鬼? 看到这个结果我又返回去看了一眼布局
->android:layout_width=”200dp”
->android:layout_height=”200dp”
没毛病啊,这个225和57哪来的?
接下来,将布局中的HelloWorld *2,改成

   android:text="Hello World!Hello World!"

log打印:

onCreate: measuredWidth =450    measuredHeight = 57

对的,你猜的没错,他得到的是内容的大小!!跟你给控件设置的宽高没一毛钱关系(感兴趣的可以自己测一下,我把TextView改成ImageView,宽和高都给的很小或者很大,设置个大的图片,getMeasuredWidth()方法得到的结果都是图片的大小)
所以,此方法慎用!!!

第三种:观察者模式

观察View的绘制流程,设置OnGlobalLayoutListener监听,布局完成时会调用onGlobalLayout(),在onGlobalLayout()方法里面获取空间的宽和高
代码:

  @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mTextView = (TextView) findViewById(R.id.textview);    mTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {        @Override        public void onGlobalLayout() {            mWidth = mTextView.getWidth();            int measuredHeight = mTextView.getMeasuredHeight();            mHeight = mTextView.getHeight();            Log.d(TAG, "onGlobalLayout: width = " + mWidth + "   height = " + mHeight + "***" + measuredHeight);        }    }); }

log打印:

  onGlobalLayout: width = 600   height = 600

第四种:View.post(Runnable action)

代码:

     @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mTextView = (TextView) findViewById(R.id.textview);    mTextView.post(new Runnable() {        @Override        public void run() {            mWidth = mTextView.getWidth();            mHeight = mTextView.getHeight();            Log.d(TAG, "run: width = " + mWidth + "   height = " + mHeight);        }    });

log打印:

run: width = 600   height = 600

解释一下为什么View.post(Runnable action)可以获取到正确的宽高
先看一下方法执行的时间
这里用自定义控件,重写onMeasure(),onLayout(),onDraw().方法
在这些方法中分别测量宽高,并打印时间

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    mWidth = getWidth();    mHeight = getHeight();    Log.d(TAG, "onMeasure: width = " + mWidth + "   height = " + mHeight + "时间 : " + System.currentTimeMillis());    super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {    mWidth = getWidth();    mHeight = getHeight();    Log.d(TAG, "onLayout: width = " + mWidth + "   height = " + mHeight + "时间 : " + System.currentTimeMillis());    super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {    mWidth = getWidth();    mHeight = getHeight();    Log.d(TAG, "onDraw: width = " + mWidth + "   height = " + mHeight + "时间 : " + System.currentTimeMillis() );    super.onDraw(canvas);}

log打印:

   onResume: width = 0   height = 0时间 : 1484040644793   onMeasure: width = 0   height = 0时间 : 1484040644819   onLayout: width = 600   height = 600时间 : 1484040644904   run: width = 600   height = 600时间 : 1484040644930   onWindowFocusChanged: width = 600   height = 600时间 : 1484040644930   onDraw: width = 600   height = 600时间 : 1484040644971

从上面日志的时间可以看出,View.post()中的run方法和onWindowFocusChanged方法几乎是同时执行,都是在onLayout之后,所以都是可以得到控件的宽高的!!!
还有,getMeasuredHeight()和getMeasuredWidth(),在Layout执行完成后得到的也是控件的宽高了!!!

更多相关文章

  1. 查看Android的appPackage和Activity的多种方法
  2. Android异常总结---type Status report message HTTP method GET
  3. 【Android】ArrayList通过remove方法删除元素对象源码分析
  4. Android学习笔记05:ProgressBar的使用
  5. Android(安卓)琐碎知识点汇总
  6. Android之Kotlin入门:常量和静态方法
  7. Android之Drawable转换drawable、bitmap、byte[]
  8. android之自定义组合控件
  9. Android(安卓)EditText的setOnEditorActionListener方法

随机推荐

  1. Windows平台上编译OpenCV的Android版本
  2. Android Xutils 框架
  3. Android中弹出输入法界面不影响app界面布
  4. android之CTS兼容性测试
  5. [置顶] Android超精准计步器开发-Dylan计
  6. Android系统分析之带着问题看Handler
  7. android studio 在线更新android sdk,遇到
  8. 使用 Android快速开发框架 Afinal 0.3 快
  9. 系出名门Android(5) - 控件(View)之TextV
  10. Android清除缓存功能实现