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

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

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

1、onWindowFocusChanged

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

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是合理的。

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

(0)

相关推荐

  • Android App中自定义View视图的实例教程

    一.基础 很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 3.重写onMesure 4.重写onDraw 我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的. 1.自定义View的属性,首先在res/values/  下建立一个attrs.xm

  • Android ImageView 固定宽高比例的实现方法

    Android ImageView 固定宽高比例的实现方法 本文主要介绍 ImageView 固定宽高比例, 方法一:设置 adjustViewBounds="true", 方法二:使用 Universal-Image-Loader 图片缓存类,需要注意的是方法二和方法一同时使用导致设置无效. 方法一:设置 adjustViewBounds="true" <ImageView android:id="@+id/img_banner" and

  • 4种Android获取View宽高的方式

    有时我们会有基于这样的需求,当Activity创建时,需要获取某个View的宽高,然后进行相应的操作,但是我们在onCreate,onStart中获取View的大小,获取到的值都是0,只是由于View的绘制工程还未完成,和在onCreate中弹出Dialog或者PopupWindow会报一个Activity not running原理类似. 接下来就为大家介绍几种获取View宽高的方法: 第一种方式:重写Activity中的onWindowFocusChanged,当Activity获取到焦点的

  • Android开发中获取View视图宽与高的常用方法小结

    本文实例讲述了Android开发中获取View视图宽与高的常用方法.分享给大家供大家参考,具体如下: 一.根据WindowManager管理器获得 1)这两种方法在屏幕未显示的时候,还是处于0的状态,即要在setContentView调用之后才有效. 2)Activity必须如此设置才能获得view的宽高 //设置为无标题 requestWindowFeature(Window.FEATURE_NO_TITLE); //设置为全屏模式getWindow().setFlags(WindowMana

  • Android视图控件架构分析之View、ViewGroup

    在Android中,视图控件大致被分为两类,即ViewGroup和View,ViewGroup控件作为父控件,包含并管理着子View,通过ViewGroup和View便形成了控件树,各个ViewGoup对象和View对象就是控件树中的节点.在控件树中,以树的深度来遍历查找对应的控件元素,同时,上层控件负责子控件的测量与绘制,并传递交互事件. Android控件树: AndroidUI界面架构图: 一.测量View的工具类:MeasureSpec 1.MeasureSpec包含了测量的模式和测量的

  • Android获取屏幕或View宽度和高度的方法

    本文实例讲述了Android获取屏幕或View宽度和高度的方法.分享给大家供大家参考,具体如下: 在Activity中获取屏幕的高度和宽度 Display display=getWindowManager().getDefaultDisplay(); int width=display.getWidth(); int height=display.getHeight(); 在重写ViewGroup中获取屏幕的有效宽度和高度在OnMesure方法中 protected void onMeasure

  • Android视图的绘制流程(上) View的测量

    综述 View的绘制流程可以分为三大步,它们分别是measure,layout和draw过程.measure表示View的测量过程,用于测量View的宽度和高度:layout用于确定View在父容器的位置:draw则是负责将View绘制到屏幕中.下面主要来看一下View的Measure过程. 测量过程 View的绘制流程是从ViewRoot的performTraversals方法开始的,ViewRoot对应ViewRootImpl类.ViewRoot在performTraversals中会调用p

  • Android开发之自定义View(视图)用法详解

    本文实例讲述了Android开发之自定义View(视图)用法.分享给大家供大家参考,具体如下: View类是Android的一个超类,这个类几乎包含了所有的屏幕类型.每一个View都有一个用于绘图的画布,这个画布可以进行任意扩展.在游戏开发中往往需要自定义视图(View),这个画布的功能更能满足我们在游戏开发中的需要.在Android中,任何一个View类都只需重写onDraw 方法来实现界面显示,自定义的视图可以是复杂的3D实现,也可以是非常简单的文本形式等. 为了实现自定义View,需要创建

  • Android中RecyclerView的item宽高问题详解

    前言 本文主要给大家介绍了关于Android中RecyclerView的item宽高问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 在创建viewholder传入的View时,如果不指定其viewgroup,就会出现宽高只包裹显示内容的问题. View view = LayoutInflater.from(context).inflate(R.layout.test_test,null); 上面的做法就会出问题 改成这样就可以正常显示设置的宽高 View vie

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

    <Android开发艺术探索>笔记: 在Activity的onCreate()或者onResume()中去获得View的高度的时候不能正确获得宽度和高度信息,这是因为 View的measure过程和Activity的生命周期不是同步执行的,因此无法保证Activity执行了onCreate onStart onResume时,某个View已经测量完毕了,如果还没有测量完,那么获得的宽高就是0.可以通过下面几种方式来获得: 1.onWindowFocusChanged onWindowFocus

  • Android 获得屏幕宽高的三种方式

    老风格,废话不多说了,直接给大家贴android获取屏幕宽高的代码了. 主要代码: package com.km.screeninfo; import android.os.Bundle; import android.support.v.app.Fragment; import android.support.v.app.FragmentActivity; import android.util.DisplayMetrics; import android.view.LayoutInflate

  • Android中获取控件宽高的4种方法集合

    借鉴自开发艺术 1.onWindowFocusChanged 这个方法会被调用多次,在View初始化完毕后会调用,当Activity的窗口得到焦点和失去焦点都会被调用一次(Activity继续执行和暂停执行时). @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { int width = view.getMeasur

  • Android源码解析onResume方法中获取不到View宽高

    目录 前言 问题1.为什么onCreate和onResume中获取不到view的宽高? 问题2.为什么View.post为什么可以获取View宽高? 结论 前言 有一个经典的问题,我们在Activity的onCreate中可以获取View的宽高吗?onResume中呢? 对于这类八股问题,只要看过都能很容易得出答案:不能. 紧跟着追问一个,那为什么View.post为什么可以获取View宽高? 今天来看看这些问题,到底为何? 今日份问题: 为什么onCreate和onResume中获取不到vie

  • android中Webview实现截屏三种方式小结

    本人最近学习了android中Webview实现截屏三种方式,下面我来记录一下,有需要了解的朋友可参考.希望此文章对各位有所帮助. 第一种方式 通过调用webview.capturePicture(),得到一个picture对象,根据图像的宽和高创建一个Bitmap,再创建一个canvas,绑定bitmap,最后用picture去绘制. //获取Picture对象 Picture picture = wv_capture.capturePicture(); //得到图片的宽和高(没有reflec

  • Android实现底部状态栏切换的两种方式

    Android开发过程中,特别是新开的项目,底部状态栏的切换使用的频率非常的高,主要的实现方式有: (1).TabLayout + Fragment     (2).FragmentTabHost + Fragment     (3).BottomNavigationView + Fragment     (4).RidioGroup + Fragment 这里我先介绍前面两种实现方式,后面两种后期再贴出实现方式. 一.使用TabLayout + Fragment + ViewPager实现 1

  • Android实现关机与重启的几种方式(推荐)

    下面我们来探究Android如何实现关机,重启:在Android中这种操作往往需要管理员级别,或者root Android实现的方式如下几种: 默认的SDK并没有提供应用开发者直接的Android系统关机或重启的API接口,一般来讲,实现Android系统的关机或重启,需要较高的权限(系统权限甚至Root权限).所以,在一般的APP中,如果想要实现关机或重启功能,要么是在App中声明系统权限,要么是通过某种"间接"的方式,比如广播或反射,来间接实现系统关机或重启.再者,就是放在源码环境

  • Android中实现多线程操作的几种方式

    目录 前言 最基础的方式 继承Thread类并实现run()方法 匿名内部类 实现Runnable接口 callable+FutureTask 线程池 手动创建线程池 使用Executors创建线程池 Android中特有的实现多线程 使用HandlerThread 使用IntentService JobIntentService/JobScheduler WorkManager WorkManager 使用协程 AsyncTask 结语 前言 多线程一直是一个老大难的问题,首先因为它难以理解,

  • Android如何添加控件监听器(三种方式)

    目录 本文概述: 方式一:在布局中添加onClick属性 方式二:采用匿名内部类 方式三:MainActivity 实现 View.OnClickListener 接口 本文概述: 本文介绍了,在Android中为控件添加监听的三种常见方式 设置控件的onClick属性 采用匿名内部类 MainActivity 实现 View.OnClickListener 接口 方式一:在布局中添加onClick属性 编写思路: 在布局文件中: 指定控件 id 指定控件onClick属性 在MainActiv

随机推荐