Android 中ScrollView嵌套GridView,ListView的實例
Android 中ScrollView嵌套GridView,ListView的實例
在Android開發(fā)中,經(jīng)常有一些UI需要進行固定style的動態(tài)布局,然而由于現(xiàn)在的UI都喜歡把一個界面拉的很長,所以我們很多情況下需要使用ScrollView來嵌套列表控件來實現(xiàn)UI。這樣就導致了很多不順心的問題。
問題一:列表控件顯示不完全
原因是嵌套情況下,ScrollView不能正確的計算列表控件的高度。
有兩種解決方案
方案一
在適配器賦值完成后代碼動態(tài)計算列表的高度。這里貼出ListView的計算代碼,GridView的計算方式類似,不過需要考慮列數(shù),下面代碼沒有加上列表控件padding的計算,如果你設置了這個屬性,需要加上計算代碼
public void setListViewHeightBasedOnChildren(ListView listView) { // 獲取ListView對應的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復用機制會失效
@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會不停的去計算列表控件的高度。賊影響繪制性能。
兩種方案有利有弊,大家自己取舍
問題二:列表控件自動獲取焦點,導致ScrollView自動滾動到列表控件所在的位置
這個問題其實有很多種解決方案,歸結起來是兩種。
方案一
等待列表控件數(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值來告訴控件是否攔截或者傳遞事件,需要哪個控件相應哪個方向的滾動事件就攔截哪個方向的事件傳遞,作為一個有追求的開發(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);
這一句代碼可以在子控件里決定是否讓父容器獲取事件
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關文章
Android編程實現(xiàn)XML解析與保存的三種方法詳解
這篇文章主要介紹了Android編程實現(xiàn)XML解析與保存的三種方法,結合實例形式詳細分析了Android實現(xiàn)xml解析的SAX、DOM、PULL三種方法的相關操作技巧,需要的朋友可以參考下2017-08-08Android編程調(diào)節(jié)屏幕亮度(背景燈)及保持背景燈常亮的方法
這篇文章主要介紹了Android編程調(diào)節(jié)屏幕亮度(背景燈)及保持背景燈常亮的方法,涉及Android屏幕相關屬性涉及技巧,需要的朋友可以參考下2016-01-01