通过事件分发机制处理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数量去请求父类是否拦截事件。


Activity
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里面只是简单的布局。


下面看一看最终的效果!!



通过这个效果主要是为了加深对Android事件分发机制的了解,想更深入了解可以查看下面这些博文,说不定会有意想不到的收获!

View的事件分发机制学习笔记

Android View 事件分发机制 源码解析 (上)

0 0
原创粉丝点击