android 右滑返回的示例代码

android 右滑返回的示例代码,第1张

概述类似于微信的右滑返回,在BaseActivity里利用dispatchTouchEvent()拦截右滑动作,利用setTranslationX()实现动画,在DecorView里添加View作为滑动时的左侧阴影。

类似于微信的右滑返回,在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时,判断是否为(产品经理要)右滑动作

手指落点为全屏幕,X方向滑动距离要比Y方向的大一些; 手指落点为左侧边,X方向滑动距离有一些就行
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 右滑返回的示例代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1144538.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存