From f796d2a84271ceee501b9702fd7b75ac1004cafa Mon Sep 17 00:00:00 2001 From: tarsin Date: Fri, 13 Jan 2023 10:13:01 +0800 Subject: [PATCH] Tweak NavigationUI to disable multiple backstack and use custom anim --- .../androidx/navigation/ui/NavigationUI.kt | 48 +++++++++++++++++++ .../com/hippo/ehviewer/ui/MainActivity.kt | 24 ++++++++++ 2 files changed, 72 insertions(+) create mode 100644 app/src/main/java/androidx/navigation/ui/NavigationUI.kt diff --git a/app/src/main/java/androidx/navigation/ui/NavigationUI.kt b/app/src/main/java/androidx/navigation/ui/NavigationUI.kt new file mode 100644 index 000000000..326bd38f4 --- /dev/null +++ b/app/src/main/java/androidx/navigation/ui/NavigationUI.kt @@ -0,0 +1,48 @@ +package androidx.navigation.ui + +import android.view.Menu +import android.view.MenuItem +import androidx.annotation.IdRes +import androidx.navigation.ActivityNavigator +import androidx.navigation.NavController +import androidx.navigation.NavDestination +import androidx.navigation.NavDestination.Companion.hierarchy +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavOptions + +fun onNavDestinationSelected2(item: MenuItem, navController: NavController): Boolean { + val builder = NavOptions.Builder().setLaunchSingleTop(true) + if ( + navController.currentDestination!!.parent!!.findNode(item.itemId) + is ActivityNavigator.Destination + ) { + builder.setEnterAnim(R.anim.nav_default_enter_anim) + .setExitAnim(R.anim.nav_default_exit_anim) + .setPopEnterAnim(R.anim.nav_default_pop_enter_anim) + .setPopExitAnim(R.anim.nav_default_pop_exit_anim) + } else { + builder.setEnterAnim(com.hippo.ehviewer.R.anim.scene_open_enter) + .setExitAnim(com.hippo.ehviewer.R.anim.scene_open_exit) + .setPopEnterAnim(com.hippo.ehviewer.R.anim.scene_close_enter) + .setPopExitAnim(com.hippo.ehviewer.R.anim.scene_close_exit) + } + if (item.order and Menu.CATEGORY_SECONDARY == 0) { + builder.setPopUpTo( + navController.graph.findStartDestination().id, + inclusive = false, + saveState = false + ) + } + val options = builder.build() + return try { + // TODO provide proper API instead of using Exceptions as Control-Flow. + navController.navigate(item.itemId, null, options) + // Return true only if the destination we've navigated to matches the MenuItem + navController.currentDestination?.matchDestination(item.itemId) == true + } catch (e: IllegalArgumentException) { + false + } +} + +fun NavDestination.matchDestination(@IdRes destId: Int): Boolean = + hierarchy.any { it.id == destId } \ No newline at end of file diff --git a/app/src/main/java/com/hippo/ehviewer/ui/MainActivity.kt b/app/src/main/java/com/hippo/ehviewer/ui/MainActivity.kt index c07deb56b..89a522247 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/MainActivity.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/MainActivity.kt @@ -34,13 +34,17 @@ import androidx.activity.OnBackPressedCallback import androidx.annotation.RequiresApi import androidx.annotation.StringRes import androidx.core.view.GravityCompat +import androidx.customview.widget.Openable import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout.DrawerListener import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.ui.NavigationUI +import androidx.navigation.ui.onNavDestinationSelected2 import androidx.navigation.ui.setupWithNavController +import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.snackbar.Snackbar import com.hippo.app.BaseDialogBuilder import com.hippo.app.EditTextDialogBuilder @@ -231,6 +235,26 @@ class MainActivity : EhActivity() { } binding.drawView.addDrawerListener(mDrawerOnBackPressedCallback) binding.navView.setupWithNavController(navController) + + // Trick: Tweak NavigationUI to disable multiple backstack + binding.navView.setNavigationItemSelectedListener { + val navigationView = binding.navView + val handled = onNavDestinationSelected2(it, navController) + if (handled) { + val parent = navigationView.parent + if (parent is Openable) { + parent.close() + } else { + val bottomSheetBehavior = NavigationUI.findBottomSheetBehavior(navigationView) + if (bottomSheetBehavior != null) { + bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN + } + } + } + handled + } + // Trick End + if (savedInstanceState == null) { if (intent.action != Intent.ACTION_MAIN) { onNewIntent(intent)