Android的事件分发实例分析

来源:互联网 发布:python爬取百度文库 编辑:程序博客网 时间:2024/05/21 11:03

如果对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

0 0