您的位置:首页 > 移动开发 > 微信开发

ViewDragHelper实现微信侧滑

2015-12-25 14:51 716 查看
本文是参考开源的代码进行修改获得的,https://github.com/BlueMor/DragLayout

 具体实现已经都在代码中添加了注解,

public class SlideDrawLayout extends FrameLayout {

private Context mContext;

private View mLeftContainer;

private View mMainContainer;

private ViewDragHelper dragHelper;

private int mDragTotalDis;

private int mMainToLeftDis; // 就记录主View的左边距离

private int mWidth;

private int mHeight;

private int mLeftWidth;

private int mLeftLayoutDis;

private int mLeftScrollDis;

public SlideDrawLayout(Context context) {
this(context, null, -1);
}

public SlideDrawLayout(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}

public SlideDrawLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}

public void init(Context context) {

mContext = context;

// 第二参数,配置拖动的敏感度
dragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {

//决定chlid是否可被拖动
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == mLeftContainer || child == mMainContainer;
}

// 当View正被拖着时
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}

@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
if (releasedChild == mMainContainer) {
if (mMainToLeftDis > mDragTotalDis / 3) {
open();
} else {
close();
}
} else if (releasedChild == mLeftContainer) {
if (mMainToLeftDis < mDragTotalDis / 3) {
close();
} else {
open();
}
}
}

// 横向拖拽的范围,大于0时可拖拽,等于0无法拖拽
// 此方法只用于计算如view释放速度,敏感度等
// 实际拖拽范围由clampViewPositionHorizontal方法设置
@Override
public int getViewHorizontalDragRange(View child) {
return super.getViewHorizontalDragRange(child);
}

//返回的是拖动的范围,如果当前移动的超过了,不能继续拖动
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (mMainToLeftDis + dx < 0) {
return 0;
} else if (mMainToLeftDis + dx > mDragTotalDis) {
return mDragTotalDis;
}
return left;
}

// 当View位置发生变化,
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
if (changedView == mMainContainer) {
mMainToLeftDis = left;
} else {// 当是左边的View时, left,就是左边View的值了,
mMainToLeftDis += dx;
}

// 进行值的修正
if (mMainToLeftDis < 0) {
mMainToLeftDis = 0;
} else if (mMainToLeftDis > mDragTotalDis) {
mMainToLeftDis = mDragTotalDis;
}

// 如果拖拽的是左面板,强制在指定位置绘制Content
if (changedView == mLeftContainer) {
layoutContent();
}

dispatchDragEvent(mMainToLeftDis);

}

@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return super.clampViewPositionVertical(child, top, dy);
}

});
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return dragHelper.shouldInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
dragHelper.processTouchEvent(event);
return true;
}

private void layoutContent() {
mMainContainer.layout(mMainToLeftDis, 0, mMainToLeftDis + mWidth, mHeight);
mLeftContainer.layout(0, 0, mWidth, mHeight);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

mMainContainer.layout(mMainToLeftDis, 0, mMainToLeftDis + mWidth, mHeight);
mLeftContainer.layout(0, 0, mLeftWidth, mHeight);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 初始移动一定距离
ViewHelper.setTranslationX(mLeftContainer, -mLeftLayoutDis);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();

if (mLeftContainer != null) {

mLeftWidth = mLeftContainer.getMeasuredWidth();

mLeftLayoutDis = mLeftWidth / 3;

mDragTotalDis = mLeftWidth;

mLeftScrollDis = mLeftLayoutDis;

}

}

/**
* 每次更新都会调用 根据当前执行的位置计算百分比percent
*/
protected void dispatchDragEvent(int left) {
float percent = left / (float) mDragTotalDis;
animViews(percent);
}

/**
* 伴随动画:
*
* @param percent
*/
private void animViews(float percent) {

float leftDis = -mLeftScrollDis + mLeftScrollDis * percent;

ViewHelper.setTranslationX(mLeftContainer, leftDis);
}

public void close() {
close(true);
}

public void open() {
open(true);
}

public void close(boolean isSmooth) {
mMainToLeftDis = 0;
if (isSmooth) {
// 执行动画,返回true代表有未完成的动画, 需要继续执行
if (dragHelper.smoothSlideViewTo(mMainContainer, mMainToLeftDis, 0)) {
// 注意:参数传递根ViewGroup
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
layoutContent();
}
}

public void open(boolean isSmooth) {
mMainToLeftDis = mDragTotalDis;
if (isSmooth) {
if (dragHelper.smoothSlideViewTo(mMainContainer, mMainToLeftDis, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
layoutContent();
}
}

@Override
public void computeScroll() {
//
if (dragHelper.continueSettling(true)) { // true 决定后面继续执行,
ViewCompat.postInvalidateOnAnimation(this);
}
}

/**
* 填充结束时获得两个子布局的引用
*/
@Override
protected void onFinishInflate() {

super.onFinishInflate();

int childCount = getChildCount();
// 必要的检验
if (childCount < 2) {
throw new IllegalStateException(
"You need two childrens in your content");
}

if (!(getChildAt(0) instanceof ViewGroup)
|| !(getChildAt(1) instanceof ViewGroup)) {
throw new IllegalArgumentException(
"Your childrens must be an instance of ViewGroup");
}

mLeftContainer = getChildAt(0);
mMainContainer = getChildAt(1);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息