仿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)))); }
相关文章推荐
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- QQ商业化,如何实现从0到1的破局?
- 十年生死两茫茫,Linux QQ 突然复活!
- 按右键另存图片只能存BMP
- photoshop去除图片上的水印
- VB实现的《QQ美女找茬游戏》作弊器实例
- CSS中的滑动门技术
- 路由器端QQ封堵方案
- upload上传单张图片
- 图片引发的溢出危机(图)
- QQ输入法自动删除其它输入法的解决方法
- 让普通QQ号也能克隆QQ好友
- C#实现把彩色图片灰度化代码分享
- C#将图片和字节流互相转换并显示到页面上
- C#监控文件夹并自动给图片文件打水印的方法
- VBS取QQ或TM自动登录代码并防止关闭的脚本
- 纯CSS实现的当鼠标移上图片添加阴影效果代码
- C#实现打开画图的同时载入图片、最大化显示画图窗体的方法
- 随鼠标移动的图片或文字特效代码