我的例子继承ConstraintLayout,把要拖动的view在xml中 tag设置为float,其他的view按正常的ConstraintLayout用法使用即可,互不影响,多个也可tag设为float
原理:基于ViewDragHelper,view的拖拽按正常处理,抬手时判断位置决定贴边可参考鸿洋的教程
/**
* Created by 不听话的好孩子 on 2018/1/26.
* 子viewTag为float会被抓住
*/
class FloatLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
var MOVE_FLAT = "float"
var sticky = true
private var viewDragHelper: ViewDragHelper? = null
val callback = object : ViewDragHelper.Callback() {
override fun tryCaptureView(child: View?, pointerId: Int)= MOVE_FLAT == child?.tag
//限制view上下边界
override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
var verticalscroll = 0
if (top > height - child.height) {
verticalscroll = height - child.height
} else {
if (top > 0)
verticalscroll = top
}
return verticalscroll
}
//限制view左右边界
override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
var horizontalScroll = 0
if (left > width - child.width) {
horizontalScroll = width - child.width
} else {
if (left > 0)
horizontalScroll = left
}
return horizontalScroll
}
override fun getViewVerticalDragRange(child: View): Int {
return height - child.height
}
override fun getViewHorizontalDragRange(child: View): Int {
return width - child.width
}
//放手时贴边
override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
if (sticky) {
if (releasedChild.left + releasedChild.width / 2 > width / 2) {
viewDragHelper?.settleCapturedViewAt(width - releasedChild.width, releasedChild.top)
} else {
viewDragHelper?.settleCapturedViewAt(0, releasedChild.top)
}
invalidate()
}
}
}
override fun computeScroll() {
if (viewDragHelper!!.continueSettling(true)) {
invalidate()
}
}
init {
viewDragHelper = ViewDragHelper.create(this, 1f, callback)
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return viewDragHelper!!.shouldInterceptTouchEvent(ev)
}
//手指放下的地方在float子view上处理事件
override fun onTouchEvent(event: MotionEvent): Boolean {
viewDragHelper?.processTouchEvent(event)
return true
}
}