aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/views
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2019-07-01 11:54:38 -0700
committerAllan Wang <me@allanwang.ca>2019-07-01 11:54:38 -0700
commit92aad9bf4cd6ec5c1568420e9a2514bd4861438b (patch)
tree573562b0d4f8ef3621e0bb55e1ff46bfca20e5b4 /app/src/main/kotlin/com/pitchedapps/frost/views
parent79efcadf89f324f04f57d22c3b60a05fd297f2b9 (diff)
downloadfrost-92aad9bf4cd6ec5c1568420e9a2514bd4861438b.tar.gz
frost-92aad9bf4cd6ec5c1568420e9a2514bd4861438b.tar.bz2
frost-92aad9bf4cd6ec5c1568420e9a2514bd4861438b.zip
Disable refresh if not at the top, resolves #1450
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/views')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt78
1 files changed, 78 insertions, 0 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt
new file mode 100644
index 00000000..0ab11fc6
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/SwipeRefreshLayout.kt
@@ -0,0 +1,78 @@
+package com.pitchedapps.frost.views
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewConfiguration
+import android.webkit.WebView
+import android.widget.ListView
+import androidx.core.widget.ListViewCompat
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnChildScrollUpCallback
+import com.pitchedapps.frost.utils.L
+
+/**
+ * Variant that forbids refreshing if child layout is not at the top
+ * Inspired by https://github.com/slapperwan/gh4a/blob/master/app/src/main/java/com/gh4a/widget/SwipeRefreshLayout.java
+ *
+ */
+class SwipeRefreshLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+ SwipeRefreshLayout(context, attrs) {
+
+ private var preventRefresh: Boolean = false
+ private var downY: Float = -1f
+ private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
+
+ /**
+ * Copy of [canChildScrollUp], with additional support if necessary
+ */
+ private val canChildScrollUp = OnChildScrollUpCallback { parent, child ->
+ when (child) {
+ is WebView -> child.canScrollVertically(-1).apply {
+ L.d { "Webview can scroll up $this" }
+ }
+ is ListView -> ListViewCompat.canScrollList(child, -1)
+ // Supports webviews as well
+ else -> child?.canScrollVertically(-1) ?: false
+ }
+ }
+
+ init {
+ setOnChildScrollUpCallback(canChildScrollUp)
+ }
+
+ override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
+ if (ev.action != MotionEvent.ACTION_DOWN && preventRefresh) {
+ return false
+ }
+ when (ev.action) {
+ MotionEvent.ACTION_DOWN -> {
+ downY = ev.y
+ preventRefresh = canChildScrollUp()
+ }
+ MotionEvent.ACTION_MOVE -> {
+ if (downY - ev.y > touchSlop) {
+ preventRefresh = true
+ return false
+ }
+ }
+ }
+ return super.onInterceptTouchEvent(ev)
+ }
+
+ override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
+ if (preventRefresh) {
+ /*
+ * Ignoring offsetInWindow since
+ * 1. It doesn't seem to matter in the typical use case
+ * 2. It isn't being transferred to the underlying array used by the super class
+ */
+ dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null)
+ } else {
+ super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
+ }
+ }
+
+ interface OnRefreshListener : SwipeRefreshLayout.OnRefreshListener
+} \ No newline at end of file