Android 中ScrollView嵌套GridView,ListView的實例
Android 中ScrollView嵌套GridView,ListView的實例
在Android開發(fā)中,經(jīng)常有一些UI需要進行固定style的動態(tài)布局,然而由于現(xiàn)在的UI都喜歡把一個界面拉的很長,所以我們很多情況下需要使用ScrollView來嵌套列表控件來實現(xiàn)UI。這樣就導(dǎo)致了很多不順心的問題。
問題一:列表控件顯示不完全
原因是嵌套情況下,ScrollView不能正確的計算列表控件的高度。
有兩種解決方案
方案一
在適配器賦值完成后代碼動態(tài)計算列表的高度。這里貼出ListView的計算代碼,GridView的計算方式類似,不過需要考慮列數(shù),下面代碼沒有加上列表控件padding的計算,如果你設(shè)置了這個屬性,需要加上計算代碼
public void setListViewHeightBasedOnChildren(ListView listView) {
// 獲取ListView對應(yīng)的Adapter
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
// listAdapter.getCount()返回數(shù)據(jù)項的數(shù)目
View listItem = listAdapter.getView(i, null, listView);
// 計算子項View 的寬高
listItem.measure(0, 0);
// 統(tǒng)計所有子項的總高度
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
// listView.getDividerHeight()獲取子項間分隔符占用的高度
// params.height最后得到整個ListView完整顯示需要的高度
listView.setLayoutParams(params);
}
方案二
重寫列表控件的onMeasure方法,這種方案不會出現(xiàn)列表控件本身的滾動條,并且viewholder復(fù)用機制會失效
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(1 << 16, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
方案一代碼多,需要多次寫,建議寫成工具類方便調(diào)用;方案二在數(shù)據(jù)量大到不能一屏顯示完的情況下會有性能問題,而且快速滑動的時候ScrollView會不停的去計算列表控件的高度。賊影響繪制性能。
兩種方案有利有弊,大家自己取舍
問題二:列表控件自動獲取焦點,導(dǎo)致ScrollView自動滾動到列表控件所在的位置
這個問題其實有很多種解決方案,歸結(jié)起來是兩種。
方案一
等待列表控件數(shù)據(jù)全部加載完成后(包括圖片加載)調(diào)用ScrollView.fullScroll(ScrollView.FOCUS_UP);
方法讓ScrollView滾動到頂部。這個加載完成的時間不好控制,搞得不好會有滾動動畫出現(xiàn),很尷尬的事情。
方案二
重寫列表控件的如下兩個方法,使之固定返回false
@Override
public boolean isFocused() {
return false;
}
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
return false;
}
兩種方案的優(yōu)缺點很明顯,喔,第二種方案的缺點我目前沒發(fā)現(xiàn)。如果你這么使用發(fā)現(xiàn)了什么坑,請留言告知
問題三 滑動沖突
解決起來也離不開幾個要點,不過首先你得熟悉view的事件傳遞
你需要根據(jù)情況決定重寫列表控件與ScrollView的如下幾個方法,根據(jù)情況給方法返回不同的bool值來告訴控件是否攔截或者傳遞事件,需要哪個控件相應(yīng)哪個方向的滾動事件就攔截哪個方向的事件傳遞,作為一個有追求的開發(fā)者,切記不要一通亂攔截
@Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
給個小彩蛋
getParent().requestDisallowInterceptTouchEvent(boolean b);
這一句代碼可以在子控件里決定是否讓父容器獲取事件
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Android編程實現(xiàn)XML解析與保存的三種方法詳解
這篇文章主要介紹了Android編程實現(xiàn)XML解析與保存的三種方法,結(jié)合實例形式詳細分析了Android實現(xiàn)xml解析的SAX、DOM、PULL三種方法的相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android編程調(diào)節(jié)屏幕亮度(背景燈)及保持背景燈常亮的方法
這篇文章主要介紹了Android編程調(diào)節(jié)屏幕亮度(背景燈)及保持背景燈常亮的方法,涉及Android屏幕相關(guān)屬性涉及技巧,需要的朋友可以參考下2016-01-01

