详细说一下 MeasureSpec.UNSPECIFIED

前面的文章 我留下了一个疑惑,那就是到底为什么 NestedScrollView 要把子 View 的测量模式强行设置为 MeasureSpec.UNSPECIFIED ,这不,在鸿洋的 "wanAndroid" 中,他再次提出了这样的问题:

MesureSpec.UNSPECIFIED

  1. 这个模式什么时候会遇到?
  2. 遇到后怎么处理?
  3. 有什么注意事项?

下面摘自用户「陈小缘啦啦啦」的回答,我觉得回答的非常到位,特别在这里和大家分享一下。

UNSPECIFID,就是未指定的意思,在这个模式下父控件不会干涉子 View 想要多大的尺寸。
那么,这个模式什么时候会onMeasure() 里遇到呢?其实是取决于它的父容器。
就拿最常用的 RecyclerView 做例子,在 Item 进行 measure() 时,如果列表可滚动,并且 Item 的宽或高设置了 wrap_content 的话,那么接下来,itemView 的 onMeasure( )方法的测量模式就会变成 MeasureSpec.UNSPECIFIED
我们不妨打开 RecyclerView 源码,会在 getChildMeasureSpec() 方法里看到这么一句注释:

MATCH_PARENT can't be applied since we can scroll in this dimension, wrap instead using UNSPECIFIED.

它想表达的是:在可滚动的ViewGroup中,不应该限制 Item 的尺寸(如果是水平滚动,就不限制宽度),为什么呢? 因为是可以滚动的,就算 Item 有多宽,有多高,通过滚动也一样能看到滚动前被遮挡的部分。

这里其实也就回答了我之前询问的 NestedScrollView 要强行设置 Item 为 UNSPECIFIED 的原因。
有同学可能会有疑问: 我设置 wrap_content,在 onMeasure() 中应该收到的是 AT_MOST 才对啊,为什么要强制变成 UNSPECIFIED

这是因为考虑到 Item 的尺寸有可能超出这个可滚动的 ViewGroup 的尺寸,而在 AT_MOST 模式下,你的尺寸不能超出你所在的 ViewGroup 的尺寸,最多只能等于,所以用 UNSPECIFIED会更合适,这个模式下你想要多大就多大。

那么,我们在自定义 View 的时候,在测量时发现是 UNSPECIFIED 模式时,应该怎么做呢?

这个就比较自由了,既然尺寸由自己决定,那么我可以写死为 50,也可以固定为 200。但还是建议结合实际需求来定义咯。

比如 ImageView,它的做法就是:有设置图片内容(drawable)的话,会直接使用这个 drawable 的尺寸,但不会超过指定的 MaxWidthMaxHeight, 没有内容的话就是 0。而 TextView 处理 UNSPECIFIED 的方式,和 AT_MOST 是一样的。

当然了,这些尺寸都不一定等于最后 layout 出来的尺寸,因为最后决定子 View 位置和大小的,是在 onLayout() 方法中,在这里你完全可以无视这些尺寸,去 layout()成自己想要的样子。不过,一般不会这么做。

每日一问:详细说一下 MeasureSpec.UNSPECIFIED的更多相关文章

  1. 每日一问:谈谈对 MeasureSpec 的理解

    作为一名 Android 开发,正常情况下对 View 的绘制机制基本还是耳熟能详的,尤其对于经常需要自定义 View 实现一些特殊效果的同学. 网上也出现了大量的 Blog 讲 View 的 onM ...

  2. 每日一问:LayoutParams 你知道多少?

    前面的文章中着重讲解了 View 的测量流程.其中我提到了一句非常重要的话:View 的测量匡高是由父控件的 MeasureSpec 和 View 自身的 `LayoutParams 共同决定的.我们 ...

  3. 每日一问:简述 View 的绘制流程

    Android 开发中经常需要用一些自定义 View 去满足产品和设计的脑洞,所以 View 的绘制流程至关重要.网上目前有非常多这方面的资料,但最好的方式还是直接跟着源码进行解读,每日一问系列一直追 ...

  4. 每日一问:Android 消息机制,我有必要再讲一次!

    坚持原创日更,短平快的 Android 进阶系列,敬请直接在微信公众号搜索:nanchen,直接关注并设为星标,精彩不容错过. 我 17 年的 面试系列,曾写过一篇名为:Android 面试(五):探 ...

  5. 每日一问:谈谈 volatile 关键字

    这是 wanAndroid 每日一问中的一道题,下面我们来尝试解答一下. 讲讲并发专题 volatile,synchronize,CAS,happens before, lost wake up 为了 ...

  6. 每日一问:讲讲 Java 虚拟机的垃圾回收

    昨天我们用比较精简的文字讲了 Java 虚拟机结构,没看过的可以直接从这里查看: 每日一问:你了解 Java 虚拟机结构么? 今天我们必须来看看 Java 虚拟机的垃圾回收算法是怎样的.不过在开始之前 ...

  7. 每日一问:你了解 Java 虚拟机结构么?

    对于从事 C/C++ 程序员开发的小伙伴来说,在内存管理领域非常头疼,因为他们总是需要对每一个 new 操作去写配对的 delete/free 代码.而对于我们 Android 乃至 Java 程序员 ...

  8. android 深入浅出 群内“每日一问” 问答总结

    永远不变的就是变. 俗话说的好,环境改变人生. 常常面对的是一群积极奋进的人,那么你的心态和生活也会变的充满斗志.青春在于折腾,趁我们还年轻,拿出你的激情.踏着泪水载着梦,才干拥有自己的一片天空. 上 ...

  9. 每日一问:面试结束时面试官问"你有什么问题需要问我呢",该如何回答?

    面试结束时面试官问"你有什么问题需要问我呢",该如何回答?

随机推荐

  1. Linux常用命令:fdisk mkfs mount umount fstab实现自动挂载

    写在前 记录点常用命令,fdisk mkfs mount和umount,以及fstab实现自动挂载 fdisk fdisk主要用于操作硬盘的分区表.分区,下面简单记一点最常用的部分 查看当前系统识别到 ...

  2. 最简单的 kubernetes 高可用安装方式

    sealos 项目地址:https://github.com/fanux/sealos 本文教你如何用一条命令构建 k8s 高可用集群且不依赖 haproxy 和 keepalived,也无需 ans ...

  3. Java匹马行天下之JavaSE核心技术——反射机制

    Java反射机制 一.什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及 ...

  4. python 练习题:请利用循环依次对list中的每个名字打印出Hello, xxx!

    方法一: # -*- coding: utf-8 -*- # 请利用循环依次对list中的每个名字打印出Hello, xxx! L = ['Bart', 'Lisa', 'Adam'] n = 0 w ...

  5. mysql启动时出现ERROR 2003问题的解决方法

    目录 写在前面 问题描述 分析原因 问题解决 写在前面 今天,在打开Navicat Permium 链接MySQL 的时候出现Error 2003 的错误. 遂记录产生的原因以及解决方法. 问题描述 ...

  6. webapi处理OPTIONS请求

    报错1信息 Access to XMLHttpRequest at 'http://localhost:4445/api/v/getmsg' from origin 'http://localhost ...

  7. zookeeper知识点总结

    1. 关于ZooKeeper集群服务器数: ZooKeeper 官方确实给出了关于奇数的建议,但绝大部分 ZooKeeper 用户对于这个建议认识有偏差.一个 ZooKeeper 集群如果要对外提供可 ...

  8. Invalid attempt to spread non-iterable instance

    问题在于对数据的操作,或数据类型,或数据名称

  9. django2外键,F表达式,Q表达式

    一对多 环境 两个类:书的类别和文章,一片文章只能有一个作者,一个作者可以有多个文章,这之间组成了一对多的关系 class Category(models.Model): category = mod ...

  10. Caused by: java.lang.ClassNotFoundException: Cannot find class:

    Caused by: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibat ...