Android之ScrollView里嵌套ListView


ScrollView套ListView會存以下兩個問題

  1.里面的listView高度無法算出來,通常只能顯示listview的其中一行

  2.listview不能滾動

  這里我用的是可展開的(ExpandableListView

解決問題一,如果ExpandableListView是的子項是用寫死的布局文件來加載的,只要在設置ListView的Adapter后調用此靜態方法即可讓ListView正確的顯示在其父ListView的ListItem中。但是要注意的是,子ListView的每個Item必須是LinearLayout,不能是其他的,因為其他的Layout(如RelativeLayout)沒有重寫onMeasure(),所以會在onMeasure()時拋出異常。

 1 public static void setListViewHeightBasedOnChildren(ListView listView) { 
 2         ListAdapter listAdapter = listView.getAdapter();  
 3         if (listAdapter == null) { 
 4             return; 
 5         }   
 6         int totalHeight = 0; 
 7         for (int i = 0; i < listAdapter.getCount(); i++) { 
 8             View listItem = listAdapter.getView(i, null, listView); 
 9             listItem.measure(0, 0); 
10             totalHeight += listItem.getMeasuredHeight(); 
11         }   
12         ViewGroup.LayoutParams params = listView.getLayoutParams(); 
13         params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); 
14         listView.setLayoutParams(params); 
15 } 

如果ExpandableListView 的子項是用代碼來代碼動態加載的,那么給每個子項定義一個高度,這個就可以計算整個listview的高度了。代碼如下:

先定義子項高度

public static final int ItemHeight = 85;

定義子項的TextView布局

1 static public TextView getTextView(Context context) {
2       AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
3            ViewGroup.LayoutParams.FILL_PARENT, ItemHeight);
4       TextView textView = new TextView(context);
5       textView.setLayoutParams(lp);
6       textView.setTextColor(Color.BLACK);
7       textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
8       return textView;
9   }

然后extends BaseExpandableListAdapter中重寫以下方法,其中getChild(groupPosition, childPosition).toString()是從數組中讀出來的要顯示在子項TextView中的文字。

1    @Override
2    public View getChildView(int groupPosition, int childPosition,
3         boolean isLastChild, View convertView, ViewGroup parent) {
4       TextView textView = getTextView(this.parentContext);
5       textView.setText(getChild(groupPosition, childPosition).toString());
6       textView.setPadding(myPaddingLeft + PaddingLeft, 0, 0, 0);
7       return textView;
8    }

這樣,問題一就解決了。

問題二就是ScrollView中嵌套listView后ListView不能進行滑動,只能看到顯示出來的ListView一部分,解決辦法原理很簡單ScrollView有一個方法requestDisallowInterceptTouchEvent(boolean);這個方法是設置是否交出ontouch權限的,如果讓外層的scrollview.requestDisallowInterceptTouchEvent(false);那么外層的onTouch權限會失去,這樣里面的listview就能拿到ontouch權限了,listView就能滾動了。

  問題是:權限只有一個,要支持兩個view都能滾動。監聽OnTouch的MotionEvent.ACTION_SCROLL:事件當手指觸到listview的時候,讓外面的scrollview交出權限,當手指觸碰到listview之外的時候,讓外面的scrollview重新獲得權限。這樣ok了。R.id.hlpg_main_lv:是listview對應的id,R.id.hlpg_main_allcontent:是listview之外的布局的id。

  且看代碼實現:

 1     case R.id.hlpg_main_lv:
 2            sView.requestDisallowInterceptTouchEvent(false);
 3            break;
 4      case R.id.hlpg_main_allcontent:              
 5            sView.requestDisallowInterceptTouchEvent(true);
 6            break;
 7      default:               
 8            sView.requestDisallowInterceptTouchEvent(true);
 9            break;
10                      

這樣之后第二個問題也就解決了。

Listview中還提供了對listView滾動的監聽,設置這些監聽便可以做一些相應的操作

 1 expandableListView.setOnScrollListener(new OnScrollListener() {
 2         @Override
 3         public void onScrollStateChanged(AbsListView view, int scrollState) {
 4            switch (scrollState) {   // 當不滾動時
 5            case OnScrollListener.SCROLL_STATE_IDLE:
 6               // TODO coding here dosometing
 7               break;
 8            }
 9         }      
10         @Override
11         public void onScroll(AbsListView view, int firstVisibleItem,
12               int visibleItemCount, int totalItemCount) {
13             // TODO coding here dosometing
14         }
15       });

這個問題是在開發過程中遇到的,最初想着用其它方式來實現,發現越做越復雜還達不到想要的效果,最后翻閱資料才發現可以來切換ScrollView和ListView之間的OnTouch焦點實現嵌套滑動,希望這個技術分享解決大家遇到的同類問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM