Merge pull request #1950 from Kruna1Pate1/fix/navigation

Fix navigation and backstack issues
This commit is contained in:
Bnyro 2022-11-21 14:45:51 +01:00 committed by GitHub
commit 3aeca38591
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 33 deletions

View File

@ -17,6 +17,7 @@ import android.view.WindowManager
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.children
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.findNavController import androidx.navigation.findNavController
@ -105,18 +106,16 @@ class MainActivity : BaseActivity() {
binding.bottomNav.setOnApplyWindowInsetsListener(null) binding.bottomNav.setOnApplyWindowInsetsListener(null)
binding.bottomNav.setOnItemSelectedListener { // Prevent duplicate entries into backstack, if selected item and current
// clear backstack if it's the start fragment // visible fragment is different, then navigate to selected item.
if (startFragmentId == it.itemId) navController.backQueue.clear() binding.bottomNav.setOnItemReselectedListener {
if (it.itemId != navController.currentDestination?.id) {
if (it.itemId == R.id.subscriptionsFragment) { navigateToBottomSelectedItem(it)
binding.bottomNav.removeBadge(R.id.subscriptionsFragment) }
} }
removeSearchFocus() binding.bottomNav.setOnItemSelectedListener {
navigateToBottomSelectedItem(it)
// navigate to the selected fragment
navController.navigate(it.itemId)
false false
} }
@ -144,11 +143,18 @@ class MainActivity : BaseActivity() {
} }
} }
if (navController.currentDestination?.id == startFragmentId) { when (navController.currentDestination?.id) {
startFragmentId -> {
moveTaskToBack(true) moveTaskToBack(true)
} else { }
R.id.searchResultFragment -> {
navController.popBackStack(R.id.searchFragment, true) ||
navController.popBackStack() navController.popBackStack()
} }
else -> {
navController.popBackStack()
}
}
} }
}) })
@ -219,23 +225,26 @@ class MainActivity : BaseActivity() {
val searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java] val searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java]
searchView.setOnSearchClickListener {
if (navController.currentDestination?.id != R.id.searchResultFragment) {
searchViewModel.setQuery(null)
navController.navigate(R.id.searchFragment)
}
}
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean { override fun onQueryTextSubmit(query: String?): Boolean {
val bundle = Bundle() val bundle = Bundle()
bundle.putString("query", query) bundle.putString("query", query)
navController.navigate(R.id.searchResultFragment, bundle) navController.navigate(R.id.searchResultFragment, bundle)
searchViewModel.setQuery("") searchViewModel.setQuery("")
searchView.clearFocus()
return true return true
} }
override fun onQueryTextChange(newText: String?): Boolean { override fun onQueryTextChange(newText: String?): Boolean {
// Prevent navigation when search view is collapsed
if (searchView.isIconified ||
binding.bottomNav.menu.children.any {
it.itemId == navController.currentDestination?.id
}
) {
return true
}
// prevent malicious navigation when the search view is getting collapsed // prevent malicious navigation when the search view is getting collapsed
if (navController.currentDestination?.id in listOf( if (navController.currentDestination?.id in listOf(
R.id.searchResultFragment, R.id.searchResultFragment,
@ -258,6 +267,36 @@ class MainActivity : BaseActivity() {
return true return true
} }
}) })
searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
if (navController.currentDestination?.id != R.id.searchResultFragment) {
searchViewModel.setQuery(null)
navController.navigate(R.id.searchFragment)
}
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS or MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW)
return true
}
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
if (binding.mainMotionLayout.progress == 0F) {
try {
minimizePlayer()
} catch (e: Exception) {
// current fragment isn't the player fragment
}
}
// Handover back press to `BackPressedDispatcher`
else if (binding.bottomNav.menu.children.none {
it.itemId == navController.currentDestination?.id
}
) {
this@MainActivity.onBackPressedDispatcher.onBackPressed()
}
return true
}
})
return super.onCreateOptionsMenu(menu) return super.onCreateOptionsMenu(menu)
} }
@ -450,6 +489,26 @@ class MainActivity : BaseActivity() {
} }
} }
private fun navigateToBottomSelectedItem(item: MenuItem) {
// clear backstack if it's the start fragment
if (startFragmentId == item.itemId) navController.backQueue.clear()
if (item.itemId == R.id.subscriptionsFragment) {
binding.bottomNav.removeBadge(R.id.subscriptionsFragment)
}
// navigate to the selected fragment, if the fragment already
// exists in backstack then pop up to that entry
if (!navController.popBackStack(item.itemId, false)) {
navController.navigate(item.itemId)
}
// Remove focus from search view when navigating to bottom view.
// Call only after navigate to destination, so it can be used in
// onMenuItemActionCollapse for backstack management
removeSearchFocus()
}
override fun onUserLeaveHint() { override fun onUserLeaveHint() {
super.onUserLeaveHint() super.onUserLeaveHint()
supportFragmentManager.fragments.forEach { fragment -> supportFragmentManager.fragments.forEach { fragment ->

View File

@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance import com.github.libretube.api.RetrofitInstance
@ -16,7 +15,6 @@ import com.github.libretube.db.DatabaseHelper
import com.github.libretube.db.obj.SearchHistoryItem import com.github.libretube.db.obj.SearchHistoryItem
import com.github.libretube.extensions.TAG import com.github.libretube.extensions.TAG
import com.github.libretube.extensions.hideKeyboard import com.github.libretube.extensions.hideKeyboard
import com.github.libretube.ui.activities.MainActivity
import com.github.libretube.ui.adapters.SearchAdapter import com.github.libretube.ui.adapters.SearchAdapter
import com.github.libretube.ui.base.BaseFragment import com.github.libretube.ui.base.BaseFragment
import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.PreferenceHelper
@ -143,14 +141,4 @@ class SearchResultFragment : BaseFragment() {
) )
} }
} }
override fun onStop() {
if (findNavController().currentDestination?.id != R.id.searchFragment) {
// remove the search focus
(activity as MainActivity)
.binding.toolbar.menu
.findItem(R.id.action_search).collapseActionView()
}
super.onStop()
}
} }