完美解决ListView和ViewPager的滑动冲突

时间:2022-09-22 18:56:21

在网上找了一下关于ListView和ViewPager滑动冲突的问题发很多但都没有解决,也没有可运行的Demo运行。其中就包括http://www.apkbus.com/forum.phpmod=viewthread&tid=115131               

于是在网上找了一下事件的分发和拦截来学习。有兴趣的同学可以看看。写的比较详细   http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html

下面来贴一下我的代码,如果有需要的可以下载看看运行效果,当然代码我会全部贴出来。

首先来看一下布局文件。很简单就是一个listview的头部放入一个viewpager  ,viewpager里面有三个图片。

下面是ListView里面的布局文件。

  1. <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=".MainActivity" >
    
        <cn.zhongyun.listviewandviewpager.customview.MyListView
            android:id="@+id/listView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true" />
    
    </RelativeLayout>


   接下来是ViewPager的布局文件  需要注意的是ViewPager的高度要固定否则在ListView的头部会显示不出来。如果不固定的话,就要在代码里估量头部的大小然后再得到高度
  1. <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
    
        <android.support.v4.view.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
                  android:layout_height="150dp" />
    
    </LinearLayout>



  下面来贴一下核心代码,也就是重写ListView的拦截事件处理
  1. public class MyListView extends ListView {
            // 滑动距离及坐标
            private float xDistance, yDistance, xLast, yLast;
            public MyListView(Context context, AttributeSet attrs, int defStyle) {
                    super(context, attrs, defStyle);
            }
    
            public MyListView(Context context, AttributeSet attrs) {
                    super(context, attrs);
            }
    
            public MyListView(Context context) {
                    super(context);
            }
            
            @Override
            public boolean onInterceptTouchEvent(MotionEvent ev) {
                    switch (ev.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                            xDistance = yDistance = 0f;
                            xLast = ev.getX();
                            yLast = ev.getY();
                            break;
                    case MotionEvent.ACTION_MOVE:
                            final float curX = ev.getX();
                            final float curY = ev.getY();
    
                            xDistance += Math.abs(curX - xLast);
                            yDistance += Math.abs(curY - yLast);
                            xLast = curX;
                            yLast = curY;
    
                            if (xDistance > yDistance) {
                                    return false;   //表示向下传递事件
                            }
                    }
    
                    return super.onInterceptTouchEvent(ev);
            }
    }


    在onInterceptTouchEvent这个方法里拦截。如果在x轴上的距离大于y轴上的距离表示是ViewPager的滑动,所以滑动处理交给ViewPager的OnTouchEvent来处理,ListView不处理。(代码里返回return false)
     反之 return  super.onInterceptTouchEvent(ev); 表示交给当前view(也就是ListView的触摸事件处理)。当然如果你不理解可以看看上面我发的那个链接可以看看。这样就解决了滑动冲突的问题。