ViewPager +fragment+listview 高度適配,出現(xiàn)大部分空白的問題

現(xiàn)象:

viewpager 嵌套多個fragment违寿。fragment中有l(wèi)istview湃交。在切換的時時候,大家會遇到這種情況藤巢,listview的內(nèi)容有多有少搞莺,但是viewpager都是以最高的listview的位置,這樣就會導致高度比較小向上滑動的時候會出現(xiàn)空白掂咒。

遇到這問題才沧,首先會想到的是ViewPager高度沒有自動適配listview。那么我們首先可以根據(jù)獲取fragment中l(wèi)istview的高度動態(tài)設置viewPager高度绍刮。

第一步自定義ViewPager温圆。

```

/**

*?自動適應高度的ViewPager

*?@author

*

*/

public class CustomViewPager extendsViewPager?{

publicCustomViewPager(Context?context)?{

super(context);

}

public CustomViewPager(Context?context,?AttributeSet?attrs)?{

super(context,?attrs);

}

@Override

protected void ?onMeasure(intwidthMeasureSpec,intheightMeasureSpec)?{

intheight?=0;

for(inti?=0;?i?<?getChildCount();?i++)?{

View?child?=?getChildAt(i);

child.measure(widthMeasureSpec,?MeasureSpec.makeMeasureSpec(0,?MeasureSpec.UNSPECIFIED));

inth?=?child.getMeasuredHeight();

if(h?>?height)

height?=?h;

}

heightMeasureSpec?=?MeasureSpec.makeMeasureSpec(height,?MeasureSpec.EXACTLY);

super.onMeasure(widthMeasureSpec,?heightMeasureSpec);

}

}

```

這是最常見的一種處理辦法,選擇你fragment中高度最大的那個作為你整個viewpager的高度孩革。解決了沖突問題岁歉,但你會遇到這樣一個棘手的問題:所有viewpager中的fragment都是那個最大的高度,如果你的fragment中view的高度很小的話膝蜈,或者view的高度過大的話锅移,會導致自身或者其他fragment中出現(xiàn)大面積空白。所以綜上所述饱搏,我們要達到的效果是去除這空白非剃,使viewpager的高度真正“自適應”。所以進一步升級 viewpager的自定義

升級版的viewpager

```

importandroid.content.Context;

importandroid.support.v4.app.Fragment;

importandroid.support.v4.view.ViewPager;

importandroid.util.AttributeSet;

importandroid.util.TypedValue;

importandroid.view.MotionEvent;

importandroid.view.View;

importandroid.widget.LinearLayout;

importjava.util.HashMap;

importjava.util.Map;

/**

*?Created?by?vipui?on?16/8/25.

*/

public ?class ?CustomViewpager ?extends ?ViewPager?{

private ?int ?current;

privateintheight?=0;

privatebooleanscrollble?=true;

publicCustomViewpager(Context?context)?{

super(context);

}

publicCustomViewpager(Context?context,?AttributeSet?attrs)?{

super(context,?attrs);

}

@Override

protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec)?{

if(getChildCount()?>?current)?{

View?child?=?getChildAt(current);

child.measure(widthMeasureSpec,?MeasureSpec.makeMeasureSpec(0,?MeasureSpec.UNSPECIFIED));

inth?=?child.getMeasuredHeight();

height?=?h;

}

heightMeasureSpec?=?MeasureSpec.makeMeasureSpec(height,?MeasureSpec.EXACTLY);

super.onMeasure(widthMeasureSpec,?heightMeasureSpec);

}

publicvoidresetHeight(intcurrent)?{

this.current?=?current;

if(getChildCount()?>?current)?{

LinearLayout.LayoutParams?layoutParams?=?(LinearLayout.LayoutParams)?getLayoutParams();

if(layoutParams?==null)?{

layoutParams?=newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,?height);

}else{

layoutParams.height?=?height;

}

setLayoutParams(layoutParams);

}

}

@Override

publicbooleanonTouchEvent(MotionEvent?ev)?{

if(!scrollble)?{

returntrue;

}

returnsuper.onTouchEvent(ev);

}

publicbooleanisScrollble()?{

returnscrollble;

}

publicvoidsetScrollble(booleanscrollble)?{

this.scrollble?=?scrollble;

}

}

```

onMeasure()測量控件的方法推沸,resetHeight()重置viewpager的高度的方法努潘,從代碼中可以看出在調用resetHeight()方法中傳入實參current后,viewpager的高度會變成你傳入實參對應下標的fragment的高度坤学,那么在哪里調用這個方法呢?請看代碼:

```

viewpager.setOnPageChangeListener(newViewPager.OnPageChangeListener() {

@Override

publicvoidonPageScrolled(intposition,floatpositionOffset,intpositionOffsetPixels)?{

}

@Override

publicvoidonPageSelected(intposition)?{

viewpager.resetHeight(position);

}

}

@Override

publicvoidonPageScrollStateChanged(intstate)?{

}

});

activityScdetailsBottomVp.resetHeight(0);

}

```

在viewpager中的onpagerChagelistener的方法中报慕,當你改變viewpager的pager頁位置時重置viewpager的高度深浮。好了如果你按照這個邏輯去做已經(jīng)很接近實現(xiàn)了,但要說明一個問題眠冈,很重要的一個問題飞苇,在低版本的SDK下菌瘫,似乎沒什么問題,但是在高版本SDK下布卡,就有了問題雨让。這個問題糾結了我一天多,因為我在Android4.3的手機忿等,完全實現(xiàn)了栖忠,但是在隊友Android6.0的手機下就出現(xiàn)了問題。(這是因為高版本中viewpager有改動贸街,并不知道有什么改動庵寞,覺得是預加載的改動)對的,高度不對應薛匪,就是你viewpager中的fragment不是自己本身的高度捐川,可能是其他fragment的高度,這個問題逸尖,大家都應該想的到古沥,viewpager的預加載導致的(3個或3個以上的子view),viewpager在加載當前fragment的過程中會預加載臨近兩個的fragment娇跟,所以岩齿,拿viewpager中有三個fragment來說,你的第一個fragment的高度是第三個fragment的高度逞频,(因為預加載到第三個)第一你們第二個fragment的高度是你 第一個fragment的高度(預加載到第一個)纯衍,以此類推。解決這個問題的方法有兩個苗胀,

第一個辦法:

```

activityScdetailsBottomVp.setOnPageChangeListener(newViewPager.OnPageChangeListener() {

@Override

publicvoidonPageScrolled(intposition,floatpositionOffset,intpositionOffsetPixels)?{

}

@Override

publicvoidonPageSelected(intposition)?{

if(position?==0)?{

if(Build.VERSION.SDK_INT?>?Build.VERSION_CODES.KITKAT)?{

activityScdetailsBottomVp.resetHeight(1);

}else{

activityScdetailsBottomVp.resetHeight(0);

}

}elseif(position?==1)?{

if(Build.VERSION.SDK_INT?>?Build.VERSION_CODES.KITKAT)?{

activityScdetailsBottomVp.resetHeight(2);

}else{

activityScdetailsBottomVp.resetHeight(1);

}

}else{

if(Build.VERSION.SDK_INT?>?Build.VERSION_CODES.KITKAT)?{

activityScdetailsBottomVp.resetHeight(0);

}else{

activityScdetailsBottomVp.resetHeight(2);

}

}

}

@Override

publicvoidonPageScrollStateChanged(intstate)?{

}

});

if(Build.VERSION.SDK_INT?>?Build.VERSION_CODES.KITKAT)?{

activityScdetailsBottomVp.resetHeight(1);

}else{

activityScdetailsBottomVp.resetHeight(0);

}

```

簡單粗暴的辦法襟诸,用版本控制你要加載的頁面高度,親測可以解決基协,但是并不知道到了哪個高版本出現(xiàn)了變化歌亲,我這里用的是KITKAT(android4.4),這個臨界點有待商量。那么是否會有更好的辦法解決呢澜驮,這就得考慮第二種辦法了陷揪,也是我使用的辦法,也是自定義viewpager杂穷,大致差不多悍缠,不過也修改了不少。

第二種:

```

importandroid.content.Context;

importandroid.os.Build;

importandroid.support.v4.app.Fragment;

importandroid.support.v4.view.ViewPager;

importandroid.util.AttributeSet;

importandroid.util.TypedValue;

importandroid.view.MotionEvent;

importandroid.view.View;

importandroid.widget.LinearLayout;

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.LinkedHashMap;

importjava.util.List;

importjava.util.Map;

/**

*?Created?by?vipui?on?16/8/25.

*/

publicclassCustomViewpagerextendsViewPager?{

privateintcurrent;

privateintheight?=0;

/**

*?保存position與對于的View

*/

privateHashMap?mChildrenViews?=newLinkedHashMap();

privatebooleanscrollble?=true;

publicCustomViewpager(Context?context)?{

super(context);

}

publicCustomViewpager(Context?context,?AttributeSet?attrs)?{

super(context,?attrs);

}

@Override

protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec)?{

if(mChildrenViews.size()?>?current)?{

View?child?=?mChildrenViews.get(current);

child.measure(widthMeasureSpec,?MeasureSpec.makeMeasureSpec(0,?MeasureSpec.UNSPECIFIED));

height?=?child.getMeasuredHeight();

}

heightMeasureSpec?=?MeasureSpec.makeMeasureSpec(height,?MeasureSpec.EXACTLY);

super.onMeasure(widthMeasureSpec,?heightMeasureSpec);

}

publicvoidresetHeight(intcurrent)?{

this.current?=?current;

if(mChildrenViews.size()?>?current)?{

LinearLayout.LayoutParams?layoutParams?=?(LinearLayout.LayoutParams)?getLayoutParams();

if(layoutParams?==null)?{

layoutParams?=newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,?height);

}else{

layoutParams.height?=?height;

}

setLayoutParams(layoutParams);

}

}

/**

*?保存position與對于的View

*/

publicvoidsetObjectForPosition(View?view,intposition)

{

mChildrenViews.put(position,?view);

}

@Override

publicbooleanonTouchEvent(MotionEvent?ev)?{

if(!scrollble)?{

returntrue;

}

returnsuper.onTouchEvent(ev);

}

publicbooleanisScrollble()?{

returnscrollble;

}

publicvoidsetScrollble(booleanscrollble)?{

this.scrollble?=?scrollble;

}

}

```

setObjectForPosition()方法中是為了調用存放你的view和他對應的position耐量,這個是參考了鴻洋大神的一篇文章

setObjectForPosition()這個方法了飞蚓,請看我的一個fragment

```

private CustomViewpager vp;

private int index;

publicSecurityInfoFragment(CustomViewpager vp,int index) {

this.vp?=?vp;

}

@Nullable

@Override

publicView?onCreateView(LayoutInflater?inflater,@NullableViewGroup?container,@NullableBundle?savedInstanceState)?{

View?view?=?inflater.inflate(R.layout.xxxxx,null);

vp.setObjectForPosition(view,index);

return view;

}

```

最后一步廊蜒,就是調用resetheight()方法了趴拧,請look代碼

```

activityScdetailsBottomVp.setOnPageChangeListener(newViewPager.OnPageChangeListener() {

@Override

publicvoidonPageScrolled(intposition,floatpositionOffset,intpositionOffsetPixels)?{

}

@Override

publicvoidonPageSelected(intposition)?{

activityScdetailsBottomVp.resetHeight(position);//這句很重要

}

@Override

publicvoidonPageScrollStateChanged(intstate)?{

}

});

activityScdetailsBottomVp.resetHeight(0);//這句更重要

}

```

最后溅漾,特別聲明,本編參考了大神們的博客:

參考了鴻洋大神的一篇文章:http://blog.csdn.net/lmj623565791/article/details/38026503

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末著榴,一起剝皮案震驚了整個濱河市添履,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脑又,老刑警劉巖暮胧,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挂谍,居然都是意外死亡叔壤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門口叙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炼绘,“玉大人,你說我怎么就攤上這事妄田“沉粒” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵疟呐,是天一觀的道長谆吴。 經(jīng)常有香客問我向楼,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任糖耸,我火速辦了婚禮镊折,結果婚禮上垃帅,老公的妹妹穿的比我還像新娘中姜。我一直安慰自己,他們只是感情好薯演,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布撞芍。 她就那樣靜靜地躺著,像睡著了一般跨扮。 火紅的嫁衣襯著肌膚如雪序无。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天衡创,我揣著相機與錄音帝嗡,去河邊找鬼。 笑死璃氢,一個胖子當著我的面吹牛哟玷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拔莱,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼碗降,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塘秦?” 一聲冷哼從身側響起讼渊,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尊剔,沒想到半個月后爪幻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡须误,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年挨稿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片京痢。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡奶甘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出祭椰,到底是詐尸還是另有隱情臭家,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布方淤,位于F島的核電站钉赁,受9級特大地震影響,放射性物質發(fā)生泄漏携茂。R本人自食惡果不足惜你踩,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讳苦。 院中可真熱鬧带膜,春花似錦、人聲如沸医吊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卿堂。三九已至束莫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間草描,已是汗流浹背览绿。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穗慕,地道東北人饿敲。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像逛绵,于是被迫代替她去往敵國和親怀各。 傳聞我的和親對象是個殘疾皇子倔韭,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 這是谷歌官方給我們提供的一個兼容低版本安卓設備的軟件包,里面包囊了只有在安卓3.0以上可以使用的api瓢对。而view...
    Ten_Minutes閱讀 5,740評論 1 19
  • viewpager是用在滾動中相對比較多的硕蛹,最近做一個定時滾動顯示viewpager內(nèi)容醇疼。 步驟: 一:在布局文件...
    jiangbin1992閱讀 1,102評論 0 2
  • 首先描述下需求: 1、新增短信時法焰,進來收件人是為空秧荆,顯示一行文字(提醒) 2、從通訊錄選擇聯(lián)系人后埃仪,回到短信編輯界...
    小學生寫代碼閱讀 648評論 0 0
  • Android開發(fā)藝術探索筆記 SpecMode UNSPECIFIED乙濒,表示一種測量狀態(tài),對View的大小不做限...
    YangGui閱讀 682評論 0 3
  • 一開始讓你不舒服的地方千萬不要忍贵试,最后讓你們分開的琉兜,肯定是因為當初那些不愿意。
    空的了閱讀 168評論 0 0