這幾天做一個頁面,需要用到ScrollView嵌套ViewPager,而ViewPager(Fragment)中又有兩個Fragment 分别包含ListView以及WebView,大概的層級是這樣的:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX90zdOlXVU9UdGdEZsRnMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TM5UjMyMjM5ETNxYDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
這樣布局就會導緻Viewpager WebView ListView 三個控件都顯示不出來,導緻這樣的原因是,在Measure流程的時候,不能測出這三個控件的寬高,導緻這三個控件不能顯示,說到Measure 大家應該都知道該怎麼解決了吧,沒錯,就是重寫這三個控件的onMeasure方法,我們先來看看重寫的ViewPager,當然重寫ViewPager的方法,網上也有很多,就是關于這個問題的。大家,也可以去看看别人的部落格,下面貼代碼:
public class AutofitHeightViewPager extends ViewPager {
private int current;
private int height = ;
/**
* 儲存position與對于的View
*/
private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();
private boolean scrollble = true;
private static final String TAG = "AutofitHeightViewPager";
public AutofitHeightViewPager(Context context) {
super(context);
}
public AutofitHeightViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mChildrenViews.size() > current) {
View child = mChildrenViews.get(current);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(, MeasureSpec.UNSPECIFIED));
height = child.getMeasuredHeight();
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void resetHeight(int current) {
this.current = current;
if (mChildrenViews.size() > current) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
if (layoutParams == null) {
layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height);
} else {
layoutParams.height = height;
}
Log.d(TAG, "resetHeight: "+height);
setLayoutParams(layoutParams);
}
}
/**
* 儲存position與對于的View
*/
public void setObjectForPosition(View view, int position)
{
mChildrenViews.put(position, view);
}
說好重寫onMeasure 方法,怎麼還多了兩個方法呢?
如果隻重寫onMeasure方法,看看onMeasure方法,你會發現,在方法中,為了所Fragment都能顯示完全,隻會選擇最大值,來作為ViewPager的總高度,那麼,高度較小的那個Fragment下方就會留出很多空白,這樣非常不美觀,最好的辦法就是動态設定目前ViewPager的高度。下面我們看看多出來的方法,是用來幹嘛的。
setObjectForPosition:将目前的Fragment傳遞到類開頭聲明的成員中,建議在初始化Fragment的時候調用一下這個方法,将Fragment存入到目前的自定義的ViewPager中,以便後面使用,Position是查找對應Fragment的Key。
resetHeight:傳入目前ViewPager顯示的頁面下标,擷取到目前的Fragment的實際高度,設定為目前ViewPager的高度,這個方法建議設定ViewPager的頁面切換監聽,來實作設定不同高度。
當然,光重寫ViewPager是不行的,還需要将 ViewPager 中對應加載的控件的onMeasure都重寫,
ListView:
public class AutoFitHeightListView extends ListView {
public AutoFitHeightListView(Context context) {
super(context);
}
public AutoFitHeightListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoFitHeightListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> , MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, mExpandSpec);
}
}
WebView:
public class AutoFitHeightWebView extends WebView {
@SuppressLint("NewApi")
public NoScrollWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public NoScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public NoScrollWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NoScrollWebView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> , MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, mExpandSpec);
}
}
這兩個就隻要重寫哦你Measure方法就可以了,到這就差不多了。
剩下的就是在項目中,把控件都換成自定義的控件就好了。