类似于微信的右滑返回,在BaseActivity里利用dispatchtouchEvent()拦截右滑动作,利用setTranslationX()实现动画,在DecorVIEw里添加VIEw作为滑动时的左侧阴影。
渐进步骤:
设置activity背景透明 重写finish()等方法设置activity的跳转动画 重写dispatchtouchEvent()拦截 所需要 右滑动作 重写ontouchEvent()给根布局设置偏移量 添加滑动时上层activity的左侧阴影 滑动时关联下层activity滑动注意:步骤中的代码为了不关联到后面的步骤,会与最终的有点不同
背景透明
<item @R_419_6889@="androID:windowBackground">@androID:color/transparent</item> <item @R_419_6889@="androID:windowIsTranslucent">true</item>
activity的跳转动画
根据项目需要,重写用到的startActivity(Intent intent),startActivityForResult(Intent intent,int requestCode),finish()等activity跳转和销毁方法
@OverrIDepublic voID startActivity(Intent intent) { super.startActivity(intent); overrIDePendingTransition(R.anim.slIDe_right_in,0);}@OverrIDepublic voID startActivityForResult(Intent intent,int requestCode) { super.startActivityForResult(intent,requestCode); overrIDePendingTransition(R.anim.slIDe_right_in,0);}@OverrIDepublic voID finish() { super.finish(); overrIDePendingTransition(0,R.anim.slIDe_right_out);}//R.anim.slIDe_right_in<set xmlns:androID="http://schemas.androID.com/apk/res/androID"> <translate androID:duration="300" androID:fromXDelta="100%" androID:toXDelta="0" androID:fromYDelta="0" androID:toYDelta="0"/></set>//R.anim.slIDe_right_out<set xmlns:androID="http://schemas.androID.com/apk/res/androID"> <translate androID:duration="300" androID:fromXDelta="0" androID:toXDelta="100%" androID:fromYDelta="0" androID:toYDelta="0" /></set>
拦截右滑动作
所有的触摸事件通过activity.dispatchtouchEvent(MotionEvent ev)向vIEw分发。
手指在X轴方向右滑动50~100px时,判断是否为(产品经理要)右滑动作
private float downX = 0;private float downY = 0;private boolean shouldIntercept = false;private boolean hadJudge = false;@OverrIDepublic boolean dispatchtouchEvent(MotionEvent ev) { if (shouldIntercept) { return ontouchEvent(ev); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: { downX = ev.getRawX(); downY = ev.getRawY(); hadJudge = false; break; } case MotionEvent.ACTION_MOVE: { if (hadJudge) break; if (ev.getRawX() == downX) break; if (ev.getRawX() < downX) { //左滑 hadJudge = true; break; } if (ev.getRawX() - downX >=100){ //超出判断距离 hadJudge = true; break; } if (ev.getRawX() - downX > 50) { //x轴右滑50~100px float rate = (ev.getRawX() - downX) / (Math.abs(ev.getRawY() - downY)); if ((downX < 50 && rate > 0.5f) || rate > 2) { shouldIntercept = true; } } break; } case MotionEvent.ACTION_UP: { downX =0; downY = 0; shouldIntercept = false; hadJudge=false; break; } } //Activity的默认分发 if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getwindow().superdispatchtouchEvent(ev)) { return true; } return true;}
根布局位移动画
根据手指滑动距离设置根布局偏移距离,用滑动距离和手指抬起时的速度判断是否返回
private VIEw rootVIEw = null;private float lastX = -1; private VeLocityTracker veLocityTracker = null;private int maxFlingVeLocity;@OverrIDepublic boolean ontouchEvent(MotionEvent event) { if (rootVIEw == null) { VIEwGroup rootGroup = (VIEwGroup) (getwindow().getDecorVIEw()); rootVIEw = rootGroup.getChildAt(0); } //测量手指抬起时的速度 if (veLocityTracker == null) { veLocityTracker = VeLocityTracker.obtain(); maxFlingVeLocity = VIEwConfiguration.get(this).getScaledMaximumFlingVeLocity(); } veLocityTracker.addMovement(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { lastX = event.getRawX(); break; } case MotionEvent.ACTION_MOVE: { if (lastX == -1) { lastX = event.getRawX(); break; } //根据手指滑动距离设置根布局偏移距离 rootVIEw.setTranslationX(rootVIEw.getTranslationX() + event.getRawX() - lastX); if (rootVIEw.getTranslationX() < 0) rootVIEw.setTranslationX(0); lastX = event.getRawX(); break; } case MotionEvent.ACTION_UP: { //测量手指抬起时的速度 veLocityTracker.computeCurrentVeLocity(1000,maxFlingVeLocity); float veLocityX = veLocityTracker.getXVeLocity(); if (veLocityTracker != null) { veLocityTracker.recycle(); veLocityTracker = null; } //判断是否返回 if (downX < 50 && veLocityX > 1000) { //手指在左侧边落下,返回 onBack(); } else if (veLocityX > 3600) { //手指快速滑动,返回 onBack(); } else if (rootVIEw.getTranslationX() > ConvertUtil.getWIDthInPx() * 0.3) { //滑动距离超过30%屏幕宽度,返回 onBack(); } else { //不返回,根布局偏移归零 rootVIEw.animate().translationX(0).setDuration(200).start(); } lastX = -1; shouldIntercept = false; hadJudge=false; downX = 0; downY = 0; break; } } return super.ontouchEvent(event);}
添加左侧阴影
Activity的最顶层VIEw为DecorVIEw,DecorVIEw是一个FrameLayout,里面只有一个linearlayout,linearlayout包含着标题栏和自定义布局(setContentVIEw)。
上一步跟随手指滑动进行偏移的就是linearlayout,现在要在DecorVIEw里添加一个VIEw,设置背景作为阴影,并跟随linearlayout进行移动
private VIEw shadowVIEw = null;@OverrIDepublic boolean ontouchEvent(MotionEvent event) { if (rootVIEw == null) { //添加阴影 VIEwGroup rootGroup = (VIEwGroup) (getwindow().getDecorVIEw()); shadowVIEw = new VIEw(this); rootGroup.addVIEw(shadowVIEw,0); VIEwGroup.LayoutParams params = shadowVIEw.getLayoutParams(); //阴影宽度 params.wIDth = (int) ((float) ConvertUtil.getWIDthInPx() * 0.05f); params.height = ConvertUtil.getHeightInPx(); shadowVIEw.setLayoutParams(params); shadowVIEw.setBackgroundResource(R.drawable.shadow_grey_h); shadowVIEw.setTranslationX(params.wIDth); rootVIEw = rootGroup.getChildAt(1); } ... switch (event.getAction()) { ... case MotionEvent.ACTION_MOVE: { if (lastX == -1) { lastX = event.getRawX(); break; } //根据手指滑动距离设置根布局偏移距离 rootVIEw.setTranslationX(rootVIEw.getTranslationX() + event.getRawX() - lastX); if (rootVIEw.getTranslationX() < 0) rootVIEw.setTranslationX(0); //阴影跟随根布局移动 shadowVIEw.setTranslationX(-shadowVIEw.getWIDth()+rootVIEw.getTranslationX()); lastX = event.getRawX(); break; } case MotionEvent.ACTION_UP: { ... } else { //不返回,根布局偏移归零 rootVIEw.animate().translationX(0).setDuration(200).start(); //阴影偏移归零 shadowVIEw.animate().translationX(-shadowVIEw.getWIDth()).setDuration(200).start(); } ... } } ...}
关联下层activity滑动
保存所有的activity以获取下层activity 给下层activity添加退出和进入的动画 在上层activity滑动时调用下层滑动获取下层activity
private static ArrayList<Activity> Activity_Stack = new ArrayList<>();private BaseSwipeBackActivity lastActivity = null;@OverrIDeprotected voID onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); maxFlingVeLocity = VIEwConfiguration.get(this).getScaledMaximumFlingVeLocity(); if (!Activity_Stack.contains(this)) Activity_Stack.add(this); if (Activity_Stack.size() >= 2) { Activity last = Activity_Stack.get(Activity_Stack.size() - 2); if (last instanceof BaseSwipeBackActivity) { lastActivity = (BaseSwipeBackActivity) last; } }}@OverrIDeprotected voID onDestroy() { super.onDestroy(); Activity_Stack.remove(this);}
下层activity的退出、进入动画
private voID lowerActivityExitAnim() { if (rootVIEw == null) return; //只移动30% rootVIEw.animate().translationX(-ConvertUtil.getWIDthInPx() * 0.3f).setDuration(300).start();}private voID lowerActivityEnteranim(float upperTranslationX) { if (rootVIEw == null) return; //保证滑动退出时,上下层时间同步 float r = 1-upperTranslationX/ (float) ConvertUtil.getWIDthInPx(); rootVIEw.animate().translationX(0).setDuration((long) (300f * r)).start();}
在跳转时,调用下层activity的退出、进入动画
@OverrIDepublic voID startActivity(Intent intent) { super.startActivity(intent); overrIDePendingTransition(R.anim.slIDe_right_in,0); lowerActivityExitAnim();}@OverrIDepublic voID startActivityForResult(Intent intent,0); lowerActivityExitAnim();}@OverrIDepublic voID finish() { super.finish(); overrIDePendingTransition(0,R.anim.slIDe_right_out); if (lastActivity != null) lastActivity.lowerActivityEnteranim(rootVIEw.getTranslationX()); Activity_Stack.remove(this);}
上层activity滑动时关联下层滑动
@OverrIDepublic boolean ontouchEvent(MotionEvent event) { ... switch (event.getAction()) { ... case MotionEvent.ACTION_MOVE: { ... //根据手指滑动距离设置根布局偏移距离 rootVIEw.setTranslationX(rootVIEw.getTranslationX() + event.getRawX() - lastX); if (rootVIEw.getTranslationX() < 0) rootVIEw.setTranslationX(0); //阴影跟随根布局移动 shadowVIEw.setTranslationX(-shadowVIEw.getWIDth() + rootVIEw.getTranslationX()); //下层activity跟随移动 if (lastActivity != null && lastActivity.rootVIEw != null) //-ConvertUtil.getWIDthInPx() * 0.3f初始的偏移 lastActivity.rootVIEw.setTranslationX(-ConvertUtil.getWIDthInPx() * 0.3f + rootVIEw.getTranslationX() * 0.3f); ... } case MotionEvent.ACTION_UP: { ... } else { //不返回,根布局偏移归零 rootVIEw.animate().translationX(0).setDuration(200).start(); //阴影偏移归零 shadowVIEw.animate().translationX(-shadowVIEw.getWIDth()).setDuration(200).start(); //下层activity偏移复原 if (lastActivity != null) lastActivity.lowerActivityExitAnim(); } ... } } return super.ontouchEvent(event);}
完整的
public abstract class BaseSwipeBackActivity extends AppCompatActivity { private static ArrayList<Activity> Activity_Stack = new ArrayList<>(); private BaseSwipeBackActivity lastActivity = null; private VIEw rootVIEw = null; private VIEw shadowVIEw = null; private float downX = 0; private float downY = 0; private boolean shouldIntercept = false; private boolean hadJudge = false; private float lastX = -1; private VeLocityTracker veLocityTracker = null; private int maxFlingVeLocity; @OverrIDe protected voID onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); maxFlingVeLocity = VIEwConfiguration.get(this).getScaledMaximumFlingVeLocity(); if (!Activity_Stack.contains(this)) Activity_Stack.add(this); if (Activity_Stack.size() >= 2) { Activity last = Activity_Stack.get(Activity_Stack.size() - 2); if (last instanceof BaseSwipeBackActivity) { lastActivity = (BaseSwipeBackActivity) last; } } } @OverrIDe protected voID onResume() { initShadow(); super.onResume(); } @OverrIDe protected voID onDestroy() { super.onDestroy(); Activity_Stack.remove(this); } @OverrIDe public voID startActivity(Intent intent) { super.startActivity(intent); overrIDePendingTransition(R.anim.slIDe_right_in,0); lowerActivityExitAnim(); } @OverrIDe public voID startActivityForResult(Intent intent,int requestCode) { super.startActivityForResult(intent,requestCode); overrIDePendingTransition(R.anim.slIDe_right_in,0); lowerActivityExitAnim(); } @OverrIDe public voID finish() { super.finish(); overrIDePendingTransition(0,R.anim.slIDe_right_out); if (lastActivity != null) lastActivity.lowerActivityEnteranim(rootVIEw.getTranslationX()); Activity_Stack.remove(this); } private voID initShadow() { if (shadowVIEw == null) { VIEwGroup rootGroup = (VIEwGroup) (getwindow().getDecorVIEw()); shadowVIEw = new VIEw(this); rootGroup.addVIEw(shadowVIEw,0); VIEwGroup.LayoutParams params = shadowVIEw.getLayoutParams(); //阴影宽度 params.wIDth = (int) ((float) ConvertUtil.getWIDthInPx() * 0.05f); params.height = ConvertUtil.getHeightInPx(); shadowVIEw.setLayoutParams(params); //渐变背景作为阴影 shadowVIEw.setBackgroundResource(R.drawable.shadow_grey_h); shadowVIEw.setTranslationX(-params.wIDth); rootVIEw = rootGroup.getChildAt(1); } } @OverrIDe public boolean dispatchtouchEvent(MotionEvent ev) { if (shouldIntercept) { return ontouchEvent(ev); } switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: { downX = ev.getRawX(); downY = ev.getRawY(); hadJudge = false; break; } case MotionEvent.ACTION_MOVE: { if (hadJudge) break; if (ev.getRawX() == downX) break; if (ev.getRawX() < downX) { //左滑 hadJudge = true; break; } if (ev.getRawX() - downX >= 100) { //超出判断距离 hadJudge = true; break; } if (ev.getRawX() - downX > 50) { //x轴右滑50~100px float rate = (ev.getRawX() - downX) / (Math.abs(ev.getRawY() - downY)); if ((downX < 50 && rate > 0.5f) || rate > 2) { shouldIntercept = true; } } break; } case MotionEvent.ACTION_UP: { downX = 0; downY = 0; shouldIntercept = false; hadJudge = false; break; } } //Activity的默认分发 if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getwindow().superdispatchtouchEvent(ev)) { return true; } return true; } @OverrIDe public boolean ontouchEvent(MotionEvent event) { initShadow(); //测量手指抬起时的速度 if (veLocityTracker == null) { veLocityTracker = VeLocityTracker.obtain(); maxFlingVeLocity = VIEwConfiguration.get(this).getScaledMaximumFlingVeLocity(); } veLocityTracker.addMovement(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { lastX = event.getRawX(); break; } case MotionEvent.ACTION_MOVE: { if (lastX == -1) { lastX = event.getRawX(); break; } //根据手指滑动距离设置根布局偏移距离 rootVIEw.setTranslationX(rootVIEw.getTranslationX() + event.getRawX() - lastX); if (rootVIEw.getTranslationX() < 0) rootVIEw.setTranslationX(0); //阴影跟随根布局移动 shadowVIEw.setTranslationX(-shadowVIEw.getWIDth() + rootVIEw.getTranslationX()); //下层activity跟随移动 if (lastActivity != null && lastActivity.rootVIEw != null) lastActivity.rootVIEw.setTranslationX(-ConvertUtil.getWIDthInPx() * 0.3f + rootVIEw.getTranslationX() * 0.3f); lastX = event.getRawX(); break; } case MotionEvent.ACTION_UP: { //测量手指抬起时的速度 veLocityTracker.computeCurrentVeLocity(1000,maxFlingVeLocity); float veLocityX = veLocityTracker.getXVeLocity(); if (veLocityTracker != null) { veLocityTracker.recycle(); veLocityTracker = null; } //判断是否返回 if (downX < 50 && veLocityX > 1000) { //手指在左侧边落下,返回 onBack(); } else if (veLocityX > 3600) { //手指快速滑动,返回 onBack(); } else if (rootVIEw.getTranslationX() > ConvertUtil.getWIDthInPx() * 0.3) { //滑动距离超过30%屏幕宽度,返回 onBack(); } else { //不返回,根布局偏移归零 rootVIEw.animate().translationX(0).setDuration(200).start(); //阴影偏移归零 shadowVIEw.animate().translationX(-shadowVIEw.getWIDth()).setDuration(200).start(); //下层activity偏移复原 if (lastActivity != null) lastActivity.lowerActivityExitAnim(); } lastX = -1; shouldIntercept = false; hadJudge = false; downX = 0; downY = 0; break; } } return super.ontouchEvent(event); } private voID lowerActivityExitAnim() { if (rootVIEw == null) return; rootVIEw.animate().translationX(-ConvertUtil.getWIDthInPx() * 0.3f).setDuration(300).start(); } private voID lowerActivityEnteranim(float upperTranslationX) { if (rootVIEw == null) return; float r = 1-upperTranslationX/ (float) ConvertUtil.getWIDthInPx(); rootVIEw.animate().translationX(0).setDuration(r == 0.0f ? 10 : (long) (300f * r)).start(); } //退出 abstract public voID onBack();}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
总结以上是内存溢出为你收集整理的android 右滑返回的示例代码全部内容,希望文章能够帮你解决android 右滑返回的示例代码所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)