我在垂直 RecyclerView 中有水平 recyclerView。 要水平滚动,我应该从 45 度滑动到 -45 度。从 90 度垂直滚动到 45 度。有没有可能覆盖这个?
例如,垂直滚动仅适用于从 105 度到 75 度的滑动。否则,水平滚动。
最佳答案
您需要像这样创建 MainVerticalRecyclerView
:
open class MainVerticalRecyclerView : RecyclerView {
private var scrollPointerId = -1
private var pointTouchX = 0
private var pointTouchY = 0
private var touchSlopType = 0
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
val vc = ViewConfiguration.get(context)
touchSlopType = vc.scaledTouchSlop
}
override fun setScrollingTouchSlop(slopConstant: Int) {
super.setScrollingTouchSlop(slopConstant)
val vc = ViewConfiguration.get(context)
when (slopConstant) {
TOUCH_SLOP_DEFAULT -> touchSlopType = vc.scaledTouchSlop
TOUCH_SLOP_PAGING -> touchSlopType = vc.scaledPagingTouchSlop
}
}
override fun onInterceptTouchEvent(e: MotionEvent?): Boolean {
if (e == null) {
return false
}
val action = e.actionMasked
val actionIndex = e.actionIndex
when (action) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
pointTouchX = Math.round(e.x + 0.5f)
pointTouchY = Math.round(e.y + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_POINTER_DOWN -> {
scrollPointerId = e.getPointerId(actionIndex)
pointTouchX = Math.round(e.getX(actionIndex) + 0.5f)
pointTouchY = Math.round(e.getY(actionIndex) + 0.5f)
return super.onInterceptTouchEvent(e)
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index < 0) {
return false
}
val x = Math.round(e.getX(index) + 0.5f)
val y = Math.round(e.getY(index) + 0.5f)
if (scrollState != SCROLL_STATE_DRAGGING) {
val dx = x - pointTouchX
val dy = y - pointTouchY
var startScroll = false
if (layoutManager?.canScrollHorizontally() == true && Math.abs(dx) > touchSlopType && (layoutManager?.canScrollVertically() == true || Math.abs(dx) > Math.abs(dy))) {
startScroll = true
}
if (layoutManager?.canScrollVertically() == true && Math.abs(dy) > touchSlopType && (layoutManager?.canScrollHorizontally() == true || Math.abs(dy) > Math.abs(dx))) {
startScroll = true
}
return startScroll && super.onInterceptTouchEvent(e)
}
return super.onInterceptTouchEvent(e)
}
else -> {
return super.onInterceptTouchEvent(e)
}
}
}
}
并在主 RecyclerView
中为其他嵌套的 RecyclerView
创建 ChildHorizontalRecyclerView
,如下所示:
class ChildHorizontalRecyclerView : MainVerticalRecyclerView {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
如果你想在触摸 HorizontalChildRecyclerView
时像在 PlayStore
中那样滚动,需要写:
recyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
if (e.action == MotionEvent.ACTION_DOWN && rv.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
rv.stopScroll()
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
})
关于Android嵌套RecyclerView改变滚动角度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53495948/