欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 获得View宽高的几种方式总结

程序员文章站 2022-06-29 11:57:45
《android开发艺术探索》笔记: 在activity的oncreate()或者onresume()中去获得view的高度的时候不能正确获得宽度和高度信息,这是因为 v...

《android开发艺术探索》笔记:

在activity的oncreate()或者onresume()中去获得view的高度的时候不能正确获得宽度和高度信息,这是因为 view的measure过程和activity的生命周期不是同步执行的,因此无法保证activity执行了oncreate onstart onresume时,某个view已经测量完毕了,如果还没有测量完,那么获得的宽高就是0。可以通过下面几种方式来获得:

1、onwindowfocuschanged

onwindowfocuschanged:view已经初始化完毕,宽高已经有了,需要注意onwindowfocuschanged会被调用多次,activity得到焦点和失去焦点都会执行这个回调,见下图:

Android 获得View宽高的几种方式总结

1、activity首次进入的时候执行的方法

2、跳转到另一个activity时

3、返回到当前activity时
可见当执行onresume和onpause时,onwindowfocuschanged都会被调用。

 @override
 public void onwindowfocuschanged(boolean hasfocus) {
   super.onwindowfocuschanged(hasfocus);
   if (hasfocus) {
     //获得宽度
     int width = view.getmeasuredwidth();
     //获得高度
     int height = view.getmeasuredheight();
   }
 }

2、view.post(runnable)

通过post可以将一个runnable投递到消息队列的尾部,等待looper调用此runnable的时候,view也已经初始化好了,示例:

 @override
 protected void onstart() {
   super.onstart();
   view.post(new runnable() {
     @override
     public void run() {
       int width=view.getmeasuredwidth();
       int height=view.getmeasuredheight();
     }
   })
 }

3、viewtreeobserver

使用viewtreeobserver的众多回调可以完成这个功能,比如使用ongloballayoutlistener这个接口,当view树的状态发生改变或者view树内部的view的可见性发生改变时,ongloballayout方法将会被回调,这是获取view宽高很好的一个时机,需要注意的是,伴随着view树的状态改变,ongloballayout会被调用多次,示例:

@override
protected void onstart() {
  super.onstart();
  viewtreeobserver observer=view.getviewtreeobserver();
  observer.addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener() {
    @override
    public void ongloballayout() {
      view.getviewtreeobserver().removeongloballayoutlistener(this);
      int width=view.getmeasuredwidth();
      int height=view.getmeasuredheight();
    }
  });
}

4、view.measure(int widthmeasurespec, int heightmeasurespec)

通过手动对view进行measure来得到view的宽高,这里要分情况处理,根据view的layoutparams来分:

match-parent

无法测出具体的宽高,因为根据view的measure过程,构造此种measurespec需要知道parentsize,即父容器的剩余空间,而这个值我们是不知道的,所以不能测出view的大小。

具体的数值(dp/px)

比如宽高都是100px,如下measure:

 int widthmeasurespec = view.measurespec.makemeasurespec(100, view.measurespec.exactly);
 int heightmeasurespec = view.measurespec.makemeasurespec(100, view.measurespec.exactly);
 view.measure(widthmeasurespec, heightmeasurespec);

wrap_content

如下measure:

 int widthmeasurespec = view.measurespec.makemeasurespec((1 << 30) - 1, view.measurespec.at_most);
 int heightmeasurespec = view.measurespec.makemeasurespec((1 << 30) - 1, view.measurespec.at_most);
 view.measure(widthmeasurespec, heightmeasurespec);

view的specsize使用30位二进制表示,也就是说最大是30个1,也就是(1 << 30) - 1,在最大化模式下,我们用view理论上能支持的最大值去构造measurespec是合理的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。