1.使用View.layout()方法
class CustomView : View {
var downX = 0f
var downY = 0f
constructor(context: Context?) : this(context, null, 0)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
init {
setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
downX = event.x
downY = event.y
}
MotionEvent.ACTION_MOVE -> {
val offsetX = event.x - downX
val offsetY = event.y - downY
layout(
(left + offsetX).toInt(),
(top + offsetY).toInt(),
(right + offsetX).toInt(),
(bottom + offsetY).toInt()
)
}
}
true
}
}
}
2.使用offsetLeftAndRight、offsetTopAndBottom
class CustomView : View {
var downX = 0f
var downY = 0f
constructor(context: Context?) : this(context, null, 0)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
init {
setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
downX = event.x
downY = event.y
}
MotionEvent.ACTION_MOVE -> {
val offsetX = event.x - downX
val offsetY = event.y - downY
offsetLeftAndRight(offsetX.toInt())
offsetTopAndBottom(offsetY.toInt())
}
}
true
}
}
}
3.通过改变LayoutParams
这里有个坑,注意你的父布局。
比如约束布局上下左右的约束都设置了,那这个会有异常。上下都设置了约束,那view会居中,margin会在居中的基础上再生效。
class CustomView : View {
var downX = 0f
var downY = 0f
constructor(context: Context?) : this(context, null, 0)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
init {
setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
downX = event.x
downY = event.y
}
MotionEvent.ACTION_MOVE -> {
val offsetX = event.x - downX
val offsetY = event.y - downY
val layoutParams = layoutParams as MarginLayoutParams
layoutParams.leftMargin = (left + offsetX).toInt()
layoutParams.topMargin = (top + offsetY).toInt()
setLayoutParams(layoutParams)
}
}
true
}
}
}
4.scollTo与scollBy
scollTo(x,y)表示移动到一个具体的坐标点,而scollBy(dx,dy)则表示移动的增量为dx、dy。其中scollBy最终也是要调用scollTo的。scollTo、scollBy移动的是View的内容,如果在ViewGroup中使用则是移动他所有的子View。
class CustomView : View {
var downX = 0f
var downY = 0f
constructor(context: Context?) : this(context, null, 0)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
init {
setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
downX = event.x
downY = event.y
}
MotionEvent.ACTION_MOVE -> {
val offsetX = event.x - downX
val offsetY = event.y - downY
(parent as View).scrollBy(-offsetX.toInt(), -offsetY.toInt())
}
}
true
}
}
}