import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
/**
* Created by alanchen on 15/7/29.
*/
public class SwipeBackRelativelayout extends RelativeLayout {
public static final String TAG = SwipeBackRelativelayout.class.getSimpleName();
private ViewDragHelper mDragHelper;
/*通过九个数字来表示空白格的位置
* 1 2 3
* 4 5 6
* 7 8 9*/
private int blank;
private int maxLeft;
private int maxTop;
public SwipeBackRelativelayout(Context context) {
this(context, null);
}
public SwipeBackRelativelayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
//初始化空白格的位置
blank = 9;
//ViewDragHelper是很好用的拖拽用设计,建议大家学习
mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelperCallback());
//这句没用上
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
/*会有8个带图片的控件在本ViewGroup里,不能多不能少,
此处打上初始化标记,标记的意义参照变量blank*/
for (int i = 0; i < 8; i++) {
getChildAt(i).setTag(i + 1);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//获取max
maxLeft = getChildAt(0).getWidth() * 2;
maxTop = getChildAt(0).getHeight() * 2;
}
//Notice view 刚初始化的时候就会被调用一次
@Override
public void computeScroll() {
super.computeScroll();
if (mDragHelper.continueSettling(true)) {
invalidate();
}
}
class ViewDragHelperCallback extends ViewDragHelper.Callback {
//当前拖拽的view还在正位时候的位置
public int curViewTop;
public int curViewLeft;
//当前拖拽的view的tag
private int curDragView;
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果返回false,那么这个child是完全不会动的
Log.v(TAG,"tryCaptureView");
if (curDragView != 0)
return (int) child.getTag() == curDragView;
else {
curDragView = (int) child.getTag();
curViewLeft = child.getLeft();
curViewTop = child.getTop();
return true;
}
}
@Override
public void onEdgeTouched(int edgeFlags, int pointerId) {
//好像跟setEdgeTrackingEnabled有关系,没用上
Log.v(TAG,"onEdgeTouched");
}
@Override
public int getViewHorizontalDragRange(View child) {
return 1;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
// Log.d(TAG, "clampViewPositionHorizontal() called with dx = [" + dx + "]");
int c = (int) child.getTag();
if (blank % 3 == 0) {
if (c + 1 == blank) {
return mycalc(maxLeft, maxLeft / 2, left);
}
} else if (blank % 3 == 1) {
if (c - 1 == blank) {
return mycalc(maxLeft / 2, 0, left);
}
} else {
if (c + 1 == blank) {
return mycalc(maxLeft / 2, 0, left);
} else if (c - 1 == blank) {
return mycalc(maxLeft, maxLeft / 2, left);
}
}
return left - dx;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
int c = (int) child.getTag();
if (blank < 4) {
if (c - 3 == blank) {
return mycalc(maxTop / 2, 0, top);
}
} else if (blank < 7) {
if (c + 3 == blank) {
return mycalc(maxTop / 2, 0, top);
} else if (c - 3 == blank) {
return mycalc(maxTop, maxTop / 2, top);
}
} else {
if (c + 3 == blank) {
return mycalc(maxTop, maxTop / 2, top);
}
}
return top - dy;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
Log.v(TAG, "onviewreleased");
Log.v(TAG,curViewLeft+","+curViewTop);
if (Math.abs(releasedChild.getLeft() - curViewLeft) == maxLeft / 2 || Math.abs(releasedChild.getTop() - curViewTop) == maxTop / 2) {
Log.v(TAG, "onviewreleased in");
int i = blank;
blank = (int) releasedChild.getTag();
releasedChild.setTag(i);
curDragView = 0;
} else if (releasedChild.getLeft() == curViewLeft && releasedChild.getTop() == curViewTop) {
curDragView = 0;
}
Log.v(TAG,"curDragView:"+curDragView+",blank:"+blank);
}
int mycalc(int max, int min, int input) {
return input > max ? max : input < min ? min : input;
}
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
Log.v(TAG,"onViewCaptured");
super.onViewCaptured(capturedChild, activePointerId);
}
@Override
public void onViewDragStateChanged(int state) {
Log.v(TAG, "onViewDragStateChanged");
super.onViewDragStateChanged(state);
if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) {
Log.v(TAG, "onviewdragstatechanged finish");
}
}
}
}
以上就是主要代码,以下是布局文件相关
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipeackframelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.inthecheesefactory.lab.designlibrary.Main2Activity">
<com.inthecheesefactory.lab.designlibrary.SwipeBackRelativelayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<View
android:id="@+id/view0"
android:layout_width="180dp"
android:layout_height="80dp"
android:background="@drawable/header" />
<View
android:id="@+id/view8"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/view0"
android:layout_toRightOf="@+id/view0"
android:background="@drawable/header" />
<View
android:id="@+id/view7"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/view8"
android:layout_toRightOf="@+id/view8"
android:background="@drawable/header" />
<View
android:id="@+id/view6"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/view0"
android:background="@drawable/header" />
<View
android:id="@+id/view5"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_below="@+id/view0"
android:layout_toEndOf="@+id/view0"
android:layout_toRightOf="@+id/view0"
android:background="@drawable/header" />
<View
android:id="@+id/view4"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_below="@+id/view7"
android:layout_toEndOf="@+id/view5"
android:layout_toRightOf="@+id/view5"
android:background="@drawable/header" />
<View
android:id="@+id/view3"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/view5"
android:background="@drawable/header" />
<View
android:id="@+id/view2"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_below="@+id/view5"
android:layout_toEndOf="@+id/view3"
android:layout_toRightOf="@+id/view3"
android:background="@drawable/header" />
</com.inthecheesefactory.lab.designlibrary.SwipeBackRelativelayout>
</RelativeLayout>
demo还没写完
来源:oschina
链接:https://my.oschina.net/u/864553/blog/510692