虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > Android编程 > android 右滑返回的示例代码

android 右滑返回的示例代码
类别:Android编程   作者:码皇   来源:互联网   点击:

本篇文章主要介绍了android 右滑返回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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

渐进步骤:

  • 设置activity背景透明
  • 重写finish()等方法设置activity的跳转动画
  • 重写dispatchTouchEvent()拦截 所需要 右滑动作
  • 重写onTouchEvent()给根布局设置偏移量
  • 添加滑动时上层activity的左侧阴影
  • 滑动时关联下层activity滑动

注意:步骤中的代码为了不关联到后面的步骤,会与最终的有点不同

背景透明

    <item name="android:windowBackground">@android:color/transparent</item> <item name="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, int requestCode) {
    super.startActivityForResult(intent, requestCode);
    overridePendingTransition(R.anim.slide_right_in, 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 右滑返回