From a96567f03e1295d0c234f2767a301b81da12966f Mon Sep 17 00:00:00 2001 From: Vincent TE Date: Wed, 5 Mar 2025 16:17:22 +0100 Subject: [PATCH] fix: Allow parents view to intercept or not touch depending on the right conditions --- .../lib/pdfview/AnimationManager.java | 16 ++++++++-- .../lib/pdfview/DragPinchManager.java | 8 +++-- .../com/infomaniak/lib/pdfview/PDFView.java | 21 +++++++----- .../lib/pdfview/util/TouchUtils.java | 32 ++++++++++++++++--- .../lib/pdfpreview/sample/PDFViewActivity.kt | 2 +- 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/AnimationManager.java b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/AnimationManager.java index 03f92ce9..1beba151 100644 --- a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/AnimationManager.java +++ b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/AnimationManager.java @@ -106,8 +106,10 @@ public void startPageFlingAnimation(float targetOffset) { void computeFling() { if (scroller.computeScrollOffset()) { - pdfView.moveTo(scroller.getCurrX(), scroller.getCurrY()); - pdfView.loadPageByOffset(); + if (shouldHandleScrollerValue()) { + pdfView.moveTo(scroller.getCurrX(), scroller.getCurrY()); + pdfView.loadPageByOffset(); + } } else if (flinging) { // fling finished flinging = false; pdfView.loadPages(); @@ -116,6 +118,16 @@ void computeFling() { } } + private boolean shouldHandleScrollerValue() { + // Sometimes, when we reach the end of the PDF and we perform a scroll, the scroller sometimes return 0 when we + // release the touch. + if (pdfView.isSwipeVertical()) { + return scroller.getCurrY() != 0 && scroller.getCurrY() != pdfView.getDocumentLength(); + } else { + return scroller.getCurrX() != 0; + } + } + public void stopAll() { if (animation != null) { animation.cancel(); diff --git a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/DragPinchManager.java b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/DragPinchManager.java index 309c4bd6..98dcf319 100644 --- a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/DragPinchManager.java +++ b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/DragPinchManager.java @@ -368,8 +368,12 @@ private boolean shouldOverrideTouchPriority(View v, MotionEvent event) { (!canScrollRight && scrollDirection == DIRECTION_SCROLLING_LEFT) || (!canScrollLeft && scrollDirection == DIRECTION_SCROLLING_RIGHT); - if (event.getAction() == MotionEvent.ACTION_MOVE && canScrollHorizontally) { - startingTouchXPosition = STARTING_TOUCH_POSITION_NOT_INITIALIZED; + if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (canScrollHorizontally) { + startingTouchXPosition = STARTING_TOUCH_POSITION_NOT_INITIALIZED; + } else if (startingTouchXPosition == STARTING_TOUCH_POSITION_NOT_INITIALIZED) { + startingTouchXPosition = event.getX(); + } } if (!isScrollingBlocked || startingTouchXPosition == STARTING_TOUCH_POSITION_NOT_INITIALIZED) { diff --git a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/PDFView.java b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/PDFView.java index 2aaf5585..838faf3d 100644 --- a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/PDFView.java +++ b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/PDFView.java @@ -383,7 +383,7 @@ public void jumpTo(int page, boolean withAnimation) { } page = pdfFile.determineValidPageNumberFrom(page); - float offset = -pdfFile.getPageOffset(page, zoom) + pageSeparatorSpacing; + float offset = -pdfFile.getPageOffset(page, zoom) + pageSeparatorSpacing + startSpacing; if (swipeVertical) { if (withAnimation) { animationManager.startYAnimation(currentYOffset, offset); @@ -719,14 +719,11 @@ protected void onDraw(Canvas canvas) { } // Moves the canvas before drawing any element - float currentXOffset = this.currentXOffset; - float currentYOffset = this.currentYOffset; canvas.translate(currentXOffset, currentYOffset); // Draws thumbnails for (PagePart part : cacheManager.getThumbnails()) { drawPart(canvas, part); - } // Draws parts @@ -970,11 +967,11 @@ public void moveTo(float offsetX, float offsetY, boolean moveHandle) { if (contentHeight < getHeight()) { // whole document height visible on screen offsetY = (getHeight() - contentHeight) / 2; } else { - float maxOffsetY = toCurrentScale((verticalBorder * 2f) - startSpacing); + float maxOffsetY = toCurrentScale((verticalBorder * 2f) + startSpacing); if (offsetY > maxOffsetY) { // top visible offsetY = maxOffsetY; - } else if (offsetY + contentHeight + toCurrentScale((verticalBorder * 2f)) < getHeight() + toCurrentScale(endSpacing)) { // bottom visible - offsetY = -contentHeight + getHeight() + toCurrentScale(endSpacing - (verticalBorder * 2f)); + } else if (offsetY < getMinOffsetY()) { // bottom visible + offsetY = getMinOffsetY(); } } @@ -1006,7 +1003,7 @@ public void moveTo(float offsetX, float offsetY, boolean moveHandle) { float maxOffsetX = toCurrentScale((horizontalBorder * 2f) - startSpacing); if (offsetX > maxOffsetX) { // left visible offsetX = maxOffsetX; - } else if (offsetX + contentWidth + toCurrentScale((horizontalBorder * 2f)) < getWidth() + toCurrentScale(endSpacing)) { // right visible + } else if (offsetX + contentWidth + toCurrentScale((horizontalBorder * 2f)) < getWidth() + toCurrentScale(endSpacing)) { // right visible offsetX = -contentWidth + getWidth() + toCurrentScale(endSpacing - (horizontalBorder * 2f)); } } @@ -1056,6 +1053,14 @@ void loadPageByOffset() { } } + private float getMinOffsetY() { + return getHeight() - toCurrentScale(endSpacing) - toCurrentScale(verticalBorder * 2f) - pdfFile.getDocLen(zoom); + } + + public int getDocumentLength() { + return (int) (getHeight() - pdfFile.getDocLen(zoom)); + } + /** * Animate to the nearest snapping position for the current SnapPolicy */ diff --git a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/util/TouchUtils.java b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/util/TouchUtils.java index f873dc4f..2a5f1069 100644 --- a/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/util/TouchUtils.java +++ b/android-pdf-viewer/src/main/java/com/infomaniak/lib/pdfview/util/TouchUtils.java @@ -5,6 +5,9 @@ import android.view.ViewParent; import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager2.widget.ViewPager2; + +import com.infomaniak.lib.pdfview.PDFView; public class TouchUtils { @@ -17,11 +20,13 @@ private TouchUtils() { throw new IllegalStateException("Utility class"); } - public static void handleTouchPriority(MotionEvent event, - View view, - int pointerCount, - boolean shouldOverrideTouchPriority, - boolean isZooming) { + public static void handleTouchPriority( + MotionEvent event, + View view, + int pointerCount, + boolean shouldOverrideTouchPriority, + boolean isZooming + ) { ViewParent viewToDisableTouch = getViewToDisableTouch(view); if (viewToDisableTouch == null) { @@ -34,6 +39,11 @@ public static void handleTouchPriority(MotionEvent event, view.canScrollVertically(DIRECTION_SCROLLING_TOP) && view.canScrollVertically(DIRECTION_SCROLLING_BOTTOM); if (shouldOverrideTouchPriority) { viewToDisableTouch.requestDisallowInterceptTouchEvent(false); + + ViewParent viewPager = getViewPager(view); + if (viewPager != null) { + viewPager.requestDisallowInterceptTouchEvent(true); + } } else if (event.getPointerCount() >= pointerCount || canScrollHorizontally || canScrollVertically) { int action = event.getAction(); @@ -47,9 +57,21 @@ public static void handleTouchPriority(MotionEvent event, private static ViewParent getViewToDisableTouch(View startingView) { ViewParent parentView = startingView.getParent(); + while (parentView != null && !(parentView instanceof RecyclerView)) { parentView = parentView.getParent(); } + + return parentView; + } + + private static ViewParent getViewPager(View startingView) { + ViewParent parentView = startingView.getParent(); + + while (parentView != null && !(parentView instanceof ViewPager2)) { + parentView = parentView.getParent(); + } + return parentView; } } diff --git a/sample/src/main/java/com/infomaniak/lib/pdfpreview/sample/PDFViewActivity.kt b/sample/src/main/java/com/infomaniak/lib/pdfpreview/sample/PDFViewActivity.kt index 72b722f5..33fc9b80 100644 --- a/sample/src/main/java/com/infomaniak/lib/pdfpreview/sample/PDFViewActivity.kt +++ b/sample/src/main/java/com/infomaniak/lib/pdfpreview/sample/PDFViewActivity.kt @@ -212,7 +212,7 @@ class PDFViewActivity : AppCompatActivity(), OnPageChangeListener, OnLoadComplet private const val HANDLE_PADDING_BOTTOM_DP = 40 private const val PDF_PAGE_SPACING_DP = 10 private const val DEFAULT_TEXT_SIZE_DP = 16 - private const val START_END_SPACING_DP = 200 + private const val START_END_SPACING_DP = 10 private const val MIN_ZOOM = 0.93f private const val MID_ZOOM = 3.0f private const val MAX_ZOOM = 6.0f