美文网首页高级UIview
「已解决」ItemTouchHelper 与刷新控件的滑动冲突

「已解决」ItemTouchHelper 与刷新控件的滑动冲突

作者: ZEKI安卓学弟 | 来源:发表于2019-11-26 14:03 被阅读0次

    前言
    在RecyclerView中使用ItemTouchHelper可以轻松实现列表交换顺序的效果,基本用法就不说了,大家百度Google一下满大街都是。对于仅仅是列表的情况,无论是实现上下滑动拖拽还是左右滑动拖拽,ItemTouchHelper都能轻松应对。 但是当我将RecyclerView放入RefreshLayout(第三方控件或者SwipeRefreshLayout)中时,就产生了滑动冲突,是因为刷新控件本身就会监听我们的RecyclerView的滑动并在下滑时添加刷新头,而我们的 ItemTouchHelper 也会监听 RecyclerView 的滑动,当我长按触发拖拽再继续下拉拖拽,刷新头就出现了,这就是在竖直方向的拖拽情况下,两者产生的冲突。

    解决

       要解决无非就是在拖拽开启时将刷新控件的 enabled 属性置为 false ,在拖拽结束时将enabled 再置为 true ,刚开始我并没有找到 ItemTouchHelper 的对应拖拽开启的方法,但是可以使用 onSelectedChanged + actionState 来解决我们的问题
    

    看看onSelectedChanged方法

    
    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
    
      super.onSelectedChanged(viewHolder, actionState)
    
    }
    
    

    其中actionState表示当前的状态,一共有三个值

    1. ACTION_STATE_IDLE 表示没有任何手势,此时selected对应的应当是null;

    2. ACTION_STATE_SWIPE 表示侧滑状态;

    3. ACTION_STATE_DRAG 表示拖动状态。

    在我们长按item开启了拖拽后,onSelectedChanged() 会被调用,在结束拖拽后,它也会被调用,那么我们只需要加上判断 actionState 是否处于 ACTION_STATE_DRAG 就能判断出是在刚触发拖拽还是已经结束拖拽,这部分代码是这样的

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
    
    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
        onSwipeStart()//自定义的开启拖拽时的回调方法(这里可以替换为 refreshLayout.enabled = false)
    }else {
    
    onSwiped()//自定义的拖拽结束时的回调方法(这里可以替换为refreshLayout.enabled = true)
    
    }
    super.onSelectedChanged(viewHolder, actionState)
    
    }
    

    这里我是为RecyclerView写了一个扩展方法,这样只需要直接使用‘recyClerView.attachItemSwipe’就轻松为RecyclerView添加了拖拽功能,当然这是 Kotlin语言才有的,使用Java的话就乖乖使用传参的方式吧,下面贴这个方法的完整代码

    const val ITEM_SWIPE_VERTICAL =0
    
    const val ITEM_SWIPE_HORIZENTAL =1
    
    const val ITEM_SWIPE_FREE =2
    
    fun RecyclerView.attachItemSwipe(decoration: Int, onSwipeStart: () -> Unit, onSwiped: () -> Unit) {
    
    //互换位置
    
      ItemTouchHelper(object : ItemTouchHelper.Callback() {
    
    override fun getMovementFlags(
    
    recyclerView: RecyclerView,
    
            viewHolder: RecyclerView.ViewHolder
    
    ): Int =when (decoration) {
    
    ITEM_SWIPE_VERTICAL -> makeMovementFlags(
    
    ItemTouchHelper.UP or ItemTouchHelper.DOWN,
    
                ItemTouchHelper.UP or ItemTouchHelper.DOWN
    
            )
    
    ITEM_SWIPE_HORIZENTAL -> makeMovementFlags(
    
    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT,
    
                ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
    
            )
    
    ITEM_SWIPE_FREE -> makeMovementFlags(
    
    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN,
    
                ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
    
            )
    
    else -> makeMovementFlags(
    
    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN,
    
                ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
    
            )
    
    }
    
    override fun isLongPressDragEnabled(): Boolean =true
    
          override fun onMoved(
    
    recyclerView: RecyclerView,
    
            viewHolder: RecyclerView.ViewHolder,
    
            fromPos: Int,
    
            target: RecyclerView.ViewHolder,
    
            toPos: Int,
    
            x: Int,
    
            y: Int
    
    ) {
    
    }
    
    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
    
    if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
    
    onSwipeStart()//自定义的开启拖拽时的回调方法(这里可以替换为 refreshLayout.enabled = false)
    
            }else {
    
    onSwiped()//自定义的拖拽结束时的回调方法(这里可以替换为 refreshLayout.enabled = true)
    
            }
    
    super.onSelectedChanged(viewHolder, actionState)
    
    }
    
    override fun onMove(
    
    recyclerView: RecyclerView,
    
            viewHolder: RecyclerView.ViewHolder,
    
            target: RecyclerView.ViewHolder
    
    ): Boolean {
    
    (adapter as MessageListAdapter).onItemMove(
    
    viewHolder.adapterPosition, target.adapterPosition
    
    )
    
    return true
    
    }
    
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
    
    })
    
    .attachToRecyclerView(this)
    
    }
    

    在Fragment(Activity)中:

    //添加拖拽互换位置功能
    
    recyclerViewLayout.attachItemSwipe(ITEM_SWIPE_VERTICAL, {
    
      //onSwipeStart 交换开始
    
      refreshLayout.isEnabled =false //刷新控件置为不可用
    
    }, {
    
      //onSwiped 交换完成
    
      refreshLayout.isEnabled =true //刷新控件置为可用
    
    })
    

    相关文章

      网友评论

        本文标题:「已解决」ItemTouchHelper 与刷新控件的滑动冲突

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