Modernize backhandling to support predictive back handling

This commit is contained in:
tzugen 2023-06-05 17:23:48 +02:00
parent bfec814b43
commit bfe24e5dfd
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
4 changed files with 56 additions and 38 deletions

View File

@ -33,6 +33,7 @@
android:supportsRtl="false"
android:preserveLegacyExternalStorage="true"
tools:ignore="UnusedAttribute">
<!-- Add for API 34 android:enableOnBackInvokedCallBack="true" -->
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>

View File

@ -21,6 +21,7 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.ImageView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
@ -51,7 +52,6 @@ import org.moire.ultrasonic.R
import org.moire.ultrasonic.app.UApp
import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.data.ServerSettingDao
import org.moire.ultrasonic.fragment.OnBackPressedHandler
import org.moire.ultrasonic.model.ServerSettingsModel
import org.moire.ultrasonic.provider.SearchSuggestionProvider
import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport
@ -126,6 +126,8 @@ class NavigationActivity : AppCompatActivity() {
navigationView = findViewById(R.id.nav_view)
drawerLayout = findViewById(R.id.drawer_layout)
setupDrawerLayout(drawerLayout!!)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
@ -212,6 +214,27 @@ class NavigationActivity : AppCompatActivity() {
}
}
private fun setupDrawerLayout(drawerLayout: DrawerLayout) {
onBackPressedDispatcher.addCallback(this, closeNavigationDrawerOnBack)
drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
// Nothing
}
override fun onDrawerOpened(drawerView: View) {
closeNavigationDrawerOnBack.isEnabled = true
}
override fun onDrawerClosed(drawerView: View) {
closeNavigationDrawerOnBack.isEnabled = false
}
override fun onDrawerStateChanged(newState: Int) {
// Nothing
}
})
}
override fun onResume() {
Timber.d("onResume called")
super.onResume()
@ -328,15 +351,11 @@ class NavigationActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfig)
}
override fun onBackPressed() {
if (drawerLayout?.isDrawerVisible(GravityCompat.START) == true) {
this.drawerLayout?.closeDrawer(GravityCompat.START)
} else {
val currentFragment = host!!.childFragmentManager.fragments.last()
if (currentFragment is OnBackPressedHandler) currentFragment.onBackPressed()
else super.onBackPressed()
private val closeNavigationDrawerOnBack = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
drawerLayout?.closeDrawer(GravityCompat.START)
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val retValue = super.onCreateOptionsMenu(menu)
@ -352,17 +371,12 @@ class NavigationActivity : AppCompatActivity() {
super.onOptionsItemSelected(item)
}
// TODO: Why is this needed? Shouldn't it just work by default?
override fun onSupportNavigateUp(): Boolean {
val currentFragment = host!!.childFragmentManager.fragments.last()
return if (currentFragment is OnBackPressedHandler) {
currentFragment.onBackPressed()
true
} else {
findNavController(R.id.nav_host_fragment).navigateUp(appBarConfiguration)
}
return findNavController(R.id.nav_host_fragment).navigateUp(appBarConfiguration)
}
// TODO Test if this works with external Intents
// TODO: Test if this works with external Intents
// android.intent.action.SEARCH and android.media.action.MEDIA_PLAY_FROM_SEARCH calls here
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)

View File

@ -7,12 +7,14 @@
package org.moire.ultrasonic.fragment
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
@ -52,7 +54,7 @@ private const val DIALOG_PADDING = 12
/**
* Displays a form where server settings can be created / edited
*/
class EditServerFragment : Fragment(), OnBackPressedHandler {
class EditServerFragment : Fragment() {
private val serverSettingsModel: ServerSettingsModel by viewModel()
private val activeServerProvider: ActiveServerProvider by inject()
@ -82,6 +84,13 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
super.onCreate(savedInstanceState)
}
override fun onAttach(context: Context) {
requireActivity().onBackPressedDispatcher.addCallback(
this, confirmCloseCallback
)
super.onAttach(context)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -189,11 +198,25 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
}
}
private val confirmCloseCallback = object : OnBackPressedCallback(
true // default to enabled
) {
override fun handleOnBackPressed() {
finishActivity()
}
}
override fun onStop() {
Util.hideKeyboard(activity)
confirmCloseCallback.isEnabled = false
super.onStop()
}
override fun onResume() {
confirmCloseCallback.isEnabled = true
super.onResume()
}
private fun correctServerAddress() {
serverAddressEditText?.editText?.setText(
serverAddressEditText?.editText?.text?.trim(' ', '/')
@ -206,11 +229,6 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
image?.setTint(currentColor)
serverColorImageView?.background = image
}
override fun onBackPressed() {
finishActivity()
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
savedInstanceState.putString(
::serverNameEditText.name, serverNameEditText!!.editText?.text.toString()

View File

@ -1,15 +0,0 @@
/*
* OnBackPressedHandler.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.fragment
/**
* Interface for fragments handling their own Back button
*/
interface OnBackPressedHandler {
fun onBackPressed()
}