【发布时间】:2016-01-20 20:36:36
【问题描述】:
这似乎是 android 中相当常见的模式。我正在尝试创建类似于 Facebook 显示广告的方式:
您可以看到它们有一个外部垂直回收器视图和一个内部水平回收器视图作为外部垂直回收器视图适配器中的项目之一。
我遵循了 Google 的“管理 ViewGroup 中的触摸事件”指南 - http://developer.android.com/training/gestures/viewgroup.html,因为 Recyclerview 扩展了 ViewGroup,并且那里的代码与我想做的类似。
我对其进行了一些定制,以便它检测 Y 轴上的运动而不是 X 轴上的运动,并将其应用于外部垂直回收器视图。
/**
* Created by Simon on 10/11/2015.
*///This is the recyclerview that would allow all vertical scrolls
public class VerticallyScrollRecyclerView extends RecyclerView {
public VerticallyScrollRecyclerView(Context context) {
super(context);
}
public VerticallyScrollRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticallyScrollRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
ViewConfiguration vc = ViewConfiguration.get(this.getContext());
private int mTouchSlop = vc.getScaledTouchSlop();
private boolean mIsScrolling;
private float startY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
// Always handle the case of the touch gesture being complete.
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
// Release the scroll.
mIsScrolling = false;
startY = ev.getY();
return false; // Do not intercept touch event, let the child handle it
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (mIsScrolling) {
// We're currently scrolling, so yes, intercept the
// touch event!
return true;
}
// If the user has dragged her finger horizontally more than
// the touch slop, start the scroll
// left as an exercise for the reader
final float yDiff = calculateDistanceY(ev.getY());
Log.e("yDiff ", ""+yDiff);
// Touch slop should be calculated using ViewConfiguration
// constants.
if (yDiff > mTouchSlop) {
// Start scrolling!
Log.e("Scroll", "we are scrolling vertically");
mIsScrolling = true;
return true;
}
break;
}
}
return false;
}
private float calculateDistanceY(float endY) {
return startY - endY;
}
}
我的 xml 布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_recyclerview_holder">
<com.example.simon.customshapes.VerticallyScrollRecyclerView
android:id="@+id/main_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
当我尝试拖动内部水平recyclerview(希望touchevent被外部垂直recyclerview拦截)时,外部recyclerview根本不会垂直滚动。
这也给了我一个错误提示:
错误处理滚动;未找到 id -1 的指针索引。是否跳过了任何 MotionEvents?
有谁知道如何让它正常工作?
【问题讨论】:
-
为什么需要创建自定义
VerticallyScrollRecyclerView?你不能只使用水平的LinearLayoutManager吗? -
我在内部水平回收器视图中使用水平 LinearLayoutManager。外部recyclerview 使用的是垂直的LinearLayoutManager。这个问题基于实现触摸事件的正确代码,我需要 VerticallyScrollRecyclerView 因为我需要它来拦截所有移动触摸事件,以便它能够正确滚动。否则,内部和外部回收器视图之间将存在触摸冲突。
-
你能找到解决办法吗?
-
在这里试试这个解决方案:stackoverflow.com/questions/33456216/…
标签: android android-layout android-recyclerview touch-event motionevent