前言
自从iOS提供了侧滑返回上一级页面功能之后,Android很多应用也开始跟风,美其名曰:保证体验上的统一。作为开发者,当然得研究一下如何实现。
方案1-透明activity
将activity背景色设置成透明,滑动时,将activity-content-view跟随侧滑。
优点
缺点
实战
我们可以用如下代码实现一个简化版本的侧滑返回:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| public class SlideBackActivity extends AppCompatActivity { private boolean mFinishAfterAnimate; private float mLastDownPointX; private boolean mIsSliding; private View mContentView; private int mScreenWidth; private int mTouchSlop; @Override protected void onCreate(Bundle savedInstanceState) { Log.e("kkk", "SlideBackActivity-onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_slide_back); mContentView = findViewById(Window.ID_ANDROID_CONTENT); mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop(); mScreenWidth = getResources().getDisplayMetrics().widthPixels; } @Override public boolean dispatchTouchEvent(MotionEvent ev) { final int action = ev.getAction() & MotionEvent.ACTION_MASK; switch (action) { case MotionEvent.ACTION_DOWN: mLastDownPointX = ev.getRawX(); mFinishAfterAnimate = false; mIsSliding = true; break; case MotionEvent.ACTION_MOVE: final float curPointX = ev.getRawX(); if (mIsSliding) { if(Math.abs(curPointX - mLastDownPointX) > mTouchSlop) { mContentView.setX(Math.abs(curPointX - mLastDownPointX)); } } break; case MotionEvent.ACTION_UP: final float currentPointX = ev.getRawX(); if(Math.abs(currentPointX - mLastDownPointX) > 500) { mFinishAfterAnimate = true; animateContentView(Math.abs(currentPointX - mLastDownPointX), mScreenWidth); } else { mFinishAfterAnimate = false; animateContentView(Math.abs(currentPointX - mLastDownPointX), 0); } mIsSliding = false; break; } return super.dispatchTouchEvent(ev); } private void animateContentView(float start, float end) { ObjectAnimator anim1 = ObjectAnimator.ofFloat(mContentView, "x", start, end); AnimatorSet animSet = new AnimatorSet(); animSet.setInterpolator(new LinearInterpolator()); animSet.setDuration(100); animSet.playTogether(anim1); if (mFinishAfterAnimate) { animSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { finish(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } animSet.start(); } @Override public void finish() { super.finish(); if (mFinishAfterAnimate) overridePendingTransition(0,0); } @Override protected void onStart() { Log.e("kkk", "SlideBackActivity-onStart"); super.onStart(); } @Override protected void onResume() { Log.e("kkk", "SlideBackActivity-onResume"); super.onResume(); } @Override protected void onPause() { Log.e("kkk", "SlideBackActivity-onPause"); super.onPause(); } @Override protected void onStop() { Log.e("kkk", "SlideBackActivity-onStop"); super.onStop(); } @Override protected void onDestroy() { Log.e("kkk", "SlideBackActivity-onDestroy"); super.onDestroy(); } }
|
当然了,前提还是得把activity主题设置成透明
1 2 3 4
| <style name="Transparent" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsTranslucent">true</item> </style>
|
通过下方日志我们可以看到,启动SlideBackAcitvity时,上一个activity(main)-onStop方法没有走到,而退出SlideBackAcitvity后,上一个activity(main)-onStart方法也没有走到。
1 2 3 4 5 6 7 8 9 10
| 03-02 15:28:54.790 1531-1531/com.mason.swipebackdemo E/kkk: main-onStart 03-02 15:28:54.799 1531-1531/com.mason.swipebackdemo E/kkk: main-onResume 03-02 15:29:11.439 1531-1531/com.mason.swipebackdemo E/kkk: main-onPause 03-02 15:29:11.447 1531-1531/com.mason.swipebackdemo E/kkk: SlideBackActivity-onCreate 03-02 15:29:11.452 1531-1531/com.mason.swipebackdemo E/kkk: SlideBackActivity-onStart 03-02 15:29:11.453 1531-1531/com.mason.swipebackdemo E/kkk: SlideBackActivity-onResume 03-02 15:29:16.905 1531-1531/com.mason.swipebackdemo E/kkk: SlideBackActivity-onPause 03-02 15:29:16.924 1531-1531/com.mason.swipebackdemo E/kkk: main-onResume 03-02 15:29:16.966 1531-1531/com.mason.swipebackdemo E/kkk: SlideBackActivity-onStop 03-02 15:29:16.966 1531-1531/com.mason.swipebackdemo E/kkk: SlideBackActivity-onDestroy
|
开源方案
方案2-替换view
- 拿到上一个Avtivity-View的引用,并添加到当前activity-view下方。
- 滑动时,左侧加上阴影,当前activity-view跟随侧滑
优点
- 无需设置activity透明
- 不影响activity生命周期
缺点
实现相对复杂
开源方案
and_swipeback
SlideBack
结论
新闻采用的是方案2,一是对性能影响相比之下较小,二是有些统计依赖于activity生命周期。因现有开源方案并不能满足需要,最终还是选择自己实现一套。