diff options
author | Allan Wang <me@allanwang.ca> | 2019-07-01 11:54:38 -0700 |
---|---|---|
committer | Allan Wang <me@allanwang.ca> | 2019-07-01 11:54:38 -0700 |
commit | 92aad9bf4cd6ec5c1568420e9a2514bd4861438b (patch) | |
tree | 573562b0d4f8ef3621e0bb55e1ff46bfca20e5b4 | |
parent | 79efcadf89f324f04f57d22c3b60a05fd297f2b9 (diff) | |
download | frost-92aad9bf4cd6ec5c1568420e9a2514bd4861438b.tar.gz frost-92aad9bf4cd6ec5c1568420e9a2514bd4861438b.tar.bz2 frost-92aad9bf4cd6ec5c1568420e9a2514bd4861438b.zip |
Disable refresh if not at the top, resolves #1450
6 files changed, 89 insertions, 8 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt index ed207896..42a0f6bb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -87,6 +87,9 @@ class LoginActivity : BaseActivity() { toolbar(toolbar) } profileLoader = GlideApp.with(profile) + swipeRefresh.setOnChildScrollUpCallback { parent, child -> + web.canScrollVertically(-1) + } launch { for (refreshing in refreshChannel.uniqueOnly(this)) { if (refreshing) swipeRefresh.isEnabled = true 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 diff --git a/app/src/main/res/layout/activity_debug.xml b/app/src/main/res/layout/activity_debug.xml index 55553f42..c3818749 100644 --- a/app/src/main/res/layout/activity_debug.xml +++ b/app/src/main/res/layout/activity_debug.xml @@ -16,7 +16,7 @@ app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> - <androidx.swiperefreshlayout.widget.SwipeRefreshLayout + <com.pitchedapps.frost.views.SwipeRefreshLayout android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent" @@ -29,7 +29,7 @@ android:focusable="true" android:focusableInTouchMode="true" /> - </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> + </com.pitchedapps.frost.views.SwipeRefreshLayout> <include layout="@layout/view_main_fab" /> diff --git a/app/src/main/res/layout/login_webview.xml b/app/src/main/res/layout/login_webview.xml index 8816383a..48d48589 100644 --- a/app/src/main/res/layout/login_webview.xml +++ b/app/src/main/res/layout/login_webview.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" +<com.pitchedapps.frost.views.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -36,4 +36,4 @@ </RelativeLayout> -</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
\ No newline at end of file +</com.pitchedapps.frost.views.SwipeRefreshLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/view_content_base_recycler.xml b/app/src/main/res/layout/view_content_base_recycler.xml index 05b14215..ce33ce13 100644 --- a/app/src/main/res/layout/view_content_base_recycler.xml +++ b/app/src/main/res/layout/view_content_base_recycler.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - <androidx.swiperefreshlayout.widget.SwipeRefreshLayout + <com.pitchedapps.frost.views.SwipeRefreshLayout android:id="@id/content_refresh" android:layout_width="match_parent" android:layout_height="wrap_content"> @@ -19,7 +19,7 @@ android:focusableInTouchMode="true" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> + </com.pitchedapps.frost.views.SwipeRefreshLayout> <ProgressBar android:id="@id/content_progress" diff --git a/app/src/main/res/layout/view_content_base_web.xml b/app/src/main/res/layout/view_content_base_web.xml index 9360b9f3..641ce918 100644 --- a/app/src/main/res/layout/view_content_base_web.xml +++ b/app/src/main/res/layout/view_content_base_web.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - <androidx.swiperefreshlayout.widget.SwipeRefreshLayout + <com.pitchedapps.frost.views.SwipeRefreshLayout android:id="@id/content_refresh" android:layout_width="match_parent" android:layout_height="wrap_content"> @@ -19,7 +19,7 @@ android:focusableInTouchMode="true" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> + </com.pitchedapps.frost.views.SwipeRefreshLayout> <ProgressBar android:id="@id/content_progress" |