拖拽API

2020-05-14  本文已影响0人  王灵

通过 startDrag() 来启动拖拽
用 setOnDragListener() 来监听
OnDragListener 内部只有一个方法:onDrag()
onDragEvent() 方法也会收到拖拽回调(界面中的每个 View 都会收到)

需要创建一个 ViewDragHelper 和 Callback()
需要写在 ViewGroup 里面,重写 onIntercept() 和 onTouchevent()

MeasureSpec.getSize(widthMeasureSpec)//获取测量规范中定义的像素大小

具体的使用

基本的View实现

private const val COLUMNS = 2
private const val ROWS = 4

class OnDragListenerView(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {
    private val matthewDragListener = MatthewDragListener()

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var specW = MeasureSpec.getSize(widthMeasureSpec)
        var specH = MeasureSpec.getSize(heightMeasureSpec)
        measureChildren(
            MeasureSpec.makeMeasureSpec(specW / COLUMNS, MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(specH / ROWS, MeasureSpec.EXACTLY)
        )
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val cw = width / COLUMNS
        val ch = height / ROWS
        for ((index, child) in children.withIndex()) {
            child.layout(0, 0, cw, ch)
            child.translationX = (index % 2) * cw.toFloat()
            child.translationY = (index / 2) * ch.toFloat()
        }
    }  
}

然后在ViewPager里添加几个View,就会实现如下图效果

  <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/black7f000000"
        android:contentDescription="view1" />
截图1.png

只需要startDrag() 启动拖拽和OnDragListener 监听拖拽就行了

创建一个内部类实现OnDragListener,onDrag里有很多事件类型,取名很良心不必解释

inner class MatthewDragListener : OnDragListener {

        override fun onDrag(v: View, event: DragEvent): Boolean {
           //v 当事件触发时 触摸点所在的view
            //event.localState 正在被拖拽的view
            when (event.action) {
                DragEvent.ACTION_DRAG_STARTED -> {
                }
                DragEvent.ACTION_DRAG_ENTERED -> {
                }
                DragEvent.ACTION_DRAG_EXITED -> {
                }
                DragEvent.ACTION_DRAG_ENDED -> {
                }
                DragEvent.ACTION_DRAG_LOCATION -> {
                }
                DragEvent.ACTION_DROP -> {//
                    ToastUtils.showShort("DROP${event.clipData.getItemAt(0).text}")
                    show("ACTION_DROP")
                }
            }
            return true
        }
    }

重写onFinishInflate,在里面遍历子 view设置长按监听。
启动拖拽(view.startDragview.startDragAndDrop都可以;建议使用ViewCompat.startDragAndDrop
设置监听(view.setOnDragListener(matthewDragListener)

 override fun onFinishInflate() {
        super.onFinishInflate()
        children.forEach {
            it.setOnLongClickListener {
                //创建一个clipData信息,使用的是view的描述信息 通过在xml设置 android:contentDescription="view1"
                val clipData = ClipData.newPlainText("name", it.contentDescription)
//                it.startDrag(clipData, DragShadowBuilder(it), it, 0) 和下面的写法效果一样,但是下面的写的更好一些,有版本判断
                ViewCompat.startDragAndDrop(
                    it,//设置触发长按事件的view
                    clipData,//设置需要携带的数据  不需要可以null
                    DragShadowBuilder(it),//---不知道---
                    it,//在onDrag(v: View, event: DragEvent) 里可以通过event.localState获得这个view  可以null
                    0//---不知道---
                )
            }
            it.setOnDragListener(matthewDragListener)
        }
    }

需要注意的是ViewCompat.startDragAndDrop里的clipData只有在DragEvent.ACTION_DROP事件触发时才能通过event.clipData获得

需要重写三个方法

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        return viewDragHelper.shouldInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        viewDragHelper.processTouchEvent(event)
        return true
    }

    override fun computeScroll() {
       if (viewDragHelper.continueSettling(true)){
           ViewCompat.postInvalidateOnAnimation(this)
//           postInvalidateOnAnimation()
       }
    }

viewDragHelper对象创建

inner class DragCallback : ViewDragHelper.Callback() {

        override fun tryCaptureView(child: View, pointerId: Int): Boolean {
            TODO("Not yet implemented")
        }

    }
private val dragCallback = DragCallback()
    private val viewDragHelper = ViewDragHelper.create(this, dragCallback)

没搞懂。。

上一篇 下一篇

猜你喜欢

热点阅读