通过事件分发机制处理ListView与ScrollView滑动冲突
来源:互联网 发布:如何学编程 编辑:程序博客网 时间:2024/05/25 21:34
ListView与ScrollView滑动冲突处理,是一个很经典的案例,网络上有各种各样的解决方案,比如使用LinearLayout取代ListView、重写ListView的onMeasure方法都能很好的解决这个问题。
但是本次采用的是通过重写ListView的dispatchTouchEvent来处理滑动冲突,并以此加深对Android事件分发机制的理解。
在此之前先了解下面这三个方法:
1. dispatchTouchEvent(MotionEvent event)
如果事件传递给View那么此方法一定能够被调用,其返回结果表示是否消费当前的事件。
2. onIntercepteTouchEvent(MotionEvent event)
表示是否拦截当前事件,如果当前View拦截了某个事件,那么在同一事件序列当中,此方法不会再次被调用,其返回结果表示是否拦截
3. onTouchEvent(MotionEvent event)
在dispatchTouchEvent(MotionEvent event)方法中调用,用于处理点击事件,返回结果表示是否消费当前事件,如果不消费则在同一事件序列中,当前View无法再次接收到事件。
熟悉了这三个方法再说说最关键的内容了,就是如何重写dispatchTouchEvent(MotionEvent event),下面上代码:
View:
public class InsideInterceptListView extends ListView {private float lasty;public InsideInterceptListView(Context context) {super(context);}public InsideInterceptListView(Context context, AttributeSet attrs) {super(context, attrs);}public InsideInterceptListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {int action = ev.getAction();float y = ev.getY();switch (action) {case MotionEvent.ACTION_DOWN://此处必须让父View不拦截事件,否则后面的事件无法获取getParent().requestDisallowInterceptTouchEvent(true);break;case MotionEvent.ACTION_MOVE://获取ListView当前的第一个可见itemint frist = getFirstVisiblePosition();//获取ListView当前的最后一个可见itemint last = getLastVisiblePosition();//获取item总数int child = getCount();Log.i("child", "child: " + child);if (y > lasty && frist == 0) {//ListView的第一个可见View的position == 0 并且向下滑动时,请求父View拦截事件getParent().requestDisallowInterceptTouchEvent(false);} else if (y < lasty && last == child - 1) {//ListView的最后一个个可见View的position是最后一个item, 并且向上滑动时,请求父View拦截事件getParent().requestDisallowInterceptTouchEvent(false);} else {//其它情况,事件由本View消费getParent().requestDisallowInterceptTouchEvent(true);}break;case MotionEvent.ACTION_UP:getParent().requestDisallowInterceptTouchEvent(true);break;default:break;}lasty = y;return super.dispatchTouchEvent(ev);}}
View中主要是通过重写dispatchTouchEvent方法,在方法内根据当前滑动的方向和当前view的item数量去请求父类是否拦截事件。
public class InsideInterceptActivity extends Activity {private InsideInterceptListView lvTest;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_inside_intercept);initView();}/** * 初始化控件 */@SuppressLint("CommitTransaction")private void initView() {lvTest = (InsideInterceptListView) findViewById(R.id.test_lv);List<String> data = new ArrayList<String>();ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);for (int i = 0; i < 50; i++) {data.add("ITEM:" + i);}lvTest.setAdapter(adapter);}}
Activity里面没技术含量,基本的实现而已
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <ScrollView android:id="@+id/scrollView1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/titil_tv" android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <com.xuzhenhao.demo.views.InsideInterceptListView android:id="@+id/test_lv" android:layout_width="match_parent" android:layout_height="400dp" android:scrollbars="none"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> <TextView android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:text="标题:内部拦截" android:textSize="16sp" android:textColor="#6C080A"/> </LinearLayout> </ScrollView></RelativeLayout>
xml里面只是简单的布局。
下面看一看最终的效果!!
View的事件分发机制学习笔记
Android View 事件分发机制 源码解析 (上)
- 通过事件分发机制处理ListView与ScrollView滑动冲突
- 利用事件分发机制解决ScrollView嵌套ListView滑动冲突
- Scrollview嵌套listview利用事件分发机制解决滑动冲突
- Android事件分发机制与滑动冲突
- 事件分发机制与滑动冲突
- 从ListView的滑动删除了解事件分发机制与冲突
- Android事件分发机制以及滑动冲突处理
- Android事件分发机制及滑动冲突处理的几篇博文
- Android事件分发机制以及滑动冲突处理
- Android事件分发机制以及滑动冲突处理
- Android自定义View探索(三)—事件分发机制与滑动冲突处理
- ScrollView与ListView事件分发
- Android滑动冲突与事件分发机制浅析
- Android View的事件分发机制与滑动冲突解决方案
- 从ListView与ScrollView的冲突调查android view的事件处理机制
- 从ListView与ScrollView的冲突调查android view的事件处理机制
- ScrollView下,对ListView和GridView的分发处理和滑动冲突
- 【Android View事件分发机制】滑动冲突
- 一例登录验证导致的提供的防伪标记适用于其他基于声明的用户,而不适用于当前用户的问题
- Shell--数组
- js之发布 — 订阅模式
- sql 语句的转义
- 常用的实现多线程的两种方式(二)
- 通过事件分发机制处理ListView与ScrollView滑动冲突
- The requested list key 'deptList' could not be resolved as a collection/array/map/enumeration/iterat
- cocosPods的安装与使用
- shell--echo/printf
- JavaScript操作CSS样式实现简单的验证码的功能
- Ubuntu挂载硬盘没有执行权限的解决
- 搭建springMvc+spring+hibernate+maven开发环境003
- 排序算法之计数&基数排序
- Spring Bean装配之Autowired注解说明-2