Android的事件分发实例分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/axi295309066/article/details/60139074

如果对Android的事件分发不熟悉,可以看Android的事件分发

瀑布流

实现的功能:滑动左边的RecyclerView区域,左边的RecyclerView滚动;滑动中间的RecyclerView上半部分区域,三个RecyclerView一起滚动(联动),滑动中间的RecyclerView下半部分区域,中间的RecyclerView滚动;滑动右边的RecyclerView区域,右边的RecyclerView滚动

布局文件

<?xml version="1.0" encoding="utf-8"?>
<com.github.waterfall.view.CustomLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:paddingLeft="2dp"
    android:paddingRight="2dp">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv3"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

</com.github.waterfall.view.CustomLinearLayout>

自定义CustomLinearLayout,实现touch事件分发

package com.github.waterfall.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

/**
 * ============================================================
 * Copyright:${TODO}有限公司版权所有 (c) 2017
 * Author:   AllenIverson
 * Email:    815712739@qq.com
 * GitHub:   https://github.com/JackChen1999
 * 博客:     http://blog.csdn.net/axi295309066
 * 微博:     AndroidDeveloper
 * <p>
 * Project_Name:WaterFall
 * Package_Name:com.github.waterfall.view
 * Version:1.0
 * time:2016/3/3 11:06
 * des :${TODO}
 * gitVersion:2.12.0.windows.1
 * updateAuthor:$Author$
 * updateDate:$Date$
 * updateDes:${TODO}
 * ============================================================
 */
public class CustomLinearLayout extends LinearLayout {

    public CustomLinearLayout(Context context) {
        super(context);
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int childCount = getChildCount();
        int width = getWidth() / childCount;
        int height = getHeight();

        float downX = event.getX();

        if (downX < width) {//滑动左边的RecyclerView
            event.setLocation(width / 2, event.getY());
            getChildAt(0).dispatchTouchEvent(event);
            return true;
        } else if (downX > width && downX < width * 2) {//滑动中间的RecyclerView
            float downY = event.getY();
            if (downY < height / 2) {
                event.setLocation(width / 2, event.getY());
                for (int i = 0; i < childCount; i++) {
                    View child = getChildAt(i);
                    try {
                        child.dispatchTouchEvent(event);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return true;
            } else if (downY > height / 2) {
                event.setLocation(width / 2, event.getY());
                try {
                    getChildAt(1).dispatchTouchEvent(event);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return true;
            }
        } else if (downX > width * 2) {//滑动右边的RecyclerView
            event.setLocation(width / 2, event.getY());
            getChildAt(2).dispatchTouchEvent(event);
            return true;
        }

        return true;
    }
}

重写onInterceptTouchEvent()方法,并返回true,拦截touch事件,在onTouchEvent()方法中,判断touch事件的区域,如果滑动的是左边的RecyclerView区域,调用getChildAt(0).dispatchTouchEvent(event)将touch事件分发给左边的RecyclerView;如果滑动的是右边的RecyclerView区域,将touch事件分发给右边的RecyclerView;如果滑动的是中间的RecyclerView上半部分区域,将touch事件分发给三个RecyclerView,从而实现三个RecyclerView的联动,如果滑动的是中间的RecyclerView下半部分区域,则将touch事件分发给中间的RecyclerView

InterceptorFrame

package com.mwqi.ui.widget;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import com.mwqi.ui.activity.BaseActivity;
import com.mwqi.utils.UIUtils;
import com.mwqi.utils.ViewUtils;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class InterceptorFrame extends FrameLayout {
    public static final int ORIENTATION_UP = 0x1;
    public static final int ORIENTATION_DOWN = 0x2;
    public static final int ORIENTATION_LEFT = 0x4;
    public static final int ORIENTATION_RIGHT = 0x8;
    public static final int ORIENTATION_ALL = 0x10;


    private List<View> mInterceptorViews;
    private Map<View, Integer> mViewAndOrientation;
    private int mTouchSlop;
    private float mLastX;
    private float mLastY;
    private View mTarget;

    public InterceptorFrame(Context context) {
        super(context);
        init();
    }

    private void init() {
        mInterceptorViews = new LinkedList<View>();
        mViewAndOrientation = new HashMap<View, Integer>();
        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
        mTouchSlop = configuration.getScaledTouchSlop();
    }

    public void addInterceptorView(final View v, final int orientation) {
        UIUtils.runInMainThread(new Runnable() {
            @Override
            public void run() {
                if (!mInterceptorViews.contains(v)) {
                    mInterceptorViews.add(v);
                    mViewAndOrientation.put(v, orientation);
                }
            }
        });
    }

    public void removeInterceptorView(final View v) {
        UIUtils.runInMainThread(new Runnable() {
            @Override
            public void run() {
                mInterceptorViews.remove(v);
                mViewAndOrientation.remove(v);
            }
        });
    }

    private View isTouchInterceptedView(MotionEvent event, int orientation) {
        for (View v : mInterceptorViews) {
            if (ViewUtils.isTouchInView(event, v) && (mViewAndOrientation.get(v) & orientation) == orientation && v.dispatchTouchEvent(event)) {
                return v;
            }
        }
        return null;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();

        if (mTarget != null) {
            boolean flag = mTarget.dispatchTouchEvent(ev);
            if (flag && (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP)) {
                mTarget = null;
            }
            return flag;
        }

        final float x = ev.getX();
        final float y = ev.getY();
        View view = null;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;
                view = isTouchInterceptedView(ev, ORIENTATION_ALL);
                break;
            case MotionEvent.ACTION_MOVE:
                final int xDiff = (int) Math.abs(x - mLastX);
                final int yDiff = (int) Math.abs(y - mLastY);
                if (xDiff > mTouchSlop && xDiff > yDiff) {
                    view = isTouchInterceptedView(ev, (x - mLastX > 0) ? ORIENTATION_RIGHT : ORIENTATION_LEFT);
                } else if (yDiff > mTouchSlop && yDiff > xDiff) {
                    view = isTouchInterceptedView(ev, (y - mLastY > 0) ? ORIENTATION_DOWN : ORIENTATION_UP);
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mTarget = null;
                break;
            default:
                break;
        }
        if (view != null) {
            mTarget = view;
            return true;
        } else {
            return super.dispatchTouchEvent(ev);
        }
    }
}

代码:http://download.csdn.net/detail/axi295309066/9769415

展开阅读全文

没有更多推荐了,返回首页