如果对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.youkuaiyun.com/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.youkuaiyun.com/detail/axi295309066/9769415