Nik Clayton 2023-01-13 19:51:09 +01:00 committed by GitHub
parent e5e076b0d3
commit d6e7905e01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 0 deletions

View file

@ -89,6 +89,7 @@ import com.keylesspalace.tusky.util.deleteStaleCachedMedia
import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.getDimension import com.keylesspalace.tusky.util.getDimension
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.reduceSwipeSensitivity
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.updateShortcut import com.keylesspalace.tusky.util.updateShortcut
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
@ -253,6 +254,8 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} }
} }
binding.viewPager.reduceSwipeSensitivity()
setupDrawer(savedInstanceState, addSearchButton = hideTopToolbar) setupDrawer(savedInstanceState, addSearchButton = hideTopToolbar)
/* Fetch user info while we're doing other things. This has to be done after setting up the /* Fetch user info while we're doing other things. This has to be done after setting up the

View file

@ -78,6 +78,7 @@ import com.keylesspalace.tusky.util.getDomain
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.loadAvatar import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.parseAsMastodonHtml import com.keylesspalace.tusky.util.parseAsMastodonHtml
import com.keylesspalace.tusky.util.reduceSwipeSensitivity
import com.keylesspalace.tusky.util.setClickableText import com.keylesspalace.tusky.util.setClickableText
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
@ -235,6 +236,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
// Setup the tabs and timeline pager. // Setup the tabs and timeline pager.
adapter = AccountPagerAdapter(this, viewModel.accountId) adapter = AccountPagerAdapter(this, viewModel.accountId)
binding.accountFragmentViewPager.reduceSwipeSensitivity()
binding.accountFragmentViewPager.adapter = adapter binding.accountFragmentViewPager.adapter = adapter
binding.accountFragmentViewPager.offscreenPageLimit = 2 binding.accountFragmentViewPager.offscreenPageLimit = 2

View file

@ -30,6 +30,7 @@ import com.keylesspalace.tusky.components.search.adapter.SearchPagerAdapter
import com.keylesspalace.tusky.databinding.ActivitySearchBinding import com.keylesspalace.tusky.databinding.ActivitySearchBinding
import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.reduceSwipeSensitivity
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
@ -62,6 +63,7 @@ class SearchActivity : BottomSheetActivity(), HasAndroidInjector {
} }
private fun setupPages() { private fun setupPages() {
binding.pages.reduceSwipeSensitivity()
binding.pages.adapter = SearchPagerAdapter(this) binding.pages.adapter = SearchPagerAdapter(this)
val enableSwipeForTabs = preferences.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true) val enableSwipeForTabs = preferences.getBoolean(PrefKeys.ENABLE_SWIPE_FOR_TABS, true)

View file

@ -18,8 +18,11 @@ package com.keylesspalace.tusky.util
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
fun View.show() { fun View.show() {
this.visibility = View.VISIBLE this.visibility = View.VISIBLE
@ -63,3 +66,37 @@ inline fun EditText.afterTextChanged(
} }
}) })
} }
/**
* Reduce ViewPager2's sensitivity to horizontal swipes.
*/
fun ViewPager2.reduceSwipeSensitivity() {
// ViewPager2 is very sensitive to horizontal motion when swiping vertically, and will
// trigger a page transition if the user's swipe is only a few tens of degrees off from
// vertical. This is a problem if the underlying content is a list that the user wants
// to scroll vertically -- it's far too easy to trigger an accidental horizontal swipe.
//
// One way to stop this is to reach in to ViewPager2's RecyclerView and adjust the amount
// of touch slop it has. Scaling by 2 appears to work well.
//
// See https://issuetracker.google.com/issues/139867645 and
// https://bladecoder.medium.com/fixing-recyclerview-nested-scrolling-in-opposite-direction-f587be5c1a04
// for more (the approach in that Medium article works, but is still quite sensitive to
// horizontal movement while scrolling).
try {
val recyclerViewField = ViewPager2::class.java.getDeclaredField("mRecyclerView")
recyclerViewField.isAccessible = true
val recyclerView = recyclerViewField.get(this) as RecyclerView
val touchSlopField = RecyclerView::class.java.getDeclaredField("mTouchSlop")
touchSlopField.isAccessible = true
val touchSlop = touchSlopField.get(recyclerView) as Int
// 4 seems to be a sweet-spot. 2-3 still causes a horizontal swipe right if the user drags
// down-left at ~ 45 degree angle. Experimentally, 4 requires the swipe to be +/- ~ 10 degrees
// from horizontal to register as a horizontal and not a vertical swipe.
val scaleFactor = 4
touchSlopField.set(recyclerView, touchSlop * scaleFactor)
} catch (e: Exception) {
Log.w("reduceSwipeSensitivity", e)
}
}