我想在拖动时实现可移动的imageView。拖动工作完全没问题。但是当我拖到最后,imageView会离开屏幕。 如何才能在屏幕内移动图像视图?
这是我的OnTouch listerner:
public boolean onTouch(View view, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
lastAction = MotionEvent.ACTION_DOWN;
break;
case MotionEvent.ACTION_MOVE:
view.setY(event.getRawY() + dY);
view.setX(event.getRawX() + dX);
lastAction = MotionEvent.ACTION_MOVE;
break;
case MotionEvent.ACTION_UP:
if (lastAction == MotionEvent.ACTION_DOWN)
Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
break;
default:
return false;
}
return true;
}
这是我的布局。布局包含一个scrollview及其子项,以及我想要拖动的imageview。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#ff0000"
android:gravity="center"
android:text="View 1"
android:textColor="#000"
android:textSize="100dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#00ff00"
android:text="View 2"
android:textColor="#000"
android:textSize="100dp" />
</LinearLayout>
</ScrollView>
<ImageView
android:id="@+id/draggable_view"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="20dp"
android:layout_marginEnd="20dp"
android:background="@drawable/icon" />
</FrameLayout>
答案 0 :(得分:3)
花了更多时间,最后找到最佳解决方案。
将我的OnTouch listerner部分修改为:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
screenHight = displaymetrics.heightPixels;
screenWidth = displaymetrics.widthPixels;
@SuppressLint("NewApi") @Override
public boolean onTouch(View view, MotionEvent event) {
float newX, newY;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
lastAction = MotionEvent.ACTION_DOWN;
break;
case MotionEvent.ACTION_MOVE:
newX = event.getRawX() + dX;
newY = event.getRawY() + dY;
// check if the view out of screen
if ((newX <= 0 || newX >= screenWidth-view.getWidth()) || (newY <= 0 || newY >= screenHight-view.getHeight()))
{
lastAction = MotionEvent.ACTION_MOVE;
break;
}
view.setX(newX);
view.setY(newY);
lastAction = MotionEvent.ACTION_MOVE;
break;
case MotionEvent.ACTION_UP:
if (lastAction == MotionEvent.ACTION_DOWN)
Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
break;
default:
return false;
}
return true;
}
它完美地工作:)
答案 1 :(得分:1)
经过大量研究,我找到了最好的稳健解决方案。以下代码非常适合我将 ImageView 或任何视图保持在屏幕边界内。 使用ACTION_MOVE
中的代码val pointerIndex = event.findPointerIndex(activePointerId)
if (pointerIndex == -1) return false
val (x, y) = event.getX(pointerIndex) to event.getY(pointerIndex)
posX += x - lastTouchX
posY += y - lastTouchY
// The BOUNDS_PADDING can be any value you like (Ex: 50)
val leftBound = -screenWidth + BOUNDS_PADDING
val rightBound = screenWidth - BOUNDS_PADDING
val downBound = -screenHeight + BOUNDS_PADDING
val upBound = screenHeight - BOUNDS_PADDING
if (posX <= leftBound) {
// Left Bound Reached while Dragging. So reset view position to be within bounds
posX = leftBound.toFloat()
}
if (posX >= rightBound) {
// Right Bound Reached while Dragging. So reset view position to be within bounds
posX = rightBound.toFloat()
}
if (posY <= downBound) {
// Bottom Bound Reached while Dragging. So reset view position to be within bounds
posY = downBound.toFloat()
}
if (posY >= upBound) {
// Top Bound Reached while Dragging. So reset view position to be within bounds
posY = upBound.toFloat()
}
binding.imageView.x = posX
binding.imageView.y = posY
lastTouchX = x
lastTouchY = y
您可以使用以下方法获取屏幕宽度和高度
// Get Device Display Height and Width
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val wm = windowManager.currentWindowMetrics
val insets = wm.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
screenWidth = wm.bounds.width() - insets.left - insets.right
screenHeight = wm.bounds.height() - insets.bottom - insets.top
} else {
val dm = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(dm)
screenWidth = dm.widthPixels
screenHeight = dm.heightPixels
}