-
OnDragListener
通过 startDrag() 来启动拖拽
用 setOnDragListener() 来监听
OnDragListener 内部只有一个方法:onDrag()
onDragEvent() 方法也会收到拖拽回调(界面中的每个 View 都会收到)
-
ViewDragHelper
需要创建一个 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" />

-
OnDragListener的使用
只需要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.startDrag
和view.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
获得
-
ViewDragHelper的使用
需要重写三个方法
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)
没搞懂。。
网友评论