Android滑动冲突解决

Touch事件的冲突在Android开发中是非常常见的,有时为了实现较好的效果,必须解决Touch事件冲突的问题。

自定义一个ScrollBackLayout控件,该控件继承LinearLayout。要求该控件能随手指的下滑而下滑,松开手指时能自动弹回原处。这个功能实现起来是比较简单的。但是如果在该控件中添加一个ScrollView控件,这时就会出现Touch冲突的情况。具体解决如下:

自定义的ScrollBackLayout控件:

public class ScrollBackLayout extends LinearLayout
{
    private int mMove;
    private int yDown , yMove;
    private int i = 0;
    private boolean isIntercept;
    private MyScrollView scrollView;

    public ScrollBackLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        super.onLayout(changed, l, t, r, b);
        scrollView = (MyScrollView) getChildAt(0);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        int y = (int) event.getY();
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                yDown = y;
                break;
            case MotionEvent.ACTION_MOVE:
                yMove = y;
                if ((yMove - yDown) > 0)
                {
                    //计算每次滑动的距离和总距离,将每次滑动的距离作为layout()方法的参数并重新布局,达到滑动效果
                    mMove = yMove - yDown;
                    i += mMove;
                    layout(getLeft() , getTop() + mMove , getRight() , getBottom() + mMove);
                }
                break;
            case MotionEvent.ACTION_UP:
                //MotionEvent.Action_UP:将滑动的总距离作为layout()方法的参数,重新布局,达到布局回弹的效果
                layout(getLeft() , getTop() - i , getRight() , getBottom() - i);
                i = 0;
                break;
        }
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev)
    {
        int y = (int) ev.getY();
        switch (ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                yDown = y;
                isIntercept = false;
                break;
            case MotionEvent.ACTION_MOVE:
                yMove = y;
                if (yMove - yDown < 0)
                {
                    isIntercept = false;
                }
                else if (yMove - yDown > 0)
                {
                    isIntercept = true;
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return isIntercept;
    }
}

关键是重写onInterceptTouchEvent方法。下面自定义一个ScrollView,重写onTouchEvent方法:

public class MyScrollView extends ScrollView
{
    public MyScrollView(Context context)
    {
        this(context , null);
    }

    public MyScrollView(Context context, AttributeSet attrs)
    {
        this(context, attrs , 0);
    }

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev)
    {
        switch (ev.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                //禁止父View进行事件拦截
                getParent().requestDisallowInterceptTouchEvent(true);
                break;

            case MotionEvent.ACTION_MOVE:
                int scrollY = getScrollY();

                if (scrollY == 0)
                {
                    //允许父View进行事件拦截
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                else
                {
                    //禁止父View进行事件拦截
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                break;
        }

        return super.onTouchEvent(ev);
    }
}

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/ic_main_left_bg">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="170dp">

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/img_head"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_centerInParent="true"
            app:civ_border_color="#FFFFFF"
            app:civ_border_width="1dp"
            android:src="@mipmap/default_head"/>

    </RelativeLayout>

    <test.view.zhangtao.viewscrollbackdemo1.ScrollBackLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <test.view.zhangtao.viewscrollbackdemo1.MyScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <include layout="@layout/content_layout"/>

        </test.view.zhangtao.viewscrollbackdemo1.MyScrollView>

    </test.view.zhangtao.viewscrollbackdemo1.ScrollBackLayout>

</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="#66cdaa">

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/divider_color"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="70dp">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:src="@mipmap/ic_my_detail"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="60dp"
            android:text="@string/person_center"
            android:textSize="20sp"
            android:textColor="@android:color/white"/>

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:src="@mipmap/ic_main_next"/>

    </RelativeLayout>

</LinearLayout>

自定义ScrollView在DOWN这个Action时,必须调用:getParent().requestDisallowInterceptTouchEvent(true);要不然事件还是会冲突,至于为什么这样实现,强烈建议看一下事件分发的相关源码。

源码地址:https://github.com/z13538657403/ViewScrollBack

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值