This seems to be a fairly common pattern in android. I'm trying to create something similar to how Facebook displays their adverts:
You can see that they have an outer vertical recyclerview with an inner horizontal recyclerview as one of the items in the outer vertical recyclerview's adapter.
I followed this guide from Google on "Managing Touch Events in a ViewGroup" - http://developer.android.com/training/gestures/viewgroup.html as Recyclerview extends ViewGroup and the code there is similar to what I want to do.
I have customized it a little bit so that it detects movements in Y axis instead of movements in X axis and applied it to the outer vertical recyclerview.
/**
* 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;
}
}
My xml layout:
<?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>
When I try to drag the inner horizontal recyclerview (hoping that the touchevent would be intercepted by the outer vertical recyclerview), the outer recyclerview does not scroll vertically at all.
It also gives me an error saying:
Error processing scroll; pointer index for id -1 not found. Did any MotionEvents get skipped?
Does anyone know how to get this working right?