Android 版仿微信朋友圈图片拖拽返回效果
}
@Overridepublic void dragging(float percent) {//拖拽中。percent 当前的进度,取值 0-1,可以在此额外处理一些逻辑}
@Overridepublic void dragCancel() {//拖拽取消,会自动复原。可以在此额外处理一些逻辑}
@Overridepublic void dragClose(boolean isShareElementMode) {//拖拽关闭,如果是共享元素的页面,需要执行 activity 的 onBackPressed 方法,注意如果使用 finish 方法,则返回的时候没有共享元素的返回动画 if (isShareElementMode) {onBackPressed();}}});
6.处理 touch 事件
@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {if (dragCloseHelper.handleEvent(event)) {return true;} else {return super.dispatchTouchEvent(event);}}
7.可以自定义最大拖拽距离和最小缩放尺寸
setMaxExitY(int maxExitY)setMinScale(@FloatRange(from = 0.1f, to = 1.0f) float minScale)
原理:
很简单,就是 touch 事件传递,相信大家都已经滚瓜烂熟了。大概步骤:1.检测是否有拦截 2.ACTION_DOWN 事件,初始化数据 3.ACTION_MOVE 事件,如果多手指或者手指 Id 不一致,则复原,否则开始移动,同时更新拖拽 View/ViewGroup 的位置和大小。4.ACTION_UP 事件,判断是否超过指定的最大距离,如果超过,开始关闭动画,否则开始复原动画
核心代码如下:
/**
处理 touch 事件
@param event
@return*/public boolean handleEvent(MotionEvent event) {if (dragCloseListener != null && dragCloseListener.intercept()) {//拦截 isSwipingToClose = false;return false;} else {//不拦截 if (event.getAction() == MotionEvent.ACTION_DOWN) {//初始化数据 lastPointerId = event.getPointerId(0);reset(event);} else if (event.getAction() == MotionEvent.ACTION_MOVE) {if (event.getPointerCount() > 1) {//如果有多个手指 if (isSwipingToClose) {//已经开始滑动关闭,恢复原状,否则需要派发事件 isSwipingToClose = false;resetCallBackAnimation();return true;}reset(event);return false;}if (lastPointerId != event.getPointerId(0)) {//手指不一致,恢复原状 if (isSwipingToClose) {resetCallBackAnimation();}reset(event);return true;}float currentY = event.getY();float currentX = event.getX();if (isSwipingToClose || Math.abs(currentY - mLastY) > 2 * viewConfiguration.getScaledTouchSlop()) {//已经触发或者开始触发,更新 viewmLastY = currentY;mLastX = currentX;float currentRawY = event.getRawY();float currentRawX = event.getRawX();if (!isSwipingToClose) {//准备开始 isSwipingToClose = true;if (dragCloseListener != null) {dragCloseListener.dragStart();}}//已经开始,更新 viewmCurrentTranslationY = currentRawY - mLastRawY + m
LastTranslationY;mCurrentTranslationX = currentRawX - mLastRawX + mLastTranslationX;float percent = 1 - Math.abs(mCurrentTranslationY / (maxExitY + childV.getHeight()));if (percent > 1) {percent = 1;} else if (percent < 0) {percent = 0;}parentV.getBackground().mutate().setAlpha((int) (percent * 255));if (dragCloseListener != null) {dragCloseListener.dragging(percent);}childV.setTranslationY(mCurrentTranslationY);childV.setTranslationX(mCurrentTranslationX);if (percent < minScale) {percent = minScale;}childV.setScaleX(percent);childV.setScaleY(percent);return true;}} else if (event.getAction() == MotionEvent.ACTION_UP) {//手指抬起事件 if (isSwipingToClose) {if (mCurrentTranslationY > maxExitY) {if (isShareElementMode) {//会执行共享元素的离开动画 if (dragCloseListener != null) {dragCloseListener.dragClose(true);}} else {//会执行定制的离开动画 exitWithTranslation(mCurrentTranslationY);}} else {resetCallBackAnimation();}isSwipingToClose = false;return true;}} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {//取消事件 if (isSwipingToClose) {resetCallBackAnimation();isSwipingToClose = false;return true;}}}return false;}
衍生文章
在发布文章之后,有人提出在滑动返回的过程中,上一个页面的背景是空白的。对此特意写了篇文章Android 共享元素动画分析及背景空白的解决方案
然后自己也发现了一个问题,也写了一篇文章Android 虚拟按键隐藏或显示之后共享元素动画异常解决方案
评论