android MeasureSpec的三个测量模式
1.MeasureSpec含义
其实可以去看MeasureSpec的文档,里面对MeasureSpec的作用介绍得很清楚.MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。
2.MeasureSpec的三个模式详解不定的,恰恰和AT_MOST
视图大小的基本定义如下:
MeasureSpec.EXACTLY - 视图应该是这么多像素,无论它实际上有多大。
MeasureSpec.AT_MOST - 如果视图的尺寸较小,则视图可以是此尺寸或更小。
MeasureSpec.UNSPECIFIED - 视图可以是它需要的任何大小,以显示它需要显示的内容。
如果父视图的大小绑定,MeasureSpec.AT_MOST将应用于已设置为WRAP_CONTENT的视图。例如,您的父视图可能绑定到屏幕大小。它的孩子也会受到这种规模的束缚,但它可能不会那么大。因此,父视图将MeasureSpec设置为AT_MOST,告诉孩子它可以是0到屏幕大小之间的任何位置。孩子必须做出调整,以确保它符合所提供的范围。
在特殊情况下,界限无关紧要。例如,ScrollView。对于ScrollView,子视图的高度无关紧要。因此,它将为孩子们提供一个未知的视图,告诉孩子他们可以达到他们需要的高度。ScrollView将处理它们的绘图和放置。
翻译一下(直接用软件翻译过来的,不明白的话,下面会通过例子说明):
查看的大小基本定义如下:
MeasureSpec.EXACTLY - 表示父控件已经确切的指定了子查看的大小.MeasureSpec.AT_MOST
- 表示子查看具体大小没有尺寸限制,但是存在上限,上限一般为父查看大小.MeasureSpec
。未知 - 父控件没有给子视任何限制,子查看可以设置为任意大小。
如果父视图的大小已经指定则MeasureSpec.AT_MOST将应用于已设置为WRAP_CONTENT的子视图。例如,你的父视图可能绑定到屏幕大小。它的孩子也会绑定到这个大小,但它可能不是那么大。因此,父视图将MeasureSpec设置为AT_MOST,它告诉孩子它可以在0和屏幕之间的任何地方。孩子必须进行调整,以确保它符合提供的界限。
在特殊情况下,界限无关紧要。例如,一个ScrollView。在ScrollView的情况下,子视图的高度是不相关的。因此,它将向孩子提供一个未知视图,告诉孩子他们可以像他们需要的一样高 .ScrollView将处理它们的绘图和放置。
模式 | 数值 | 描述 |
---|---|---|
UNSPECIFIED | 0(0x00000000) | 父控件没有给子视图任何限制,子视图可以设置为任意大小。 |
究竟 | 1073741824(0x40000000) | 表示父控件已经确切的指定了子视图的大小。 |
最多 | -2147483648(0x80000000) | 表示子查看具体大小没有尺寸限制,但是存在上限,上限一般为父视图大小。 |
3.例子解析
这里分为两个部分例子,例子一是父布局是LinearLayout中,子布局是LinearLayout中,例子二是是父布局是滚动型,子布局是LinearLayout中。
1)例子一解释EXACTLY和AT_MOST
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.transdotnavi.widget.NormalDot
android:id="@+id/dot1"
android:layout_width="20dp"
android:layout_height="match_parent"
android:background="#F7F6F5" >
</com.example.transdotnavi.widget.NormalDot>
</LinearLayout>
子控件,对于具体解释可以看下面代码里的注释
/**
* @author Administrator
* 2016-10-22
*
* 普通的圆点导航器
* 用于测试父控件是layout,子控件是layout的情况
* 具体可以看layout.xml,里面定义了一个LinearLayout父布局,和一个NormalDot子布局
* 测试机器:160dpi 480*800
*/
public class NormalDot extends LinearLayout
{
public NormalDot(Context context)
{
super(context);
}
@SuppressLint("NewApi")
public NormalDot(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public NormalDot(Context context, AttributeSet attrs)
{
super(context, attrs);
}
// MeasureSpec.AT_MOST = -2147483648 [0x80000000];
// MeasureSpec.EXACTLY = 1073741824 [0x40000000];
// MeasureSpec.UNSPECIFIED = 0 [0x0];
// 父布局LinearLayout固定width,height是match_parent(其实如果设置为wrap_content它的宽高也是等于屏幕宽高)
// 情况一:
// 当宽或高设为确定值时:即width=20dp,height=30dp,或者为match_parent。它会使用MeasureSpec.EXACTLY测量模式(表示父控件已经确切的指定了子View的大小)
// 情况二:
// 当宽或高设为wrap_content时,它会使用MeasureSpec.AT_MOST测量模式(表示子View具体大小没有尺寸限制,但是存在上限,上限一般为父View大小)
// 情况三:
// MeasureSpec.UNSPECIFIED,一般是在特殊情况下出现,如在父布局是ScrollView中才会出现这种测量模式
// 注意:
// 父视图可能绑定到屏幕大小。 它的孩子也会绑定到这个大小,但它可能不是那么大。
// 因此,父视图将MeasureSpec设置为AT_MOST ,
// 它告诉孩子它可以在0和屏幕之间的任何地方。 孩子必须进行调整,以确保它符合提供的界限。
// 通过一个例子解释上面面这句化的意思
// 父布局宽高都设置为match_parent,这时候父布局大小就是屏幕大小,这时候,他的子视图设置为width=20dp,height=wrap_content
// 看打出了的日志可以看到宽是20,高是800,这样的话我们应该能在屏幕的左边看到一条白色的宽为20的竖线,
// 但是事实上,我们在界面是没有看到这条竖线的,这是因为子布局可以占据0到屏幕大小这个范围,但是子布局通过调整,将height设置为0了,所以
// 我们看不到任何图像
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int mode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int mode2 = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
Log.i("lgy", "mode:"+mode+" width:"+width);
Log.i("lgy", "mode2:"+mode2+" height:"+height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
2)例子二解析的评论模式
布局文件
<?xml version="1.0" encoding="utf-8"?>
<com.example.transdotnavi.widget.LScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.transdotnavi.widget.NormalDot2
android:id="@+id/dot2"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#F7F6F5" >
<!--
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
-->
</com.example.transdotnavi.widget.NormalDot2>
</com.example.transdotnavi.widget.LScrollView>
子控件
/**
* @author Administrator
* 2016-10-22
*
* 普通的圆点导航器
* 用于测试父控件是ScrollView,子控件是layout的情况
* 具体可以看layout2.xml,里面定义了一个ScrollView父布局,和一个NormalDot2子布局
* 测试机器:160dpi 480*800
*/
public class NormalDot2 extends LinearLayout
{
public NormalDot2(Context context)
{
super(context);
}
/**
* @param context
* @param attrs
* @param defStyleAttr
*/
@SuppressLint("NewApi")
public NormalDot2(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
/**
* @param context
* @param attrs
*/
public NormalDot2(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
// MeasureSpec.AT_MOST = -2147483648 [0x80000000];
// MeasureSpec.EXACTLY = 1073741824 [0x40000000];
// MeasureSpec.UNSPECIFIED = 0 [0x0];
// 这里主要展示的是MeasureSpec.UNSPECIFIED测量模式
// 情况一:垂直的ScrollView
// 父布局ScrollView宽高都是match_parent,子布局是一个NormalDot2设置宽高都是50dp
// 从打出的日志可以看到,宽是以MeasureSpec.EXACTLY模式测量的,width=50,
// 而高是以MeasureSpec.UNSPECIFIED模式测量的,height=0
// 这时候如果NormalDot2布局里没有任何控件,那么就不会显示任何东西
// 但如果在里面加个TextView,那么这个textView就会显示出来(当然这个textView是有内容的,否则也不会显示出来),
// 但这时候height还是以MeasureSpec.UNSPECIFIED模式测量,height=0
// 情况二:水平的ScrollView
// 父布局HorizontalScrollView宽高都是match_parent,子布局是一个NormalDot2设置宽高都是50dp
// 从打出的日志可以看到,宽是MeasureSpec.UNSPECIFIED模式测量的,width=0,
// 而高是以MeasureSpec.EXACTLY模式测量的,height=50
// 这时候如果NormalDot2布局里没有任何控件,那么就不会显示任何东西
// 但如果在里面加个TextView,那么这个textView就会显示出来(当然这个textView是有内容的,否则也不会显示出来),
// 但这时候width还是以MeasureSpec.UNSPECIFIED模式测量,width=0
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int mode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int mode2 = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
Log.i("lgy", "============mode:"+mode+" width:"+width);
Log.i("lgy", "=============mode2:"+mode2+" height:"+height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
父控件(滚动型)
/**
* @author LGY
* @time 2016-10-23
* @action
*/
public class LScrollView extends
HorizontalScrollView
//ScrollView
{
/**
* @param context
*/
public LScrollView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
/**
* @param context
* @param attrs
* @param defStyleAttr
*/
public LScrollView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
/**
* @param context
* @param attrs
*/
public LScrollView(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see android.widget.ScrollView#onMeasure(int, int)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int mode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int mode2 = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
Log.i("lgy", "ScrollViewmode:"+mode+" width:"+width);
Log.i("lgy", "ScrollViewmode2:"+mode2+" height:"+height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
android MeasureSpec的三个测量模式的更多相关文章
- <Android 基础(三)> MVP模式
前言 MVP,这里指的并不是篮球比赛中的MVP(最有价值球员),而是一种代码框架和设计思想,它是由MVC演变而来的. MVP模式(Model-View-Presenter) 是MVC模式的一个衍生.主 ...
- Android:ScrollView和SwipeRefreshLayout高度测量
今天组里的同事要做一个奇葩的效果,要求在ScrollView里嵌套一个RefreshLayout.类似代码如下: <?xml version="1.0" encoding=& ...
- android自定义控件(8)-利用onMeasure测量使图片拉伸永不变形,解决屏幕适配问题
使用ImageView会遇到的问题 在Android应用中,都少不了图片的显示,ImageView,轮播图,ViewPager等等,很多都是来显示图片的,很多时候,我们都希望图片能够在宽度上填充父窗体 ...
- Android -- MeasureSpec
自定义控件都会去重写View的onMeasure方法,因为该方法指定该控件在屏幕上的大小. protected void onMeasure (int widthMeasureSpec, int he ...
- Android中Activity的四大启动模式实验简述
作为Android四大组件之一,Activity可以说是最基本也是最常见的组件,它提供了一个显示界面,从而实现与用户的交互,作为初学者,必须熟练掌握.今天我们就来通过实验演示,来帮助大家理解Activ ...
- Android源码学习之模板方法模式应用
一.模板方法模式定义 模板方法模式定义: defines the skeleton of an algorithm in a method, deferring some steps to subcl ...
- 【转】android 电池(三):android电池系统
关键词:android电池系统电池系统架构 uevent power_supply驱动 平台信息: 内核:linux2.6/linux3.0系统:android/android4.0 平台:S5PV3 ...
- Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags();singleTask的两种启动方式。
原文:Android Activity 的四种启动模式 lunchMode 和 Intent.setFlags();singleTask的两种启动方式. Android Activity 的四种启动模 ...
- 微信5.0 Android版飞机大战破解无敌模式手记
微信5.0 Android版飞机大战破解无敌模式手记 转载: http://www.blogjava.net/zh-weir/archive/2013/08/14/402821.html 微信5.0 ...
随机推荐
- C. Smallest Word
链接 [http://codeforces.com/contest/1043/problem/C] 题意 给你一个只包含a,b的字符串,有一种操作把第1个字符到第i个字符的子串进行反转,问要使最后字符 ...
- Inside the Social Network’s (Datacenter) Network
摘要: 大量服务提供商投资越来越多的更大数据中心来保证基础计算需求以支持他们的服务.因此,研究人员和行业从业者都集中了大量的努力设计网络结构有效互连和管理流量以保证这些数据中心的性能.不幸的是,数据中 ...
- 构建之法-软件测试+质量保障+稳定和发布阶段+IT行业的创新+人、绩效和职业道德
第十三章(软件测试) 要知道为什么有软件测试,首先需要知道软件开发,软件开发者一般都很难检查出自己的错误,所以才需要另外一个人测试,所以软件测试就诞生了. 书本介绍了很多测试方法,各有各的优缺点,至于 ...
- tp5+layui 实现上传大文件
前言: 之前所写的文件上传类通常进行考虑的是文件的类型.大小是否符合要求条件.当上传大文件时就要考虑到php的配置和服务器的配置问题.之前简单的觉得只要将php.ini中的表单上传的 大小,单脚本执行 ...
- 四则运算生成程序——GUI支持和部分功能改进
项目成员:张金生 张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...
- HDU 2015 偶数求和
http://acm.hdu.edu.cn/showproblem.php?pid=2015 Problem Description 有一个长度为n(n<=100)的数列,该数列定义为从2开始的 ...
- Delphi cxGrid加行号
procedure SetRowNumber(var ASender: TcxGridTableView; AViewInfo: TcxCustomGridIndicatorItemViewInfo; ...
- HGOI20181029模拟题解
HGOI20181029模拟题解 /* sxn让我一定要谴责一下出题人和他的数据! */ problem: 给出十进制数a,b,然后令(R)10=(a)10*(b)10,给出c表示一个k进制数(1&l ...
- 获取C++类成员虚函数地址
1.GCC平台 GCC平台获取C++成员虚函数地址可使用如下方法[1]: class Base{ int i; public: virtual void f1(){ cout<<" ...
- 51nod 1479 小Y的数论题
一脸不可做题~~~233333 T<=100000,所以一定要logn出解啦. 但是完全没有头绪*&#……%*&……()……#¥*#@ 题解: 因为2^p+2^p=2^(p+1) ...