安卓界面的繪制,需要經過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);
}
}