安卓界面的绘制,需要经过measure、layout、draw三个过程,其中measure决定了控件的大小。需要了解一些MeasureSpec的知识才能理解measure高度的计算。
MeasureSpec的知识
MeasureSpec是一个32位int值,高2位为测量的模式,低30位为测量的大小。测量的模式可以分为以下三种。
1)EXACTLY: 精确值模式,当layout_width或layout_height指定为具体数值,或者为match_parent时,系统使用EXACTLY。
2)AT_MOST:最大值模式,指定为wrap_content时,控件的尺寸不能超过父控件允许的最大尺寸。
3)UNSPECIFIED:不指定测量模式,View想多大就多大,一般不太使用。
android源码中关于三种模式的定义:
EXACTLY:The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be.
AT_MOST:The child can be as large as it wants up to the specified size
UNSPECIFIED:The parent has not imposed any constraint on the child. It can be whatever size it wants
自适应高度的ListView
默认情况下,即时设置了layout_height为“wrap-content”,ListView仍然会充满全屏,效果和"match-parent"一致。
可以通过重写ListView的onMeasure方法来实现wrap-content效果。
package cn.com.example.common.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
public class WrapContentListView extends ListView {
public WrapContentListView (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public WrapContentListView (Context context, AttributeSet attrs) {
super(context, attrs);
}
public WrapContentListView (Context context) {
super(context);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
自适应高度的GridView
与listview的情况类似,代码如下:
package cn.com.example.common.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
public class WrapContentGridView extends GridView {
public WrapContentGridView (Context context) {
super(context);
}
public WrapContentGridView (Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}