在双向 Recyclerview 中处理水平滚动时禁用 SwipeRefreshLayout
Disable SwipeRefreshLayout when horizintal scroll handled in two-way Recyclerview
我有一个带有自定义 LayoutManager 的 RecyclerView,它具有双向滚动逻辑。所以,我已经覆盖了它的方法:
override fun canScrollVertically(): Boolean = true
override fun canScrollHorizontally(): Boolean = true
然后我将 RecyclerView 放在自定义的 SwipeRefreshLayout 中,以防止用户水平滚动我的列表时发生 "swipe to refresh" 操作:
class CustomSwipeToRefresh
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null
) : SwipeRefreshLayout(context, attrs) {
private val touchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
private var startX = 0f
private var forbidSwipe = false
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
ACTION_DOWN -> startX = event.x
ACTION_MOVE -> {
if (abs(event.x - startX) > touchSlop || forbidSwipe) {
forbidSwipe = true
return false
}
}
ACTION_CANCEL, ACTION_UP -> {
forbidSwipe = false
}
}
return super.onInterceptTouchEvent(event)
}
}
但是这个解决方案不起作用。尝试了这个解决方案(手动禁用),但它也不起作用:
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
ACTION_DOWN -> startX = event.x
ACTION_MOVE -> {
if (abs(event.x - startX) > touchSlop || forbidSwipe) {
forbidSwipe = true
isEnabled = false
return false
}
}
ACTION_CANCEL, ACTION_UP -> {
isEnabled = true
forbidSwipe = false
}
}
return super.onInterceptTouchEvent(event)
}
无论如何,如果我写
refreshLayout.isEnabled = false
在我的 onViewCreated in Fragment 中,它被禁用了。
还尝试在 RecyclerView.OnScrollListener 中禁用 SwipeRefreshLayout,但没有帮助。
我的代码或 SwipeRefreshLayout 有什么问题?
好的。经过几天的谷歌搜索,我发现显示和移动微调器的所有魔法都位于 NestedScrollingParent 方法中。所以,我重写了 onNestedScroll 方法,如果 forbidSwipe == true
我只是忽略了超级方法:
class CustomSwipeToRefresh
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null
) : SwipeRefreshLayout(context, attrs) {
private val touchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
private var startX = 0f
private var startY = 0f
private var forbidSwipe = false
private var isStartScrolledByY = false
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
ACTION_DOWN -> {
startX = event.x
startY = event.y
}
ACTION_MOVE -> {
val isScrolledByX = abs(event.x - startX) > touchSlop
val isScrolledByY = abs(event.y - startY) > touchSlop
if (!forbidSwipe && isScrolledByY) {
isStartScrolledByY = true
}
if ((isScrolledByX || forbidSwipe) && !isStartScrolledByY) {
forbidSwipe = true
return false
}
}
ACTION_CANCEL, ACTION_UP -> {
forbidSwipe = false
isStartScrolledByY = false
}
}
return super.onInterceptTouchEvent(event)
}
override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
if (forbidSwipe) return
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
}
}
我有一个带有自定义 LayoutManager 的 RecyclerView,它具有双向滚动逻辑。所以,我已经覆盖了它的方法:
override fun canScrollVertically(): Boolean = true
override fun canScrollHorizontally(): Boolean = true
然后我将 RecyclerView 放在自定义的 SwipeRefreshLayout 中,以防止用户水平滚动我的列表时发生 "swipe to refresh" 操作:
class CustomSwipeToRefresh
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null
) : SwipeRefreshLayout(context, attrs) {
private val touchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
private var startX = 0f
private var forbidSwipe = false
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
ACTION_DOWN -> startX = event.x
ACTION_MOVE -> {
if (abs(event.x - startX) > touchSlop || forbidSwipe) {
forbidSwipe = true
return false
}
}
ACTION_CANCEL, ACTION_UP -> {
forbidSwipe = false
}
}
return super.onInterceptTouchEvent(event)
}
}
但是这个解决方案不起作用。尝试了这个解决方案(手动禁用),但它也不起作用:
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
ACTION_DOWN -> startX = event.x
ACTION_MOVE -> {
if (abs(event.x - startX) > touchSlop || forbidSwipe) {
forbidSwipe = true
isEnabled = false
return false
}
}
ACTION_CANCEL, ACTION_UP -> {
isEnabled = true
forbidSwipe = false
}
}
return super.onInterceptTouchEvent(event)
}
无论如何,如果我写
refreshLayout.isEnabled = false
在我的 onViewCreated in Fragment 中,它被禁用了。
还尝试在 RecyclerView.OnScrollListener 中禁用 SwipeRefreshLayout,但没有帮助。 我的代码或 SwipeRefreshLayout 有什么问题?
好的。经过几天的谷歌搜索,我发现显示和移动微调器的所有魔法都位于 NestedScrollingParent 方法中。所以,我重写了 onNestedScroll 方法,如果 forbidSwipe == true
我只是忽略了超级方法:
class CustomSwipeToRefresh
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null
) : SwipeRefreshLayout(context, attrs) {
private val touchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
private var startX = 0f
private var startY = 0f
private var forbidSwipe = false
private var isStartScrolledByY = false
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
ACTION_DOWN -> {
startX = event.x
startY = event.y
}
ACTION_MOVE -> {
val isScrolledByX = abs(event.x - startX) > touchSlop
val isScrolledByY = abs(event.y - startY) > touchSlop
if (!forbidSwipe && isScrolledByY) {
isStartScrolledByY = true
}
if ((isScrolledByX || forbidSwipe) && !isStartScrolledByY) {
forbidSwipe = true
return false
}
}
ACTION_CANCEL, ACTION_UP -> {
forbidSwipe = false
isStartScrolledByY = false
}
}
return super.onInterceptTouchEvent(event)
}
override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) {
if (forbidSwipe) return
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
}
}