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

View File

@ -21,6 +21,7 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -51,7 +52,6 @@ import org.moire.ultrasonic.R
import org.moire.ultrasonic.app.UApp import org.moire.ultrasonic.app.UApp
import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.data.ServerSettingDao import org.moire.ultrasonic.data.ServerSettingDao
import org.moire.ultrasonic.fragment.OnBackPressedHandler
import org.moire.ultrasonic.model.ServerSettingsModel import org.moire.ultrasonic.model.ServerSettingsModel
import org.moire.ultrasonic.provider.SearchSuggestionProvider import org.moire.ultrasonic.provider.SearchSuggestionProvider
import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport import org.moire.ultrasonic.service.MediaPlayerLifecycleSupport
@ -126,6 +126,8 @@ class NavigationActivity : AppCompatActivity() {
navigationView = findViewById(R.id.nav_view) navigationView = findViewById(R.id.nav_view)
drawerLayout = findViewById(R.id.drawer_layout) drawerLayout = findViewById(R.id.drawer_layout)
setupDrawerLayout(drawerLayout!!)
val toolbar = findViewById<Toolbar>(R.id.toolbar) val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(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() { override fun onResume() {
Timber.d("onResume called") Timber.d("onResume called")
super.onResume() super.onResume()
@ -328,13 +351,9 @@ class NavigationActivity : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfig) setupActionBarWithNavController(navController, appBarConfig)
} }
override fun onBackPressed() { private val closeNavigationDrawerOnBack = object : OnBackPressedCallback(true) {
if (drawerLayout?.isDrawerVisible(GravityCompat.START) == true) { override fun handleOnBackPressed() {
this.drawerLayout?.closeDrawer(GravityCompat.START) drawerLayout?.closeDrawer(GravityCompat.START)
} else {
val currentFragment = host!!.childFragmentManager.fragments.last()
if (currentFragment is OnBackPressedHandler) currentFragment.onBackPressed()
else super.onBackPressed()
} }
} }
@ -352,17 +371,12 @@ class NavigationActivity : AppCompatActivity() {
super.onOptionsItemSelected(item) super.onOptionsItemSelected(item)
} }
// TODO: Why is this needed? Shouldn't it just work by default?
override fun onSupportNavigateUp(): Boolean { override fun onSupportNavigateUp(): Boolean {
val currentFragment = host!!.childFragmentManager.fragments.last() return findNavController(R.id.nav_host_fragment).navigateUp(appBarConfiguration)
return if (currentFragment is OnBackPressedHandler) {
currentFragment.onBackPressed()
true
} else {
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 // android.intent.action.SEARCH and android.media.action.MEDIA_PLAY_FROM_SEARCH calls here
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent) super.onNewIntent(intent)

View File

@ -7,12 +7,14 @@
package org.moire.ultrasonic.fragment package org.moire.ultrasonic.fragment
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment 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 * 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 serverSettingsModel: ServerSettingsModel by viewModel()
private val activeServerProvider: ActiveServerProvider by inject() private val activeServerProvider: ActiveServerProvider by inject()
@ -82,6 +84,13 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
} }
override fun onAttach(context: Context) {
requireActivity().onBackPressedDispatcher.addCallback(
this, confirmCloseCallback
)
super.onAttach(context)
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, 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() { override fun onStop() {
Util.hideKeyboard(activity) Util.hideKeyboard(activity)
confirmCloseCallback.isEnabled = false
super.onStop() super.onStop()
} }
override fun onResume() {
confirmCloseCallback.isEnabled = true
super.onResume()
}
private fun correctServerAddress() { private fun correctServerAddress() {
serverAddressEditText?.editText?.setText( serverAddressEditText?.editText?.setText(
serverAddressEditText?.editText?.text?.trim(' ', '/') serverAddressEditText?.editText?.text?.trim(' ', '/')
@ -206,11 +229,6 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
image?.setTint(currentColor) image?.setTint(currentColor)
serverColorImageView?.background = image serverColorImageView?.background = image
} }
override fun onBackPressed() {
finishActivity()
}
override fun onSaveInstanceState(savedInstanceState: Bundle) { override fun onSaveInstanceState(savedInstanceState: Bundle) {
savedInstanceState.putString( savedInstanceState.putString(
::serverNameEditText.name, serverNameEditText!!.editText?.text.toString() ::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()
}