1. 程式人生 > >一行程式碼實現Android右滑返回功能

一行程式碼實現Android右滑返回功能

一行程式碼實現Android右滑返回功能

一、使用方式

首先,匯入andnext_navigation模組。
下載地址:https://github.com/jicanghai37927/WhatsAndroid

其次,在Activity

onCreate()方法中,
setContentView()替換為NavigationHelper.setContentView()
或者
setContentView()之後呼叫NavigationHelper.attach()

執行APP,Activity已經可以右滑返回了。
注:應用的第一個Activity不能右滑返回,需要在第二個Activity以後才能看到效果。

二、設計思路

首先,如何處理使用者的觸控事件來判斷使用者滑動?
2個地方可以處理觸控事件,ActivityViewdispatchTouchEvent()方法。
如果採用Activity的方式,則定義一個基類NavigationActivity來處理使用者觸控事件,並且要求所有支援右滑返回的Activity均繼承自NavigationActivity。
如果採用View的方式,則定義控制元件NavigationLayout,並將NavigationLayout加入到Activity的控制元件結構中。

其次,如何將View插入到Activity的控制元件結構中?
1、通過setContentView()將NavigationLayout加入到控制元件結構中;
2、通過ActivitygetWindow().getDecorView()獲取根控制元件,並新增NavigationLayout;

第三,如何顯示上一個Activity的內容?
2種方法可以顯示上一個Activity的內容。
1、將當前Activity的主題設定為透明,即<item name="android:windowIsTranslucent">false</item>
2、獲取當前Activity的控制元件結構,即this.getWindow().getDecorView()


如果採用的是第2種方式,我們還需要獲取到上一個Activity例項。

第四,如何獲取到上一個Activity例項?
ApplicationActivityLifecycleCallbacks可以幫助我們實現這個功能。

處理完這3個問題,我們可以展示當前及上一個Activity的內容,並且也可以處理觸控事件來實現滑動功能。如何將這些功能串聯到一起?

三、方案過濾

第一、採用ViewdispatchTouchEvent()方式來處理觸控事件。
Activity方式要求所有支援右滑返回的Activity都必須繼承自基類NavigationActivity,侵入性太強,並且可能遇到無法繼承的情況。

第二、採用this.getWindow().getDecorView()方式來顯示上一個Activity內容。
透明主題方式要求每個支援右滑返回的Activity的主題都必須是透明的,侵入性太強,不適合應用於應用內的所有Activity,區域性使用可以考慮。

四、實現過程

第一、實現NavigationLayout處理觸控事件並展示Activity內容。

第二、將NavigationLayout新增到Activity的控制元件結構中。

第三、為NavigationLayout提供上一個Activity的內容。

第四、NavigationLayout右滑結束,關閉當前Activity。

1、實現NavigationLayout

2、新增NavigationLayout

比較ActivityFragmentActivityAppCompatActivity三種Activity的控制元件結構

onCreate()setContentView()後的控制元件結構

com.android.internal.policy.DecorView[-1][子控制元件數 = 1]
android.widget.LinearLayout[-1][子控制元件數 = 2]
android.widget.FrameLayout[16908290][子控制元件數 = 1]

設定的ContentView = android.widget.LinearLayout
com.android.internal.policy.DecorView[-1][子控制元件數 = 1]
android.widget.LinearLayout[-1][子控制元件數 = 2]
android.widget.FrameLayout[16908290][子控制元件數 = 1]

設定的ContentView = android.widget.LinearLayout
com.android.internal.policy.DecorView[-1][子控制元件數 = 1]
android.widget.LinearLayout[-1][子控制元件數 = 2]
android.widget.FrameLayout[-1][子控制元件數 = 1]
androidx.appcompat.widget.ActionBarOverlayLayout[2131230791][子控制元件數 = 2]
androidx.appcompat.widget.ContentFrameLayout[16908290][子控制元件數 = 1]

設定的ContentView = android.widget.LinearLayout

onStop()之後的控制元件結構

android.view.ViewRootImpl
com.android.internal.policy.DecorView[-1][子控制元件數 = 3]
android.widget.LinearLayout[-1][子控制元件數 = 2]
android.widget.FrameLayout[16908290][子控制元件數 = 1]

設定的ContentView = android.widget.LinearLayout
android.view.ViewRootImpl
com.android.internal.policy.DecorView[-1][子控制元件數 = 3]
android.widget.LinearLayout[-1][子控制元件數 = 2]
android.widget.FrameLayout[16908290][子控制元件數 = 1]

設定的ContentView = android.widget.LinearLayout
android.view.ViewRootImpl
com.android.internal.policy.DecorView[-1][子控制元件數 = 3]
android.widget.LinearLayout[-1][子控制元件數 = 2]
android.widget.FrameLayout[-1][子控制元件數 = 1]
androidx.appcompat.widget.ActionBarOverlayLayout[2131230791][子控制元件數 = 2]
androidx.appcompat.widget.ContentFrameLayout[16908290][子控制元件數 = 1]

設定的ContentView = android.widget.LinearLayout

結論:將NavigationLayout新增到DecorView,並且將DecorView的子控制元件移動到Navigation中。

3、獲取上一個Activity

五、參考專案

SwipeBackHelper:https://github.com/Jude95/SwipeBackHelper

SwipeBackLayout:https://github.com/ikew0ng/SwipeBackLayout

and_swipeback:https://github.com/XBeats/and_swipeback