From 7bdacf8fdebbf38ecdc797d2b67506e3eeffb5a6 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Wed, 15 Apr 2020 17:23:24 +0430 Subject: Modify NestedScrollableHost to suit our need Now manages nested child scrolling when the orientation isn't perpendicular --- .../antennapod/view/NestedScrollableHost.java | 66 ++++++++-------------- 1 file changed, 22 insertions(+), 44 deletions(-) (limited to 'app/src/main/java/de/danoeh') diff --git a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java index 2be49ada4..a4daa9109 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java +++ b/app/src/main/java/de/danoeh/antennapod/view/NestedScrollableHost.java @@ -14,6 +14,7 @@ * limitations under the License. * * Source: https://github.com/android/views-widgets-samples/blob/87e58d1/ViewPager2/app/src/main/java/androidx/viewpager2/integration/testapp/NestedScrollableHost.kt + * And modified for our need */ package de.danoeh.antennapod.view; @@ -23,6 +24,7 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.ViewParent; import android.widget.FrameLayout; import androidx.annotation.NonNull; @@ -30,6 +32,7 @@ import androidx.annotation.Nullable; import androidx.viewpager2.widget.ViewPager2; import static androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL; +import static androidx.viewpager2.widget.ViewPager2.ORIENTATION_VERTICAL; /** * Layout to wrap a scrollable component inside a ViewPager2. Provided as a solution to the problem @@ -37,7 +40,7 @@ import static androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL; * ViewPager2. The scrollable element needs to be the immediate and only child of this host layout. * *

This solution has limitations when using multiple levels of nested scrollable elements - * (e.g. a horizontal RecyclerView in a vertical RecyclerView in a horizontal ViewPager2).

+ * (e.g. a horizontal RecyclerView in a vertical RecyclerView in a horizontal ViewPager2). */ class NestedScrollableHost extends FrameLayout { @@ -63,47 +66,19 @@ class NestedScrollableHost extends FrameLayout { return v == null ? null : (ViewPager2) v; } - private View getChild() { - return getChildCount() > 0 ? getChildAt(0) : null; - } - - private boolean canChildScroll(int orientation, float delta) { - int direction = (int) -Math.copySign(1, delta); - View child = getChild(); - if (child == null) { - return false; - } - switch (orientation) { - case 0: - return child.canScrollHorizontally(direction); - case 1: - return child.canScrollVertically(direction); - default: - return false; - } - } - public boolean onInterceptTouchEvent(MotionEvent e) { - handleInterceptTouchEvent(e); - return super.onInterceptTouchEvent(e); - } - - private void handleInterceptTouchEvent(MotionEvent e) { ViewPager2 parentViewPager = getParentViewPager(); if (parentViewPager == null) { - return; + return super.onInterceptTouchEvent(e); } - int orientation = parentViewPager.getOrientation(); - // Early return if child can't scroll in same direction as parent - if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) { - return; - } + ViewParent parent = getParent(); + int orientation = parentViewPager.getOrientation(); if (e.getAction() == MotionEvent.ACTION_DOWN) { initialX = e.getX(); initialY = e.getY(); - getParent().requestDisallowInterceptTouchEvent(true); + parent.requestDisallowInterceptTouchEvent(true); } else if (e.getAction() == MotionEvent.ACTION_MOVE) { int dx = (int) (e.getX() - initialX); int dy = (int) (e.getY() - initialY); @@ -112,22 +87,25 @@ class NestedScrollableHost extends FrameLayout { // assuming ViewPager2 touch-slop is 2x touch-slop of child float scaledDx = Math.abs(dx) * (isVpHorizontal ? .5f : 1f); float scaledDy = Math.abs(dy) * (isVpHorizontal ? 1f : .5f); - if (scaledDx > touchSlop || scaledDy > touchSlop) { + int value = isVpHorizontal ? dy : dx; if (isVpHorizontal == (scaledDy > scaledDx)) { - // Gesture is perpendicular, allow all parents to intercept - getParent().requestDisallowInterceptTouchEvent(false); + // Gesture is perpendicular + orientation = orientation == ORIENTATION_VERTICAL + ? ORIENTATION_HORIZONTAL : ORIENTATION_VERTICAL; + value = isVpHorizontal ? dy : dx; + } + + int direction = (int) -Math.copySign(1, value); + View child = getChildAt(0); + if (orientation == ORIENTATION_HORIZONTAL) { + parent.requestDisallowInterceptTouchEvent(child.canScrollHorizontally(direction)); } else { - // Gesture is parallel, query child if movement in that direction is possible - if (canChildScroll(orientation, isVpHorizontal ? dx : dy)) { - // Child can scroll, disallow all parents to intercept - getParent().requestDisallowInterceptTouchEvent(true); - } else { - // Child cannot scroll, allow all parents to intercept - getParent().requestDisallowInterceptTouchEvent(false); - } + parent.requestDisallowInterceptTouchEvent(child.canScrollVertically(direction)); } } } + + return super.onInterceptTouchEvent(e); } } -- cgit v1.2.3