package com.com.mr_wrong.MySwipBacklayout;
import android.content.Context;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
/**
* Created by Mr_Wrong on 15/11/18.
*/
public class MySwipBacklayout extends FrameLayout {
private int mWidth;//整个宽度
private int mHeight;//整个宽度
private int mSwipLeft;//左滑的距离
private int mSwipWidth;//左滑的最大距离
private ViewGroup mContentLyout;//内容
private ViewGroup mBehindLyout;//后面的返回
private ViewDragHelper mViewHelper;
private GestureDetectorCompat mGestureDetecyor;
private SwipeBackListener mSwipBackListener;
private SwipBackStatusEnum mStatusEnum = SwipBackStatusEnum.close;
public enum SwipBackStatusEnum {
swip,
open,
close
}
public interface SwipeBackListener {
void onOpen();
void onClose();
void onSwipe(float percent);
}
public void setOnSwipeBackListener(SwipeBackListener swipBackListener) {
this.mSwipBackListener = swipBackListener;
}
public MySwipBacklayout(Context context) {
super(context);
init();
}
public MySwipBacklayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MySwipBacklayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mViewHelper = ViewDragHelper.create(this, 1.0f, new DragHelper());
mGestureDetecyor = new GestureDetectorCompat(getContext(), new SwipDeteor());
}
class SwipDeteor extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return Math.abs(distanceX) >= Math.abs(distanceY);
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mContentLyout = (ViewGroup) getChildAt(1);
mBehindLyout = (ViewGroup) getChildAt(0);
mBehindLyout.setClickable(true);
mContentLyout.setClickable(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = mBehindLyout.getMeasuredWidth();
mHeight = mBehindLyout.getMeasuredHeight();
mSwipWidth = (int) (mWidth * 0.15);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mContentLyout.layout(mSwipLeft, 0, mWidth + mSwipLeft, mHeight);
mBehindLyout.layout(0, 0, mWidth, mHeight);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewHelper.shouldInterceptTouchEvent(ev) && mGestureDetecyor.onTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewHelper.processTouchEvent(event);
return false;
}
class DragHelper extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View view, int i) {
return true;
}
@Override
public int getViewHorizontalDragRange(View child) {
return mWidth;
}
//限制水平滑动的范围
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (mSwipLeft + dx < 0) {
return 0;
} else if (mSwipLeft + dx > mSwipWidth) {
return mSwipWidth;
} else {
return left;
}
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if (xvel > 0) {
openEvent();
} else if (xvel < 0) {
closeEvent();
}
if (releasedChild == mContentLyout && mSwipLeft > mSwipWidth * 0.5) {
openEvent();
} else {
closeEvent();
}
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
if (changedView == mContentLyout) {
mSwipLeft = left;
} else {
mSwipLeft = mSwipLeft + left;
}
dispatchEvent(mSwipLeft);
invalidate();
}
}
private void dispatchEvent(int swipLeft) {
if (mSwipBackListener == null) {
return;
}
setStatus(mSwipLeft);
float percent = swipLeft /mSwipWidth;
mSwipBackListener.onSwipe(percent);
if (mStatusEnum == SwipBackStatusEnum.open) {
//open回调在openEvent里面 这样在松手的时候再触发效果更好
mBehindLyout.setClickable(true);
} else if (mStatusEnum == SwipBackStatusEnum.close) {
mSwipBackListener.onClose();
mBehindLyout.setClickable(false);
}
}
private void setStatus(int swipLeft) {
if (swipLeft == 0) {
mStatusEnum = SwipBackStatusEnum.close;
} else if (swipLeft == mSwipWidth) {
mStatusEnum = SwipBackStatusEnum.open;
} else {
mStatusEnum = SwipBackStatusEnum.swip;
}
}
@Override
public void computeScroll() {
if (mViewHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
private void closeEvent() {
if (mViewHelper.smoothSlideViewTo(mContentLyout, 0, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
private void openEvent() {
if (mViewHelper.smoothSlideViewTo(mContentLyout, mSwipWidth, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
MySwipBacklayout.this.postDelayed(new Runnable() {
@Override
public void run() {
if (null != mSwipBackListener) mSwipBackListener.onOpen();
}
}, 200);
}
}