SwipeRefreshLayout 嵌套ScrollView,

2018-11-08  本文已影响476人  雨打空城

在实际app项目开发中,往往会遇到SwipeRefreshLayout嵌套ScrollView,ScrollView嵌套RecyclerView的情况,虽然官方文档上强烈建议了:ScrollView不要嵌套RecyclerView,ListView

Never add a RecyclerView or ListView to a scroll view. Doing so results in poor user interface performance and a poor user experience.

滑动.gif

那我们就解决嵌套之后出现的问题。

问题一:SwipeRefreshLayoutScrollView滑动冲突

SwipeRefreshLayout负责的是下拉刷新,ScrollView负责页面的上下滑动,可以根据具体的业务需求来解决滑动冲突。

(1)如果ScrollView高度没有全屏,可以通过触碰的焦点是否在该ScrollView上来设置

swipeRefreshLayout.isEnable = isFocus

(2)如果是全屏,ScrollView有一个监听滑动的方法

void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);

通过scrollY的滑动的位置来设置即可:

scrollView.setOnScrollChangeListener { _, _, _, _, _ ->
    swipeRefreshLayout.isEnabled = (scrollView.scrollY <= 0)
}

问题二:ScrollView与RecyclerView滑动冲突

官方强烈建议二者不要嵌套,因为嵌套之后,ScrollView会失去惯性滑动,造成页面卡顿。一个简单的办法就是关闭RecyclerView的滑动。

class VerticalScrollLinearLayoutManager : LinearLayoutManager {
    private var mIsScroll = false

    constructor(context:Context):super(context)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int)   : super(context, attrs, defStyleAttr, defStyleRes)

    fun setScrollEnabled(isScroll: Boolean) {
        mIsScroll = isScroll
    }

    override fun canScrollVertically(): Boolean {
        return mIsScroll && super.canScrollVertically()
    }
}

通过对RecyclerViewLayoutManager来控制是否可以滑动,如果单纯的关闭RecyclerView的滑动就会造成RecyclerView无法上拉加载更多,所以当ScrollView滑到底端时并且滑动手势向上时,要开启RecyclerView的滑动。即setScrollEnable(true)

判断ScrollView滑到底端的方法:

scrollView.getChildAt(0).height - scrollView.height == scrollView.scrollY

所以整个逻辑就是

 when (event.action) {
     MotionEvent.ACTION_DOWN -> {
        if (ScreenUtil.isViewFocus(event, commentView)) {
             lastY = event.rawY.toInt()
             curY = event.rawY.toInt()
        } else {
              lastY = -1
              curY = -1
        }
     }

    MotionEvent.ACTION_MOVE -> {
        if (ScreenUtil.isViewFocus(event, commentView)) {
            curY = event.rawY.toInt()
            if (lastY - curY > ViewConfiguration.get(context).scaledTouchSlop) {
                isScrollUp = true
            }
        } else {
            isScrollUp = false
            curY = -1
            lastY = -1
        }
    }

    MotionEvent.ACTION_UP -> {
        isScrollUp = false
        lastY = -1
        curY = -1
    }
 }
 // 当滑倒最底端时且仍往上
 if (commentTitle.visibility == View.VISIBLE
    && isScrollUp
    && scrollView.getChildAt(0).height - scrollView.height == scrollView.scrollY) {
    recyclerView.setScrollEnable(true)
} else {
    recyclerView.setScrollEnable(false)
}
上一篇下一篇

猜你喜欢

热点阅读