控件拖拽实现方式:
①根据控件的touch事件进行位置修改
②用ViewDragHelper做自定义控件
①介绍:
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:// 获取手指第一次接触屏幕
sx = (int) event.getRawX();
sy = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:// 手指在屏幕上移动对应的事件
int x = (int) event.getRawX();
int y = (int) event.getRawY();
// 获取手指移动的距离
int dx = x - sx;
int dy = y - sy;
// 得到imageView最开始的各顶点的坐标
int l = v.getLeft();
int r = v.getRight();
int t = v.getTop();
int b = v.getBottom();
// 更改imageView在窗体的位置
v.layout(l + dx, t + dy, r + dx, b + dy);
// 获取移动后的位置
sx = (int) event.getRawX();
sy = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
依据不同手指动作进行相应处理:
①手指触摸屏幕:记录控件初始位置
②鼠标移动:先记录手指移动位置,接着按上次记录的位置将移动偏移量计算出来,偏移量+控件的长宽高等可以计算出控件新的layout位置,进行设置即可。
上述就是粗略实现了控件的拖拽,依据实际要求,在不同的事件进行添加逻辑即可。
②介绍:
首先这个用法主要是自己制造一个布局,该布局下的所有控件都可以拖动
public class DragView extends ConstraintLayout {
ViewDragHelper viewDragHelper;
public DragView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
viewDragHelper = ViewDragHelper.create(this, 1.f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
return true;
}
@Override
public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
return left;
}
@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
return top;
}
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return viewDragHelper.shouldInterceptTouchEvent(ev);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);
return true;
}
}
上述是最基础设置,要用ViewDragHelper拦截控件本身的触碰方法,交由其控制。
<com.example.draghelper.DragView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@drawable/right" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@drawable/right" />
</com.example.draghelper.DragView>
在布局中,该layout下的所有控件都可以自由拖动,重点实现让控件拖拽就是通过拦截其触碰事件完成,所以可以通过在拦截部分实现部分控件拖拽。
具体逻辑在onViewReleased等事件中完成。
并且在这个布局中的tryCaptureView会将View按序获取、存储,后续可以通过getChildAt(index)对特定的View进行逻辑设计。
拖拽注意事项:
有时添加一些操作,会导致拖拽的图片返回到初始位置,这通常因为拖拽后,底层的layoutparams更改了,即布局内的控件属性等进行了修改,这种情况需要重新给拖拽的View设置一次layoutParams。