Android中获取View宽高方法

作者: SamMao | 来源:发表于2016-03-16 01:07 被阅读5102次

Android开发中经常需要获取控件的宽高,比如前不久我在写一个图片加载库时,因为需要对Bitmap进行裁剪就遇到了需要获取ImageView宽高的问题。
如果稍微了解过一下View的绘制过程,就会知道直接在onCreate()等生命周期回调方法中获取宽高,获取到的值是0,所以我们需要采用一些特殊的方法去获取。
这里简单总结一下获取宽高的几种方法:

一、通过View.post(new Runnable())获取

这里的view可以是你需要获取宽高的View。要注意的view要执行此方法必须保证它已经attached到了window上,因此在此之前是不能调用这个方法的。

Runnable里可以执行获取宽高的方法:

view.post(new Runnable(){
     @Override
     public void run() {
        int width = view.getMeasuredWidth();          
        int height = view.getMeasuredHeight();
      }
});

这个方法的原理在于:View的宽高需要在Measure 过程后才能确定,直接在onCreate()等回调方法里获取只能得到0,因为此时还没有开始Measure操作。

而通过view.post()在主线程的消息队列尾部插入了一个消息,也就是说执行获取宽高的操作被延后了,并且能够保证Measure操作在此之前,所以就能够在这里获取到正确的宽高了。

有关为什么“能够保证Measure操作在此之前”,我会在下一篇文章里详细分析。

另外,在网上还可以搜到其他类似方法如使用
ViewTreeObserver.addOnGlobalLayout()/addOnPreDrawLayout()Activity/View.onWindowFocusChanged()方法中获取的,本质也是延后了操作,等待View初始化完毕了之后再进行获取,在这里就不细说了。

总结:
此方法优点是保证获取到的宽高是准确的;
缺点是不能及时获取到,实际上还是把操作延后了,需要在Runnable里再执行相应回调。

二、通过LayoutParams获取

对于在XML文件里设置了具体宽高的View可以通过view.getLayoutParams().height/width获取到宽高。

总结:优点是能及时获取到,且操作简单;缺点是不够通用,没有设置具体宽高的获取到的值就是0了。

三、手动Measure再获取

既然View的宽高是在Measure之后才能获得的,自行调用view.measure()不就行了吗?

那么我们需要自行构造MeasureSpec,也就是测量参数,它是一个由父容器和View自身决定的变量。有关它的具体分析,可以阅读《Android开发艺术探索》来了解。

对于宽高设为具体数值wrap_content的控件,我们都可以手动构造MeasureSpec,而match_parent的情况理论上是做不到的。

对于设置了具体数值宽高的(比如都是100px),我们可以这样构造MeasureSpec

int widthMeasureSpec = MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec,heightMeasureSpec);

对于设置成wrap_content的:

int widthMeasureSpec = MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOTST);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec((1<<30)-1,MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec,heightMeasureSpec);

总结:优点也是可以立即获取到宽高;缺点是无法解决match_parent的情况。

相关文章

  • Android中获取View宽高方法

    Android开发中经常需要获取控件的宽高,比如前不久我在写一个图片加载库时,因为需要对Bitmap进行裁剪就遇到...

  • 获取View宽高

    在onCreate()中获取View宽高 两种方法: 1.使用View.post(Runable runable)...

  • xxx.post(Runnable)分析

    在Activity的onResume方法中view.post(Runnable)能获取到View宽高吗? 在Act...

  • Android View.post()

    View.post()方法使用场景 子线程中更新ui。 onCreate()中调用获取view宽高。 下面看看源码...

  • Android App 知识点整理

    1: 获取控件宽高 控件View有getHeight()和getwidth()方法可以获取宽高,但是如果直接在on...

  • Activity启动流程

    源码分析 通过View.post方法能够获取到宽高 在dispatchAttcahedToWindow方法中执行e...

  • 获取View宽高的四种方式

      一开始写Android获取view的宽高的时候,经常会直接调用一些方法,实际获得的宽高都是0。后来才知道是因为...

  • Android获取View宽高

    在Activity生命周期函数中 onCreate(...) onResume() 获取不到View的实际大小。 ...

  • 为什么view.post()能保证获取到view的宽高?

    转载自 Carson带你学Android:为什么view.post()能保证获取到view的宽高?[https:/...

  • 如何优雅地使用View.post

    简述 在android项目开发的时候,我们经常遇到在代码中获取view的宽高,如果在onCreate中直接获取,返...

网友评论

  • ttdevs:下一篇还有吗?
  • 追梦者king:问一下如果我对一个listview里的一个layout:layoutSecLoan获取宽度,他是占一行的,其实就是想看看它宽度和屏幕宽度1280差多少,但是获取到居然就是269,我的方法是:private void testWidth() {
    WindowManager wm = (WindowManager) getActivity()
    .getSystemService(Context.WINDOW_SERVICE);
    int width = wm.getDefaultDisplay().getWidth();


    int w = View.MeasureSpec.makeMeasureSpec(0,
    View.MeasureSpec.AT_MOST);
    int h = View.MeasureSpec.makeMeasureSpec(0,
    View.MeasureSpec.UNSPECIFIED);

    // layoutSecLoan
    layoutSecLoan.measure(w, h);
    int layoutSecLoanW = layoutSecLoan.getMeasuredWidth();

    //layout_rate
    layout_rate.measure(w, h);
    int layout_rateW = layout_rate.getMeasuredWidth();


    LogMe.i(TAG, "SCREEN width:" + width + ", layoutSecLoan's Wdith:" + layoutSecLoanW + ",layout_rate's Wdith:" + layout_rateW);

    }
    然后layoutSecLoan's应该是整个item的宽,不知道为啥只有269,
    SCREEN width:1280, layoutSecLoan's Wdith:269,layout_rate's Wdith:98

本文标题:Android中获取View宽高方法

本文链接:https://www.haomeiwen.com/subject/hveqlttx.html