相关介绍(抄别人的)
推荐工匠若水的博客
帮助我们方便的编写自定义ViewGroup
demo 搞起
public class MyLayout extends LinearLayout{
private ViewDragHelper mDragHelper;
private View view1,view2,view3;
//保存原本的点
private Point mAutoBackOriginPos = new Point();
public MyLayout(Context context) {
this(context,null);
}
public MyLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mDragHelper=ViewDragHelper.create(this,1.0f,new ViewDragCallback());
//设置触摸边缘会触发一些事件
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
}
private class ViewDragCallback extends ViewDragHelper.Callback {
/**
* 尝试捕获子view,一定要返回true
* @param view 尝试捕获的view
* @param pointerId 子view的id,返回什么什么可以移动
* 这里可以决定哪个子view可以拖动
*/
@Override
public boolean tryCaptureView(View view, int pointerId) {
return view==view1||view==view2;
}
/**
* 处理水平方向上的拖动
* @param child 被拖动的view
* @param left 移动到达的x轴的距离
* @param dx 建议的移动的x距离
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//到最左边不继续移动防止越界
if(getPaddingLeft() > left) {
return getPaddingLeft();
}
//viewgroup的宽度 减去 子View的宽度 小于 移动的距离,防止越界
if(getWidth() - child.getWidth() < left) {
return getWidth() - child.getWidth();
}
return left;
}
/**
* 处理竖直方向上的拖动
* @param child 被拖动到view
* @param top 移动到达的y轴的距离
* @param dy 建议的移动的y距离
*/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
// 上边距
if(getPaddingTop() > top) {
return getPaddingTop();
}
// 计算允许向下移动的距离,然后比较,返回可移动的距离
if(getHeight() - child.getHeight() < top) {
return getHeight() - child.getHeight();
}
return top;
}
/**
* 当拖拽到状态改变时回调
* @params 新的状态
*/
@Override
public void onViewDragStateChanged(int state) {
switch (state) {
case ViewDragHelper.STATE_DRAGGING: // 正在被拖动
break;
case ViewDragHelper.STATE_IDLE: // view没有被拖拽或者 正在进行fling/snap
break;
case ViewDragHelper.STATE_SETTLING: // fling完毕后被放置到一个位置
break;
}
super.onViewDragStateChanged(state);
}
/**
* 手指释放时的回调
* 回到记录的位置
* @param releasedChild
* @param xvel
* @param yvel
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if(releasedChild==view2){
mDragHelper.settleCapturedViewAt(mAutoBackOriginPos.x,mAutoBackOriginPos.y);
invalidate();
}
}
/**
* 触摸边缘时触发
* @param edgeFlags
* @param pointerId
*/
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
super.onEdgeDragStarted(edgeFlags, pointerId);
mDragHelper.captureChildView(view3,pointerId);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action= MotionEventCompat.getActionMasked(ev);
if(action==MotionEvent.ACTION_CANCEL||action==MotionEvent.ACTION_UP){
mDragHelper.cancel();
return false;
}
/**
* 检查是否可以拦截touch事件
* 如果onInterceptTouchEvent可以return true 则这里return true
*/
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
/**
* 处理拦截到的事件
* 这个方法会在返回前分发事件
*/
mDragHelper.processTouchEvent(event);
return true;
}
// 实现fling效果
@Override
public void computeScroll() {
super.computeScroll();
//计算可以继续下降?
if(mDragHelper.continueSettling(true)){
invalidate();
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
view1=findViewById(R.id.v1);
view2=findViewById(R.id.v2);
view3=findViewById(R.id.v3);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//保存与左边的距离和与右边的距离
mAutoBackOriginPos.x=view2.getLeft();
mAutoBackOriginPos.y=view2.getTop();
}
}