其实除了执行父对象的requestLayout以外,执行addView也会造成已拖动到其它位置的子view的复位
问题的关键在于测试代码里的addChild方法和callback的onViewReleased里的requestLayout
必然会造成已拖动过的子view(addChild添加的TextView)复位到0,0坐标
http://stackoverflow.com/questions/22865291/why-is-view-dragged-with-viewdraghelper-reset-to-its-original-position-on-layout
搜到一个同样的问题,但vote 2的答案似乎不太适合我这个随意添加子view的需求
特来求救。
测试代码
public class DragViewLayout extends FrameLayout {
private ViewDragHelper mDragHelper;
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
requestLayout();
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
final int leftBound = getPaddingLeft();
final int rightBound = getWidth() - child.getMeasuredWidth();
final int newLeft = Math.min(Math.max(left, leftBound), rightBound);
ViewHelper.setX(child, newLeft);
return newLeft;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
final int topBound = getPaddingTop();
final int bottomBound = getHeight() - child.getMeasuredHeight();
final int newTop = Math.min(Math.max(top, topBound), bottomBound);
ViewHelper.setY(child, newTop);
return newTop;
}
};
public DragViewLayout(Context context) {
super(context);
}
public DragViewLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DragViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mDragHelper = ViewDragHelper.create(this, 1.0f, callback);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mDragHelper.cancel();
return false;
}
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mDragHelper.processTouchEvent(ev);
return true;
}
public void addChild() {
TextView v = new TextView(getContext());
v.setPadding(20, 20, 20, 20);
v.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
v.setBackgroundColor(getContext().getResources().getColor(android.R.color.darker_gray));
v.setText(System.currentTimeMillis() + "");
addView(v);
}
public void clearChilds() {
this.removeAllViewsInLayout();
}
}