您好,登錄后才能下訂單哦!
這篇文章主要介紹了Android怎么實現(xiàn)微信側滑關閉頁面效果,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
原理
在每個Activity里面都有一個底層的View,也就是所謂的rootView,當我們加載一個xml布局時,系統(tǒng)就會自動給你生成這個rootView,由于它是一個View,那么也就意味著你可以通過一定的代碼隨意移動這個根布局。
如下代碼所示,只要簡單的幾行代碼便能實現(xiàn)布局的移動。
public class SlideActivity extends AppCompatActivity { View mRootView; private GestureDetector mDetector; private int mWindowWidth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo); mRootView = getWindow().getDecorView(); mRootView.setBackgroundColor(Color.BLUE); mDetector = new GestureDetector(this, new GestureListener()); mWindowWidth = getWindow().getWindowManager().getDefaultDisplay().getWidth(); } @Override public boolean onTouchEvent(MotionEvent event) { return mDetector.onTouchEvent(event); } /** * 手勢監(jiān)聽 */ private class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (e1 != null) { handlerCurrentActivityScroll(e2); } return super.onScroll(e1, e2, distanceX, distanceY); } /** * 處理當前頁面滑動 */ private void handlerCurrentActivityScroll(MotionEvent e2) { mRootView.setTranslationX(e2.getX()); if (e2.getX() > mWindowWidth - 20) { finish(); } } } }
這是我們的效果
Activity聯(lián)動
這差距還是很大的,最明顯的地方是,我們移動 的時候,上一層Activity竟然沒有跟著聯(lián)動。
解決這個問題的方法也簡單,如圖所示,每當啟動一個Activity時,系統(tǒng)都會把Activity放到一個棧里面,由于棧的工作原理可知,APP里面的Activity是一層覆蓋一層的,就如上圖所示。為此,每當啟動一個Activity時,就可以把當前的Actiivty存儲到一個List里面,這樣,我們就可以在當前的Activity里面取出上一個Activity進行操作。
因此,在進入一個新的Activity的時候,在其onCreate方法里面把當前的Activity加載到列表里,當退出時,在finish的重載方法里面,將當前Activity從列表里面移除。
注意?。?!在滑動的時候必須需要考慮到Activity里面有可能會有類似于ListView一類的滑動控件,因此,我們必須對事件進行分發(fā)控制。
代碼如下
/** * Created by yuyu on 2015/10/29. */ public class TestActivity extends AppCompatActivity { View mRootView; private GestureDetector mGestureDetector; private static List<TestActivity> mActivitys = new ArrayList<>(); /** * 移動距離 */ private float mWindowWidth; private TestActivity mBeforeActivity; /** * 上一個Activity偏移量 */ private float mOffsetX; /** * 上一個頁面移出的位置 */ private float mOutsideWidth; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo); /** * 把當前Activity加到列表里面 */ mActivitys.add(this); initScrollBack(); } /** * 初始化左滑退出功能 */ private void initScrollBack() { mWindowWidth = getWindowManager().getDefaultDisplay().getWidth(); mOutsideWidth = -mWindowWidth / 4; mOffsetX = mOutsideWidth; mGestureDetector = new GestureDetector(this, new GestureListener()); mRootView = getWindow().getDecorView(); mRootView.setBackgroundColor(Color.BLUE); } /** * 控制分發(fā)事件,在這里控制能能觸發(fā)拖動的范圍 */ @Override public boolean dispatchTouchEvent(@NonNull MotionEvent ev) { if (ev.getX() < mWindowWidth / 10) { if (mActivitys.size() > 1) { mBeforeActivity = mActivitys.get(mActivitys.size() - 2); beforeActivityTranslationX(mOutsideWidth); } return onTouchEvent(ev); } return super.dispatchTouchEvent(ev); } @Override public void finish() { mActivitys.remove(this); if (mOffsetX < 0.0001 || mOffsetX > 0.0001) { beforeActivityTranslationX(0); } super.finish(); } public void onClick(View view) { Intent intent = new Intent(this, Activity5.class); startActivity(intent); } public View getRootView() { return mRootView; } /** * 控制上一個Activity移動 */ private void beforeActivityTranslationX(float translationX) { if (mBeforeActivity != null) { mBeforeActivity.getRootView().setTranslationX(translationX); } } @Override public boolean onTouchEvent(MotionEvent event) { return mGestureDetector.onTouchEvent(event); } /** * 手勢監(jiān)聽 */ private class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (e1 != null) { handlerCurrentActivityScroll(e2); handleBeforeActivityScroll(e2, distanceX); } return super.onScroll(e1, e2, distanceX, distanceY); } /** * 處理當前頁面滑動 */ private void handlerCurrentActivityScroll(MotionEvent e2) { mRootView.setTranslationX(e2.getX()); if (e2.getX() > mWindowWidth - 20) { finish(); } } /** * 處理上一個頁面滑動 */ private void handleBeforeActivityScroll(MotionEvent e2, float distanceX) { if (mBeforeActivity != null) { mOffsetX = distanceX < 0 ? mOffsetX + Math.abs(distanceX) / 4 : mOffsetX - Math.abs(distanceX) / 4; if (mOffsetX > 0.0001) { mOffsetX = 0f; } mBeforeActivity.getRootView().setTranslationX(mOffsetX); } } } }
這是聯(lián)動后的效果圖
現(xiàn)在算是有點效果了,但是和微信的差距還是很大,接下來我們便需要開始處理自動滑動了
自動滑動
這個就不需要多說了,這個主要就是利用屬性動畫進行移動
以下是完整的代碼
public class SlideActivity extends AppCompatActivity { private static final String TAG = "SlideActivity"; private static List<SlideActivity> mActivitys = new ArrayList<>(); /** * 手勢監(jiān)聽 */ private GestureDetector mGestureDetector; private View mRootView; private boolean isScroll = false; /** * 移動距離 */ private float mWindowWidth; private SlideActivity mBeforeActivity; /** * 上一個Activity偏移量 */ private float mOffsetX; /** * 上一個頁面移出的位置 */ private float mOutsideWidth; private boolean canScrollBack = true; private boolean canScroll = false; @Override protected void onCreate(Bundle savedInstanceState) { getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); getWindow().setEnterTransition(new Slide(Gravity.RIGHT)); super.onCreate(savedInstanceState); /** * 把當前Activity加到列表里面 */ mActivitys.add(this); initScrollBack(); } @Override public void startActivity(Intent intent) { startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()); } /** * 初始化左滑退出功能 */ private void initScrollBack() { mWindowWidth = getWindowManager().getDefaultDisplay().getWidth(); mOutsideWidth = -mWindowWidth / 4; mOffsetX = mOutsideWidth; mGestureDetector = new GestureDetector(this, new GestureListener()); mRootView = getWindow().getDecorView(); } /** * 控制上一個Activity移動 */ private void beforeActivityTranslationX(float translationX) { if (mBeforeActivity != null) { mBeforeActivity.getRootView().setTranslationX(translationX); } } /** * 設置是否能滑動 * * @param canScrollBack true 可以滑動 */ protected void setCanScrollBack(boolean canScrollBack) { this.canScrollBack = canScrollBack; } public View getRootView() { return mRootView; } @Override public void finish() { mActivitys.remove(this); if (mOffsetX < 0.0001 || mOffsetX > 0.0001) { beforeActivityTranslationX(0); } super.finish(); } /** * 控制分發(fā)事件 */ @Override public boolean dispatchTouchEvent(@NonNull MotionEvent ev) { if (canScrollBack && ev.getX() < mWindowWidth / 10) { if (mActivitys.size() > 1) { mBeforeActivity = mActivitys.get(mActivitys.size() - 2); beforeActivityTranslationX(mOutsideWidth); } canScroll = true; return onTouchEvent(ev); } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { if (canScrollBack && canScroll) { if (event.getAction() == MotionEvent.ACTION_UP && isScroll) { isScroll = false; canScroll = false; //退出當前Activity if (event.getX() > mWindowWidth / 2) { if (mBeforeActivity != null) { ObjectAnimator.ofFloat(mBeforeActivity.getRootView(), "translationX", mOffsetX, 0).setDuration(500).start(); } ObjectAnimator moveIn = ObjectAnimator.ofFloat(mRootView, "translationX", event.getX(), mWindowWidth); moveIn.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); finish(); } }); moveIn.setDuration(500).start(); //反彈回來 } else if (event.getX() < mWindowWidth / 2) { ObjectAnimator.ofFloat(mRootView, "translationX", event.getX(), 0).setDuration(500).start(); if (mBeforeActivity != null) { ObjectAnimator.ofFloat(mBeforeActivity.getRootView(), "translationX", mOffsetX, mOutsideWidth).setDuration(500).start(); } mOffsetX = mOutsideWidth; } } else { mGestureDetector.onTouchEvent(event); } } return true; } /** * 手勢監(jiān)聽 */ private class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (e1 != null) { handlerCurrentActivityScroll(e2); handleBeforeActivityScroll(e2, distanceX); } return super.onScroll(e1, e2, distanceX, distanceY); } /** * 處理當前頁面滑動 */ private void handlerCurrentActivityScroll(MotionEvent e2) { isScroll = true; mRootView.setTranslationX(e2.getX()); if (e2.getX() > mWindowWidth - 20) { finish(); } } /** * 處理上一個頁面滑動 */ private void handleBeforeActivityScroll(MotionEvent e2, float distanceX) { if (mBeforeActivity != null) { mOffsetX = distanceX < 0 ? mOffsetX + Math.abs(distanceX) / 4 : mOffsetX - Math.abs(distanceX) / 4; if (mOffsetX > 0.0001) { mOffsetX = 0f; } mBeforeActivity.getRootView().setTranslationX(mOffsetX); } } } }
這是我們最終的效果圖
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Android怎么實現(xiàn)微信側滑關閉頁面效果”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業(yè)資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。