在ScrollView中使用ListView

来源:互联网 发布:java什么意思 编辑:程序博客网 时间:2024/05/17 07:12

     从原则上来说,不应该在一个可滚动的视图中再放置一个可滚动的视图,即滚动视图的嵌套。原因很简单,如果不加以限制,当移动事件发生时,触摸点处于有嵌套关系的多个滚动视图的交叠部分,安卓无法区分该事件应该由哪一个滚动视图消费所以,如果不是必须,可以使用其它的一些替代方式。比如用LinearLayout取代ListView放在一个ScrollView中,或者将ScrollView作为一个独立的View充当ListViewheader

     如果必须要进行嵌套,那么可以采用如下的方式:

ListView lv = (ListView)findViewById(R.id.listview); lv.setOnTouchListener(newListView.OnTouchListener() {       @Override       public boolean onTouch(View v, MotionEvent event) {           int action = event.getAction();           switch (action) {           case MotionEvent.ACTION_DOWN:               v.getParent().requestDisallowInterceptTouchEvent(true);               break;           case MotionEvent.ACTION_UP:               v.getParent().requestDisallowInterceptTouchEvent(false);                break;           }           v.onTouchEvent(event);           return true;        }});


作为父控件的ScrollView重写了onInterceptTouchEvent方法,在其静止状态时是不拦截Action_Down事件的,此时在ListView所处区域触碰屏幕产生的Action_Down事件会顺利的传递给ListViewonDispatchTouchEvent,而ListView虽然是一个ViewGroup,但是使用的时候不会往里面放子视图,而是通过适配器来加载条目,所以ListViewAction_Down事件不会被子视图消费走,最终会回到ViewonDispatchTouchEvent,此时如果ListView上绑定了OnTouchListener,就会触发OnTouchListener里面的onTouch方法,并且如果onTouch方法返回true,就不会去执行ListViewonTouchEvent。所以,我们在onTouch里面要做三件事情:

1) 不允许作为父控件的ScrollView拦截任何事件

2) 手动调用自己的onTouchEvent方法。ListView重写了onTouchEvent方法,里面有大量自己的逻辑

3) 返回true

这样一来,所有的Action_Down后续事件都会经ScrollViewonDispatchToucEvent方法传递到ListViewOnTouchListener中来。只到收到了Action_Up事件,这意味着一次完整事件的结束,因此在遇到Action_Up事件时,要恢复ScrollView的拦截能力。

    这里还有一个额外的问题,就是ListViewScrollView中显示的高度,只有一行。如果需要调整,可以写一个工具方法:

public static voidsetListViewHeightBasedOnChildren(ListView listView) {   ListAdapter listAdapter = listView.getAdapter();    if(listAdapter == null)       return;int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.UNSPECIFIED);    inttotalHeight = 0;    Viewview = null;    for(int i = 0; i < listAdapter.getCount(); i++) {       view = listAdapter.getView(i, view, listView);       if (i == 0)            view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LayoutParams.WRAP_CONTENT));       view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);       totalHeight += view.getMeasuredHeight();    }   ViewGroup.LayoutParams params = listView.getLayoutParams();   params.height = totalHeight + (listView.getDividerHeight() *(listAdapter.getCount() - 1));   listView.setLayoutParams(params);   listView.requestLayout();}


方法的作用就是将ListView的高度设定为可以一次性的将adapter中的所有条目都展示出来,通过设定LayoutParams来“覆盖”父控件原先分配的内容,设定自己希望的宽度和高度,设定完毕后申请一次重新布局。但是这样做完之后, ListView已经不用滚动机制了,因为它所有的内容都显示出来了,这样的ListView就好像一个“LinearLayout”,这么做实际上是摒弃了ListView的性能优点的。所以可以折中一下,为ListView提供一个指定的高度。

public static voidsetListViewHeightBasedOnChildren(ListView listView,int listviewHeight) {              ListAdapterlistAdapter = listView.getAdapter();              if(listAdapter == null)                     return;              ViewGroup.LayoutParamsparams = listView.getLayoutParams();              params.height= listviewHeight;              listView.setLayoutParams(params);              listView.requestLayout();}


通过该方法,可以将ListView的高度设置为我们指定的高度,比如屏幕高度的1/3

setListViewHeightBasedOnChildren(lv,getResources().getDisplayMetrics().heightPixels/3);


完整的MainActivity代码如下:

public class MainActivity extends Activity {       privateListView lv;       publicString[] strs ={"星期一","星期二","星期三","星期四","星期五","星期六","星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};       publicstatic void setListViewHeightBasedOnChildren(ListView listView) {              ListAdapterlistAdapter = listView.getAdapter();              if(listAdapter == null)                     return;               intdesiredWidth = MeasureSpec.makeMeasureSpec(                            listView.getWidth(),MeasureSpec.UNSPECIFIED);              inttotalHeight = 0;              Viewview = null;              for(int i = 0; i < listAdapter.getCount(); i++) {                     view= listAdapter.getView(i, view, listView);                     if(i == 0)                            view.setLayoutParams(newViewGroup.LayoutParams(                                          desiredWidth,LayoutParams.WRAP_CONTENT));                     view.measure(desiredWidth,MeasureSpec.UNSPECIFIED);                     totalHeight+= view.getMeasuredHeight();              }              ViewGroup.LayoutParamsparams = listView.getLayoutParams();              params.height= totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));              listView.setLayoutParams(params);              listView.requestLayout();       }       publicstatic void setListViewHeightBasedOnChildren(ListView listView,int listviewHeight){              ListAdapterlistAdapter = listView.getAdapter();              if(listAdapter == null)                     return;              ViewGroup.LayoutParamsparams = listView.getLayoutParams();              params.height= listviewHeight;              listView.setLayoutParams(params);              listView.requestLayout();       }        @Override       protectedvoid onCreate(Bundle savedInstanceState) {              super.onCreate(savedInstanceState);              setContentView(R.layout.activity_main);              lv= (ListView) findViewById(R.id.listview);              lv.setAdapter(newArrayAdapter<String>(this, android.R.layout.simple_list_item_1,strs));              lv.setOnTouchListener(newOnTouchListener() {                      @Override                     publicboolean onTouch(View v, MotionEvent event) {                            intaction = event.getAction();                            switch(action) {                            caseMotionEvent.ACTION_DOWN:                                   v.getParent().requestDisallowInterceptTouchEvent(true);                                   break;                            caseMotionEvent.ACTION_UP:                                   v.getParent().requestDisallowInterceptTouchEvent(false);                                   break;                            }                            v.onTouchEvent(event);                             returntrue;                     }              });              setListViewHeightBasedOnChildren(lv,getResources().getDisplayMetrics().heightPixels/3);       }        @Override       publicboolean onCreateOptionsMenu(Menu menu) {              //Inflate the menu; this adds items to the action bar if it is present.              getMenuInflater().inflate(R.menu.main,menu);              returntrue;       } }


布局文件如下:

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="match_parent"   android:layout_height="match_parent" >    <ScrollView       android:id="@+id/scrollview"       android:layout_width="match_parent"       android:layout_height="match_parent" >        <LinearLayout           android:layout_width="match_parent"           android:layout_height="wrap_content"           android:orientation="vertical" >            <TextView               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:text="XXXXXXXXXXXXXXXXXXXXXXXX" />            <TextView               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:text="XXXXXXXXXXXXXXXXXXXXXXXX" />            <TextView               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:text="XXXXXXXXXXXXXXXXXXXXXXXX" />            <ListView               android:id="@+id/listview"               android:layout_width="match_parent"               android:layout_height="wrap_content" >           </ListView>            <TextView               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:text="XXXXXXXXXXXXXXXXXXXXXXXX" />            <TextView               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:text="XXXXXXXXXXXXXXXXXXXXXXXX" />             <TextView               android:layout_width="match_parent"               android:layout_height="wrap_content"               android:text="XXXXXXXXXXXXXXXXXXXXXXXX" />       </LinearLayout>   </ScrollView> </RelativeLayout>


1 0
原创粉丝点击