在ScrollView中使用ListView
来源:互联网 发布:java什么意思 编辑:程序博客网 时间:2024/05/17 07:12
从原则上来说,不应该在一个可滚动的视图中再放置一个可滚动的视图,即滚动视图的嵌套。原因很简单,如果不加以限制,当移动事件发生时,触摸点处于有嵌套关系的多个滚动视图的交叠部分,安卓无法区分该事件应该由哪一个滚动视图消费。所以,如果不是必须,可以使用其它的一些替代方式。比如用LinearLayout取代ListView放在一个ScrollView中,或者将ScrollView作为一个独立的View充当ListView的header。
如果必须要进行嵌套,那么可以采用如下的方式:
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事件会顺利的传递给ListView的onDispatchTouchEvent,而ListView虽然是一个ViewGroup,但是使用的时候不会往里面放子视图,而是通过适配器来加载条目,所以ListView的Action_Down事件不会被子视图消费走,最终会回到View的onDispatchTouchEvent,此时如果ListView上绑定了OnTouchListener,就会触发OnTouchListener里面的onTouch方法,并且如果onTouch方法返回true,就不会去执行ListView的onTouchEvent。所以,我们在onTouch里面要做三件事情:
1) 不允许作为父控件的ScrollView拦截任何事件
2) 手动调用自己的onTouchEvent方法。ListView重写了onTouchEvent方法,里面有大量自己的逻辑
3) 返回true
这样一来,所有的Action_Down后续事件都会经ScrollView的onDispatchToucEvent方法传递到ListView的OnTouchListener中来。只到收到了Action_Up事件,这意味着一次完整事件的结束,因此在遇到Action_Up事件时,要恢复ScrollView的拦截能力。
这里还有一个额外的问题,就是ListView在ScrollView中显示的高度,只有一行。如果需要调整,可以写一个工具方法:
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>
- 在ScrollView中使用ListView
- 怎么在ScrollView中使用ListView
- 在ScrollView中使用GridView和ListView
- 在ScrollView中嵌套ListView
- 在ScrollView中嵌套ListView
- 在ScrollView中嵌套ListView
- 在ScrollView中嵌套ListView
- ListView在ScrollView中显示
- ListView在ScrollView中的使用
- Android中在ScrollView中显示ListView
- 在ScrollView中加入ListView时
- 如何在ScrollView中嵌套ListView
- 如何在ScrollView中嵌套ListView
- 总结:在ScrollView中嵌套ListView
- Android: 如何在ScrollView中嵌套ListView
- 总结:在ScrollView中嵌套ListView
- 总结:在ScrollView中嵌套ListView
- 总结:在ScrollView中嵌套ListView
- HDU1085(母函数)
- MongoDB一些常用操作
- MySQL主从复制之基于GTID及多线程
- 如此胆怯——致开口说英语
- 软件测试 BUG预防 关于web产品常见问题
- 在ScrollView中使用ListView
- 关于cuda的makefile
- C/C++语言中关于const用法的总结
- 如何在使用storyboard中使用tableViewController中的Prototype Cells 自定义cell
- pat1028List Sorting (25)
- TextAtlas设置Gray
- iOS动画加载图片
- 切割图片
- CSS动画学习