您的位置:首页 > 其它

仿QQ5.0侧边栏(拖拽,动画)

2015-10-02 10:57 381 查看
github源码下载:https://github.com/heinika/MyQQSideBar主要用到了ViewDragHelper这个类来简化拖拽的操作。中间设置了layout缩小和变大,透明度等动画。背景还添加了一个变暗的滤镜。

第一步:初始化

public DragLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
gestureDetector = new GestureDetectorCompat(context, new YScrollDetector());
dragHelper = ViewDragHelper.create(this, dragHelperCallback);
}

第二步:传递dragHelper到onTouchEvent()

/**
* 将拖拽事件传递到onTouchEvent
* @param e
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent e) {
try {
dragHelper.processTouchEvent(e);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}

第三步,创建一个回调接口ViewDragHelper.Callback(),来设置拖拽过程中完成的动作

private ViewDragHelper.Callback dragHelperCallback = new ViewDragHelper.Callback() {
/**
* 左右滑动的时候,子view的位置
* @param child
* @param left
* @param dx
* @return
*/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (mainLeft + dx < 0) {
return 0;
} else if (mainLeft + dx > range) {
return range;
} else {
return left;
}
}

/**
*
* @param child
* @param pointerId
* @return  true可以获得子view
*/
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}

/**
* 横向拖动的范围
* @param child
* @return
*/
@Override
public int getViewHorizontalDragRange(View child) {
return width;
}

/**
*
* @param releasedChild    释放的子view
* @param xvel             x轴方向上的速度
* @param yvel             y轴方向上的速度
*/
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (xvel > 0) {                              //速度大于零打开
open();
} else if (xvel < 0) {                      //速度小于零关闭
close();
} else if (releasedChild == vg_main && mainLeft > range * 0.3) {      //释放的view是main,则当滑动后的x位置大于0.3打开
open();
} else if (releasedChild == vg_left && mainLeft > range * 0.7) {      //释放的view是left,则当滑动后的x位置大于0.7打开
open();
} else {
close();                                                          //否则关闭
}
}

@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
if (changedView == vg_main) {
mainLeft = left;
} else {
mainLeft = mainLeft + left;
}
if (mainLeft < 0) {
mainLeft = 0;
} else if (mainLeft > range) {
mainLeft = range;
}

if (isShowShadow) {
iv_shadow.layout(mainLeft, 0, mainLeft + width, height);
}
if (changedView == vg_left) {
vg_left.layout(0, 0, width, height);
vg_main.layout(mainLeft, 0, mainLeft + width, height);
}

dispatchDragEvent(mainLeft);
}
};

第四步:在dispatchDragEvent(mainLeft)完成动画

private void dispatchDragEvent(int mainLeft) {
if (dragListener == null) {
return;
}
float percent = mainLeft / (float) range;
//进行动画操作
animateView(percent);
//向接口传递百分比数据
dragListener.onDrag(percent);
Status lastStatus = status;
if (lastStatus != getStatus() && status == Status.Close) {
dragListener.onClose();
} else if (lastStatus != getStatus() && status == Status.Open) {
dragListener.onOpen();
}
}
关闭操作和打开操作
/**
* 定义一个枚举表示三种状态
*/
public enum Status {
Drag, Open, Close
}
public Status getStatus() {
if (mainLeft == 0) {
status = Status.Close;
} else if (mainLeft == range) {
status = Status.Open;
} else {
status = Status.Drag;
}
return status;
}

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

public void open(boolean animate) {
if (animate) {
//平滑的完成打开动画,并销毁这个拖拽动作
if (dragHelper.smoothSlideViewTo(vg_main, range, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
vg_main.layout(range, 0, range * 2, height);
dispatchDragEvent(range);
}
}

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

public void close(boolean animate) {
if (animate) {
if (dragHelper.smoothSlideViewTo(vg_main, 0, 0)) {
ViewCompat.postInvalidateOnAnimation(this);
}
} else {
vg_main.layout(0, 0, width, height);
dispatchDragEvent(0);
}
}
透明度及大小变化的操作
private void animateView(float percent) {
float f1 = 1 - percent * 0.3f;
ViewHelper.setScaleX(vg_main, f1);                          //主布局逐渐变大
ViewHelper.setScaleY(vg_main, f1);
ViewHelper.setTranslationX(vg_left, -vg_left.getWidth() / 2.3f + vg_left.getWidth() / 2.3f * percent);
ViewHelper.setScaleX(vg_left, 0.5f + 0.5f * percent);       //左边的布局逐渐变小
ViewHelper.setScaleY(vg_left, 0.5f + 0.5f * percent);
ViewHelper.setAlpha(vg_left, percent);
if (isShowShadow) {
ViewHelper.setScaleX(iv_shadow, f1 * 1.4f * (1 - percent * 0.12f));
ViewHelper.setScaleY(iv_shadow, f1 * 1.85f * (1 - percent * 0.12f));
}
//添加变暗的滤镜
getBackground().setColorFilter(evaluate(percent, Color.BLACK, Color.TRANSPARENT), PorterDuff.Mode.SRC_OVER);
}

/**
* 设置变暗滤镜的参数
* @param fraction
* @param startValue
* @param endValue
* @return
*/
private Integer evaluate(float fraction, Object startValue, Integer endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;
int endInt = (Integer) endValue;
int endA = (endInt >> 24) & 0xff;
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;
return (int) ((startA + (int) (fraction * (endA - startA))) << 24)
| (int) ((startR + (int) (fraction * (endR - startR))) << 16)
| (int) ((startG + (int) (fraction * (endG - startG))) << 8)
| (int) ((startB + (int) (fraction * (endB - startB))));
}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图片 qq 拖拽 滑动 silder