美文网首页
SwipeRefreshLayout 嵌套ScrollView,

SwipeRefreshLayout 嵌套ScrollView,

作者: 雨打空城 | 来源:发表于2018-11-08 10:50 被阅读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)
    }
    

    相关文章

      网友评论

          本文标题:SwipeRefreshLayout 嵌套ScrollView,

          本文链接:https://www.haomeiwen.com/subject/htwixqtx.html