ui: migrate to OnBackPressedDispatcher
This is compatible with Android 13's prediction-based back gesture animation. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
b7295cd56f
commit
cf943b7119
@ -35,6 +35,7 @@
|
||||
android:name=".Application"
|
||||
android:allowBackup="false"
|
||||
android:banner="@mipmap/banner"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
|
@ -9,6 +9,8 @@ import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.addCallback
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
@ -26,27 +28,29 @@ import com.wireguard.android.model.ObservableTunnel
|
||||
class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener {
|
||||
private var actionBar: ActionBar? = null
|
||||
private var isTwoPaneLayout = false
|
||||
private var backPressedCallback: OnBackPressedCallback? = null
|
||||
|
||||
override fun onBackPressed() {
|
||||
private fun handleBackPressed() {
|
||||
val backStackEntries = supportFragmentManager.backStackEntryCount
|
||||
// If the two-pane layout does not have an editor open, going back should exit the app.
|
||||
if (isTwoPaneLayout && backStackEntries <= 1) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
// Deselect the current tunnel on navigating back from the detail pane to the one-pane list.
|
||||
if (!isTwoPaneLayout && backStackEntries == 1) {
|
||||
|
||||
if (backStackEntries >= 1)
|
||||
supportFragmentManager.popBackStack()
|
||||
|
||||
// Deselect the current tunnel on navigating back from the detail pane to the one-pane list.
|
||||
if (backStackEntries == 1)
|
||||
selectedTunnel = null
|
||||
return
|
||||
}
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onBackStackChanged() {
|
||||
val backStackEntries = supportFragmentManager.backStackEntryCount
|
||||
backPressedCallback?.isEnabled = backStackEntries >= 1
|
||||
if (actionBar == null) return
|
||||
// Do not show the home menu when the two-pane layout is at the detail view (see above).
|
||||
val backStackEntries = supportFragmentManager.backStackEntryCount
|
||||
val minBackStackEntries = if (isTwoPaneLayout) 2 else 1
|
||||
actionBar!!.setDisplayHomeAsUpEnabled(backStackEntries >= minBackStackEntries)
|
||||
}
|
||||
@ -57,6 +61,7 @@ class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener
|
||||
actionBar = supportActionBar
|
||||
isTwoPaneLayout = findViewById<View?>(R.id.master_detail_wrapper) != null
|
||||
supportFragmentManager.addOnBackStackChangedListener(this)
|
||||
backPressedCallback = onBackPressedDispatcher.addCallback(this) { handleBackPressed() }
|
||||
onBackStackChanged()
|
||||
}
|
||||
|
||||
@ -69,7 +74,7 @@ class MainActivity : BaseActivity(), FragmentManager.OnBackStackChangedListener
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
// The back arrow in the action bar should act the same as the back button.
|
||||
onBackPressed()
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
true
|
||||
}
|
||||
R.id.menu_action_edit -> {
|
||||
|
@ -16,12 +16,14 @@ import android.os.storage.StorageVolume
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.view.forEach
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.Observable
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import androidx.databinding.ObservableField
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@ -185,6 +187,17 @@ class TvMainActivity : AppCompatActivity() {
|
||||
binding.tunnelList.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
val backPressedCallback = onBackPressedDispatcher.addCallback(this) { handleBackPressed() }
|
||||
val updateBackPressedCallback = object : Observable.OnPropertyChangedCallback() {
|
||||
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
|
||||
backPressedCallback.isEnabled = isDeleting.get() || filesRoot.get()?.isNotEmpty() == true
|
||||
}
|
||||
}
|
||||
isDeleting.addOnPropertyChangedCallback(updateBackPressedCallback)
|
||||
filesRoot.addOnPropertyChangedCallback(updateBackPressedCallback)
|
||||
backPressedCallback.isEnabled = false
|
||||
|
||||
binding.executePendingBindings()
|
||||
setContentView(binding.root)
|
||||
|
||||
@ -298,7 +311,7 @@ class TvMainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
private fun handleBackPressed() {
|
||||
when {
|
||||
isDeleting.get() -> {
|
||||
isDeleting.set(false)
|
||||
@ -313,7 +326,6 @@ class TvMainActivity : AppCompatActivity() {
|
||||
binding.tunnelList.requestFocus()
|
||||
}
|
||||
}
|
||||
else -> super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user