From ba3a37d33dfd8e1db3451f8c63844c373bce823e Mon Sep 17 00:00:00 2001 From: Marcos Holgado Date: Thu, 18 Feb 2021 12:55:40 +0000 Subject: [PATCH 1/2] Change swipe to refresh to only be triggered when a gesture begins --- .../app/browser/DuckDuckGoWebView.kt | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt b/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt index 5b9789d0efd0..d449d2962794 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/DuckDuckGoWebView.kt @@ -35,9 +35,11 @@ import androidx.core.view.ViewCompat * Originally based on https://github.com/takahirom/webview-in-coordinatorlayout for scrolling behaviour */ class DuckDuckGoWebView : WebView, NestedScrollingChild { - private var lastClampedTopY: Boolean = false + private var lastClampedTopY: Boolean = true // when created we are always at the top private var contentAllowsSwipeToRefresh: Boolean = true private var enableSwipeRefreshCallback: ((Boolean) -> Unit)? = null + private var hasGestureFinished = true + private var canSwipeToRefresh = true private var lastY: Int = 0 private var lastDeltaY: Int = 0 @@ -76,12 +78,15 @@ class DuckDuckGoWebView : WebView, NestedScrollingChild { event.offsetLocation(0f, nestedOffsetY.toFloat()) when (action) { + MotionEvent.ACTION_UP -> { + hasGestureFinished = true + returnValue = super.onTouchEvent(event) + stopNestedScroll() + } MotionEvent.ACTION_MOVE -> { var deltaY = lastY - eventY - if (deltaY > 0) { - lastClampedTopY = false - } + lastClampedTopY = deltaY <= 0 if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) { deltaY -= scrollConsumed[1] @@ -98,8 +103,8 @@ class DuckDuckGoWebView : WebView, NestedScrollingChild { lastY -= scrollOffset[1] } - if (scrollY == 0 && lastClampedTopY && nestedOffsetY == 0) { - // we have reached the top, are clamped vertically and nestedScrollY is done too -> enable swipeRefresh (by default always disabled) + if (canSwipeToRefresh && scrollY == 0 && lastClampedTopY && nestedOffsetY == 0) { + // we are on a new gesture, have reached the top, are clamped vertically and nestedScrollY is done too -> enable swipeRefresh (by default always disabled) enableSwipeRefresh(true) } @@ -107,6 +112,7 @@ class DuckDuckGoWebView : WebView, NestedScrollingChild { } MotionEvent.ACTION_DOWN -> { + hasGestureFinished = false // disable swipeRefresh until we can be sure it should be enabled enableSwipeRefresh(false) @@ -153,7 +159,16 @@ class DuckDuckGoWebView : WebView, NestedScrollingChild { override fun onOverScrolled(scrollX: Int, scrollY: Int, clampedX: Boolean, clampedY: Boolean) { // taking into account lastDeltaY since we are only interested whether we clamped at the top lastClampedTopY = clampedY && lastDeltaY <= 0 - enableSwipeRefresh(clampedY && scrollY == 0 && (lastDeltaY <= 0 || nestedOffsetY == 0)) + + if (!lastClampedTopY) { + canSwipeToRefresh = false // disable because user scrolled down so we need a new gesture + } + + if (lastClampedTopY && hasGestureFinished) { + canSwipeToRefresh = true // only enable if at the top and gestured finished + } + + enableSwipeRefresh(canSwipeToRefresh && clampedY && scrollY == 0 && (lastDeltaY <= 0 || nestedOffsetY == 0)) super.onOverScrolled(scrollX, scrollY, clampedX, clampedY) } From 680bd964fdd8d112f4ae57069ceea1f988b490f2 Mon Sep 17 00:00:00 2001 From: Marcos Holgado Date: Mon, 22 Feb 2021 08:47:16 +0000 Subject: [PATCH 2/2] Change distance to trigger swipe to refresh --- .../java/com/duckduckgo/app/browser/BrowserTabFragment.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index de701ebb767c..81ca8694398d 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -991,6 +991,9 @@ class BrowserTabFragment : } private fun configureSwipeRefresh() { + val metrics = resources.displayMetrics + val distanceToTrigger = (DEFAULT_CIRCLE_TARGET_TIMES_1_5 * metrics.density).toInt() + swipeRefreshContainer.setDistanceToTriggerSync(distanceToTrigger) swipeRefreshContainer.setColorSchemeColors(ContextCompat.getColor(requireContext(), R.color.cornflowerBlue)) swipeRefreshContainer.setOnRefreshListener { @@ -1396,6 +1399,8 @@ class BrowserTabFragment : private const val TRACKERS_INI_DELAY = 500L private const val TRACKERS_SECONDARY_DELAY = 200L + private const val DEFAULT_CIRCLE_TARGET_TIMES_1_5 = 96 + fun newInstance(tabId: String, query: String? = null, skipHome: Boolean): BrowserTabFragment { val fragment = BrowserTabFragment() val args = Bundle()