现象: 在FrameLayout中添加一个拖拽的View后,经过移动,该view移动到指定位置 然后再次添加一个拖拽的view,这时候发现之前被移动的view又回到了初始位置
使用addView方法时,如何保持已有动态控件位置不初始化?
经过一番尝试,终于解决这个问题,简单说就是,不能使用layout()方法,来改变位置。layout()虽然可以改变控件的位置, 但不会将位置信息保存到layoutparam中。而调用addView往布局添加新的控件时,是根据layoutparam来重新布局控件位置的。 因此另一种方法就是:先获取控件的layoutparam,改变其中相关的值后,再设置回去。 这样移动过的控件,就不会在addView时回到原来的位置了。
public class DragViewGroup extends ConstraintLayout {
private int lastX;
private int lastY;
private final Rect bound;
private OnTouchDownListener touchDownListener;
public DragViewGroup(Context context) {
this(context, null);
}
public DragViewGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
DisplayMetrics dm = getResources().getDisplayMetrics();
bound = new Rect(0, 0, dm.widthPixels, dm.heightPixels);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
AbsoluteLayout.LayoutParams param = (AbsoluteLayout.LayoutParams) getLayoutParams();
param.x = (bound.left + bound.right) / 2 - getMeasuredWidth() / 2;
param.y = (bound.top + bound.bottom) / 2 - getMeasuredHeight() / 2;
setLayoutParams(param);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
if (touchDownListener != null) {
touchDownListener.onTouchDown();
}
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
int left = getLeft() + dx;
int top = getTop() + dy;
int right = getRight() + dx;
int bottom = getBottom() + dy;
if (left < bound.left) {
left = bound.left;
right = left + getWidth();
}
if (right > bound.right) {
right = bound.right;
left = right - getWidth();
}
if (top < bound.top) {
top = bound.top;
bottom = top + getHeight();
}
if (bottom > bound.bottom) {
bottom = bound.bottom;
top = bottom - getHeight();
}
layout(left, top, right, bottom);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
//记录
AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams) getLayoutParams();
params.x = getLeft();
params.y = getTop();
getParent().requestDisallowInterceptTouchEvent(false);
break;
default:
break;
}
return true;
}
public void setBound(int left, int top, int right, int bottom) {
this.bound.left = left;
this.bound.right = right;
this.bound.top = top;
this.bound.bottom = bottom;
}
//添加按下的事件
public void addTouchDownListener(OnTouchDownListener listener) {
this.touchDownListener = listener;
}
public interface OnTouchDownListener {
void onTouchDown();
}
}