我必须在屏幕上拖一些视图。我正在修改他们的位置,通过从触摸侦听器更改ACTION_MOVE上的运动事件的布局参数的左侧和顶部。有没有办法“拖动”项目更顺畅?因为这种“拖动”根本就不顺畅......这是代码
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
dx = (int) motionEvent.getX();
dy = (int) motionEvent.getY();
break;
case MotionEvent.ACTION_MOVE:
int x = (int) motionEvent.getX();
int y = (int) motionEvent.getY();
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams();
int left = lp.leftMargin + (x - dx);
int top = lp.topMargin + (y - dy);
lp.leftMargin = left;
lp.topMargin = top;
view.setLayoutParams(lp);
break;
}
return true;
}
答案 0 :(得分:22)
尝试使用motionEvent.getRawX()和motionEvent.getRawY()而不是getY和getX
答案 1 :(得分:4)
答案 2 :(得分:1)
不平滑移动的原因是leftMargin和topMargin的整数值 为了平稳移动,位置应该是浮动的 This可以提供帮助。
答案 3 :(得分:0)
了解如何处理ACTION_MOVE事件会很有用。 您是否使用event.getHistorical()方法利用所有点? 如果这不能给你一个更平滑的拖拽,其他想法可能是在路径上插入点。我相信在实现平稳运动和快速响应用户触摸之间需要进行权衡。 HTH。
答案 4 :(得分:0)
你应该对你的整数进行舍入,使用边距也不会非常平滑,使用不同的布局并根据屏幕尺寸设置X和Y坐标。
答案 5 :(得分:0)
最简单,最简洁的方法之一是创建一个自定义视图,并在该自定义视图中实现onTouchListener。在下面的代码片段中,我们扩展了AppCompatImageView。相反,我们可以使用任何一种视图。
class DraggableImageView(context: Context, attrs: AttributeSet) :
AppCompatImageView(context, attrs) {
private var draggableListener: DraggableListener? = null
private var widgetInitialX: Float = 0F
private var widgetDX: Float = 0F
private var widgetInitialY: Float = 0F
private var widgetDY: Float = 0F
init {
draggableSetup()
}
private fun draggableSetup() {
this.setOnTouchListener { v, event ->
val viewParent = v.parent as View
val parentHeight = viewParent.height
val parentWidth = viewParent.width
val xMax = parentWidth - v.width
val xMiddle = parentWidth / 2
val yMax = parentHeight - v.height
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
widgetDX = v.x - event.rawX
widgetDY = v.y - event.rawY
widgetInitialX = v.x
widgetInitialY = v.y
}
MotionEvent.ACTION_MOVE -> {
var newX = event.rawX + widgetDX
newX = max(0F, newX)
newX = min(xMax.toFloat(), newX)
v.x = newX
var newY = event.rawY + widgetDY
newY = max(0F, newY)
newY = min(yMax.toFloat(), newY)
v.y = newY
draggableListener?.onPositionChanged(v)
}
MotionEvent.ACTION_UP -> {
if (event.rawX >= xMiddle) {
v.animate().x(xMax.toFloat())
.setDuration(Draggable.DURATION_MILLIS)
.setUpdateListener { draggableListener?.onPositionChanged(v) }
.start()
} else {
v.animate().x(0F).setDuration(Draggable.DURATION_MILLIS)
.setUpdateListener { draggableListener?.onPositionChanged(v) }
.start()
}
if (abs(v.x - widgetInitialX) <= DRAG_TOLERANCE && abs(v.y - widgetInitialY) <= DRAG_TOLERANCE) {
performClick()
} else draggableListener?.xAxisChanged(event.rawX >= xMiddle)
}
else -> return@setOnTouchListener false
}
true
}
}
override fun performClick(): Boolean {
Log.d("DraggableImageView", "click")
return super.performClick()
}
fun setListener(draggableListener: DraggableListener?) {
this.draggableListener = draggableListener
}
}
object Draggable {
const val DRAG_TOLERANCE = 16
const val DURATION_MILLIS = 250L
}
interface DraggableListener {
fun onPositionChanged(view: View)
fun xAxisChanged(isInRightSide: Boolean)
}