一行程式碼實現Android右滑返回功能
一行程式碼實現Android右滑返回功能
一、使用方式
首先,匯入andnext_navigation模組。
下載地址:https://github.com/jicanghai37927/WhatsAndroid
其次,在Activity
onCreate()
方法中,將
setContentView()
替換為NavigationHelper.setContentView()
。或者
在
setContentView()
之後呼叫NavigationHelper.attach()
。
執行APP,Activity已經可以右滑返回了。
注:應用的第一個Activity不能右滑返回,需要在第二個Activity以後才能看到效果。
二、設計思路
首先,如何處理使用者的觸控事件來判斷使用者滑動?
2個地方可以處理觸控事件,Activity
和View
的dispatchTouchEvent()
方法。
如果採用Activity
的方式,則定義一個基類NavigationActivity來處理使用者觸控事件,並且要求所有支援右滑返回的Activity均繼承自NavigationActivity。
如果採用View的方式,則定義控制元件NavigationLayout,並將NavigationLayout加入到Activity的控制元件結構中。
其次,如何將View插入到Activity的控制元件結構中?
1、通過setContentView()
將NavigationLayout加入到控制元件結構中;
2、通過Activity
的getWindow().getDecorView()
獲取根控制元件,並新增NavigationLayout;
第三,如何顯示上一個Activity的內容?
2種方法可以顯示上一個Activity的內容。
1、將當前Activity的主題設定為透明,即<item name="android:windowIsTranslucent">false</item>
2、獲取當前Activity的控制元件結構,即this.getWindow().getDecorView()
如果採用的是第2種方式,我們還需要獲取到上一個Activity例項。
第四,如何獲取到上一個Activity例項?
Application
的ActivityLifecycleCallbacks
可以幫助我們實現這個功能。
處理完這3個問題,我們可以展示當前及上一個Activity的內容,並且也可以處理觸控事件來實現滑動功能。如何將這些功能串聯到一起?
三、方案過濾
第一、採用View
的dispatchTouchEvent()
方式來處理觸控事件。
Activity
方式要求所有支援右滑返回的Activity
都必須繼承自基類NavigationActivity,侵入性太強,並且可能遇到無法繼承的情況。
第二、採用this.getWindow().getDecorView()
方式來顯示上一個Activity內容。
透明主題方式要求每個支援右滑返回的Activity的主題都必須是透明的,侵入性太強,不適合應用於應用內的所有Activity,區域性使用可以考慮。
四、實現過程
第一、實現NavigationLayout處理觸控事件並展示Activity內容。
第二、將NavigationLayout新增到Activity的控制元件結構中。
第三、為NavigationLayout提供上一個Activity的內容。
第四、NavigationLayout右滑結束,關閉當前Activity。
1、實現NavigationLayout
2、新增NavigationLayout
比較Activity
、FragmentActivity
、AppCompatActivity
三種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