Android Nested RecyclerView更改滚动角度

时间:2018-11-27 08:59:32

标签: android android-recyclerview recycler-adapter

我在垂直RecyclerView中有水平RecyclerViews。 enter image description here要水平滚动,我应该从45度滑动到-45度。从90度垂直滚动到45度。有可能否决吗?

例如,垂直滚动仅适用于从105度到75度的滑动。否则,水平滚动。

1 个答案:

答案 0 :(得分:0)

您需要像这样创建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)
            }
        }
    }
}

并在主ChildHorizontalRecyclerView内为其他嵌套的RecyclerView创建RecyclerView,如下所示:

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) {}
}

如果您想在触摸PlayStore时像在HorizontalChildRecyclerView中一样滚动,请输入:

        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) {}
        })