androidMeasureSpec的三个测量模式
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将处理它们的绘图和放置。
模式数值描述
UNSPECIFIED0(0x00000000)⽗控件没有给⼦视图任何限制,⼦视图可以设置为任意⼤⼩。
究竟1073741824(0x40000000)表⽰⽗控件已经确切的指定了⼦视图的⼤⼩。
最多-2147483648(0x80000000)表⽰⼦查看具体⼤⼩没有尺⼨限制,但是存在上限,上限⼀般为⽗视图⼤⼩。
3.例⼦解析
这⾥分为两个部分例⼦,例⼦⼀是⽗布局是LinearLayout中,⼦布局是LinearLayout中,例⼦⼆是是⽗布局是滚动型,⼦布局是LinearLayout 中。
1)例⼦⼀解释EXACTLY和AT_MOST
布局⽂件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="schemas.android/apk/res/android"
xmlns:tools="schemas.android/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
&ansdotnavi.widget.NormalDot
android:id="@+id/dot1"
android:layout_width="20dp"
android:layout_height="match_parent"
android:background="#F7F6F5" >
</ansdotnavi.widget.NormalDot>
</LinearLayout>
⼦控件,对于具体解释可以看下⾯代码⾥的注释
/**
* @author Administrator
* 2016-10-22
*
* 普通的圆点导航器
* ⽤于测试⽗控件是layout,⼦控件是layout的情况
* 具体可以看l,⾥⾯定义了⼀个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 = Mode(widthMeasureSpec);
int width = Size(widthMeasureSpec);
int mode2 = Mode(heightMeasureSpec);
int height = Size(heightMeasureSpec);
Log.i("lgy", "mode:"+mode+" width:"+width);
Log.i("lgy", "mode2:"+mode2+" height:"+height);
}
}
2)例⼦⼆解析的评论模式
布局⽂件
<?xml version="1.0" encoding="utf-8"?>
&ansdotnavi.widget.LScrollView xmlns:android="schemas.android/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
&ansdotnavi.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" />
-->
</ansdotnavi.widget.NormalDot2>
</ansdotnavi.widget.LScrollView>
⼦控件
/**
* @author Administrator
* 2016-10-22
*
* 普通的圆点导航器
* ⽤于测试⽗控件是ScrollView,⼦控件是layout的情况
* 具体可以看l,⾥⾯定义了⼀个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 = Mode(widthMeasureSpec);
android layout布局int width = Size(widthMeasureSpec);
int mode2 = Mode(heightMeasureSpec);
int height = Size(heightMeasureSpec);
Log.i("lgy", "============mode:"+mode+" width:"+width);
Log.i("lgy", "=============mode2:"+mode2+" height:"+height);
}
}
⽗控件(滚动型)
/**
* @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 = Mode(widthMeasureSpec);
int width = Size(widthMeasureSpec);
int mode2 = Mode(heightMeasureSpec);
int height = Size(heightMeasureSpec);
Log.i("lgy", "ScrollViewmode:"+mode+" width:"+width);
Log.i("lgy", "ScrollViewmode2:"+mode2+" height:"+height);
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论