Android BottomNavigation is not highlighting properly with Navigation Controller - android

I am trying to implement Nagivation from Android Architecture Components. I am able to navigate successfully across my fragments. I am trying to attach it to my bottom navigation but I am unable to use it properly. I can navigate between fragments successfully with Navigation.findNavController(View).navigate(R.id.Fragment) but when I do that by using any UI component or back button, a highlight from my bottom navigation is not changing as shown in the following gif
My code is as follows for MainActivity.kt,
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
navController.navigate(R.id.homeFragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_dashboard -> {
navController.navigate(R.id.addEmotionFragment)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_notifications -> {
return#OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navController = Navigation.findNavController(this, R.id.nav_host)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
}
For HomeFragment.kt
class HomeFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
button.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.addEmotionFragment)
}
}
}

Try to use navigation-ui.
implementation 'androidx.navigation:navigation-ui:' + navigationVersion //currently 1.0.0-alpha05
in activity
navController = Navigation.findNavController(this, R.id.nav_host)
NavigationUI.setupWithNavController(bottomNavigation, navController)
And make sure your fragment id match menu id.
<item
android:id="#+id/homeFragment"
android:title="Home"/>

You need to manually set a checked property inside your button click like:
button.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.addEmotionFragment)
.... (Over Here)
}
The Java Code would be:
MenuItem menuItem = YourBottomViewObject.getMenu().getItem(1);
menuItemsetChecked(true);
MenuItem menuItem = YourBottomViewObject.getMenu().getItem(0);
menuItemsetChecked(false);

Related

Navigating back to the previous Fragment not working

I'm developing a simple app, with several static screens, just. I get working passing from first fragment, but can't go back to any screen ever.
I saw some videos, like shorturl.at/jFPRY, but in any cases makes work. In my MainActivity I have the OnCreate method, where I save the instance, set the layout, and add a Listener to options on my menu itens.
In the first click, when I open the app, it goes to correct destiny. However, when I click another item it does nothing, stucked. I need to set the Fragments bidirectional, in other words, the user can view any fragment in any moment from any fragment.
My OnCreate method:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.appBarMain.toolbar)
val drawerLayout: DrawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
navView.setNavigationItemSelectedListener {
when (it.itemId) {
R.id.nav_conheca_a_UFTM -> {
supportFragmentManager.beginTransaction()
.replace(R.id.drawer_layout, ConhecaUftmFragment())
.commit()
// Remove the other operations
supportFragmentManager.beginTransaction().addToBackStack(null);
}
R.id.nav_calendario_academico -> {
supportFragmentManager.beginTransaction()
.replace(R.id.drawer_layout, GalleryFragment())
.commit()
// Remove the other operations
supportFragmentManager.beginTransaction().addToBackStack(null);
}
R.id.nav_mural_de_informacoes -> {
supportFragmentManager.beginTransaction()
.replace(R.id.drawer_layout, CalendarioFragment())
.commit()
// Remove the other operations
supportFragmentManager.beginTransaction().addToBackStack(null);
}
}
it.isChecked = true
drawerLayout.closeDrawers()
true
}
supportActionBar?.apply {
setDisplayHomeAsUpEnabled(true)
}
navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main)
val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
NavigationUI.setupWithNavController(binding.appBarMain.toolbar, navController, appBarConfiguration)
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
}
I have also the method onSupportNavigateUp:
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(id.nav_host_fragment_content_main)
return navController.navigateUp()
}
And here is an example of Fragment that I have:
class GalleryFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_calendario_academico, container, false)
/* view.setOnClickListener(){ Navigation.findNavController(view).
navigate(R.id.conhecauftmToaprimorando)
}*/
return view
}
override fun onDestroyView() {
super.onDestroyView()
}
}
I will pass my GitHub link, if anyone can help to fix this issue.
First approach would be to not use FragmentTransactions when you using NavComponent.
If you have the MenuOptions on the MainActivity layout (which I don't recommend, it should go on every fragment, so the MenuOptions are correlated to the current fragment) you can define your navigations in the nav_graph.xml and use them in the MainActivity through NavigationDirections object.
Please visit https://developer.android.com/guide/navigation/navigation-getting-started for more info.
If you want to come back from GalleryFragment to where you have defined the destination of the Popback behaviour, you should call: findNavController.popBackStack()

Jetpack Navigation Drawer always recreates the first fragment even in onBackPress

The title itself is my problem, whenever I open MainActivity then navigate to another fragment available in the hamburger/drawer menu then press/swipe back to return in main screen (first fragment) it recreates. Is there away for Nav Component to make it not recreate the first fragment? I am using the Jetpack Navigation template generated by Android Studio and it seems that is the default behavior.
This is the MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private var _binding: ActivityMainBinding? = null
// This property is only valid between onCreate and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.appBarMain.toolbar)
drawerLayout = binding.drawerLayout
val navView: NavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_content_main)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home, R.id.nav_marketcap, R.id.nav_about), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
menu.findItem(R.id.action_settings).isChecked = AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_main)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
override fun onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START)
else
super.onBackPressed()
}
}
This is the Home Fragment (The first fragment in MainActivity) that holds child fragment AssetFragment
class HomeFragment : Fragment() {
private val homeViewModel: HomeViewModel by activityViewModels()
private var _binding: FragmentHomeBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var viewPager : ViewPager2
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
viewPager = binding.viewPagerContainer
val bottomNav = binding.bottomNav
// val tabLayout = binding.tabLayout
val fragmentList : MutableList<Pair<String, Fragment>> = mutableListOf()
fragmentList.add(Pair(getString(R.string.assets), AssetFragment.newInstance()))
fragmentList.add(Pair(getString(R.string.news), NewsFragment.newInstance()))
fragmentList.add(Pair(getString(R.string.videos), VideosFragment.newInstance()))
val adapter = AppFragmentAdapter(fragmentList, this)
viewPager.adapter = adapter
viewPager.offscreenPageLimit = 2
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
bottomNav.menu.getItem(position).isChecked = true
homeViewModel.setTitle(adapter.getFragmentTabName(position))
}
})
val bottomNavListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when(item.itemId) {
R.id.page_1 -> {
// Respond to navigation item 1 click
viewPager.setCurrentItem(0, true)
true
}
R.id.page_2 -> {
// Respond to navigation item 2 click
viewPager.setCurrentItem(1, true)
true
}
R.id.page_3 -> {
// Respond to navigation item 3 click
viewPager.setCurrentItem(2, true)
true
}
else -> false
}
}
bottomNav.setOnNavigationItemSelectedListener(bottomNavListener)
// val layoutInflater : LayoutInflater = LayoutInflater.from(context)
//Connect TabLayout with ViewPager2
// TabLayoutMediator(tabLayout, viewPager){ tab, position ->
// tab.customView = prepareTabView(layoutInflater, tabLayout, adapter.getFragmentTabName(position), tabIcons[position])
// }.attach()
return root
}
// private fun prepareTabView(
// layoutInflater: LayoutInflater,
// tabLayout: TabLayout,
// fragmentName: String,
// drawableId: Int
// ): View {
//
// val rootView : View = layoutInflater.inflate(R.layout.main_custom_tab_text, tabLayout, false)
//
// val tabName : AppCompatTextView = rootView.findViewById(R.id.tabName)
//
// tabName.text = fragmentName
// tabName.setCompoundDrawablesWithIntrinsicBounds(null, AppCompatResources.getDrawable(requireContext(), drawableId), null, null)
//
// return tabName
//
// }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onResume() {
super.onResume()
requireView().isFocusableInTouchMode = true
requireView().requestFocus()
requireView().setOnKeyListener(object : View.OnKeyListener {
override fun onKey(v: View?, keyCode: Int, event: KeyEvent?): Boolean {
if (event!!.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
onBackPress()
return true
}
return false
}
})
}
fun onBackPress() {
if (viewPager.currentItem != 0)
viewPager.setCurrentItem(0, true)
else
requireActivity().onBackPressed()
}
}
This is one of the child fragment displayed in ViewPager hosted by parent fragment HomeFragment
class AssetFragment : Fragment() {
companion object {
fun newInstance() = AssetFragment()
}
private lateinit var viewModel: AssetViewModel
private var _binding: FragmentAssetsBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
private lateinit var logTxt: AppCompatTextView
private lateinit var recyclerView: RecyclerView
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentAssetsBinding.inflate(inflater, container, false)
val root: View = binding.root
recyclerView = binding.recyclerView
swipeRefreshLayout = binding.refreshLayout
logTxt = binding.errorLog
recyclerView.layoutManager = LinearLayoutManager(context)
adapter = AssetAdapter(requireContext(), this)
recyclerView.adapter = adapter
swipeRefreshLayout.isRefreshing = true
fetchAssets("30")
swipeRefreshLayout.setOnRefreshListener {
swipeRefreshLayout.isRefreshing = true
fetchAssets("30")
}
return root
}
private fun fetchAssets(limit: String) {
//Network stuff
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this).get(AssetViewModel::class.java)
// TODO: Use the ViewModel
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Navigation xml
This are the fragments that will be shown in the drawer menu
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mobile_navigation"
app:startDestination="#+id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="com.myapp.ui.home.HomeFragment"
android:label="#string/home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_marketcap"
android:name="com.myapp.ui.marketcap.MarketCapFragment"
android:label="#string/marketCap"
tools:layout="#layout/fragment_marketcap" />
<fragment
android:id="#+id/nav_about"
android:name="com.myapp.ui.about.AboutFragment"
android:label="#string/about"
tools:layout="#layout/fragment_about" />
</navigation>
The menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item android:title="#string/menu">
<menu>
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_assets"
android:title="#string/home" />
<item
android:id="#+id/nav_marketcap"
android:icon="#drawable/ic_marketcap"
android:title="#string/marketCap" />
<item
android:id="#+id/nav_about"
android:icon="#drawable/ic_about"
android:title="#string/about" />
</menu>
</item>
</group>
<item android:title="#string/connect">
<menu>
<item
android:id="#+id/email_connect"
android:icon="#drawable/ic_email"
android:title="#string/fui_email_hint" />
</menu>
</item>
</menu>
Flow:
Open the app
Launching the MainActivity
Show HomeFragment (AssetFragment)
Open drawer menu
Select item e.g. About (AboutFragment)
Press/Swipe back
Problem here The HomeFragment onCreateView is being triggered once again
Expected behavior HomeFragment will no longer need to inflate view since we just literally make the user back to the very first destination. Unless a user itself press Home item in our drawer menu, that is the time HomeFragment will be recreated.
As per the Saving state with fragments guide, it is expected that your Fragment's view (but not the fragment itself) is destroyed and recreated when it is on the back stack.
As per that guide, one of the types of state is non config state:
NonConfig: data pulled from an external source, such as a server or local repository, or user-created data that is sent to a server once committed.
NonConfig data should be placed outside of your fragment, such as in a ViewModel. The ViewModel class inherently allows data to survive configuration changes, such as screen rotations, and remains in memory when the fragment is placed on the back stack.
So your fragment should never be calling fetchAssets("30") in onCreateView(). Instead, this logic should happen inside a ViewModel such that it is instantly available when the fragment returns from the back stack. As per the ViewModel guide, your fetchAssets should be done inside the ViewModel and your Fragment would observe that data.

Add custom layout to standard Toolbar

I want to add my custom layout to the side of the existing Toolbar, keeping all features with NavigationUI (Up button, animations, placing up buttons and drawers, etc)
How can i achieve this?
After some research i`ve found out the solution
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val navController by lazy { findNavController(R.id.main_nav_host_fragment) }
private val appBarConfiguration by lazy { AppBarConfiguration(navController.graph) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = this.findNavController(R.id.main_nav_host_fragment)
NavigationUI.setupActionBarWithNavController(this, navController)
NavigationUI.setupWithNavController(
findViewById<NavigationView>(R.id.navigation_view),
navController
)
}
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.main_nav_host_fragment)
return NavigationUI.navigateUp(navController, appBarConfiguration)
}
}
FragmentToolbar.kt interface
interface FragmentToolbar {
fun clearActionBar()
fun setCustomActionBar()
}
MainFragment.kt
Next class MainFragment.kt is abstract with methods clearActionBar() and setCustomActionBar() that can be overridden. They are defined in FragmentToolbar.kt interface, because if you set custom layout in first fragment, you will see it also in all other fragments. So, you will almost always have to clear your ActionBar and this class is responsible for standard realisation. setCustomActionBar() is up to you\
abstract class MainFragment : Fragment(), FragmentToolbar {
val actionBar: ActionBar? by lazy { (requireActivity() as AppCompatActivity).supportActionBar }
override fun clearActionBar() {
actionBar?.apply {
setDisplayShowCustomEnabled(false)
setDisplayShowTitleEnabled(true)
}
}
override fun setCustomActionBar() {}
}
MyFragment.kt
class MyFragment : MainFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
clearActionBar() // defined in MainFragment
// Your code
}
override fun setCustomActionBar() {
actionBar?.apply {
setDisplayShowCustomEnabled(true)
setCustomView(R.layout.view_cart_and_bill)
}
actionBar?.customView?.apply { /* Here use findViewById to find necessary views inside your custom layout */ }
}
}
Hope my answer helps you. It also would be great, if ViewBinding could be used with this layout added in runtime, but i have not solved this issue yet

android Navigation controller go back one level

I'm using navigation controller.
I was wondering should I add an additional destination to go back? or there is a builtin call that does that.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_sign_up, container, false).apply {
val navController = NavHostFragment.findNavController(this#SignUpFragment)
this.btnSignUp.setOnClickListener {
navController.navigate(R.id.action_signUpFragment_to_homeActivity)
}
this.btnGotoLogin.setOnClickListener {
navController.navigate(R.id.action_signUpFragment_to_loginFragment)
}
this.back_to_auth_selection.setOnClickListener {
// should I add another action ?
}
}
}
this.back_to_auth_selection.setOnClickListener
{
activity?.onBackPressed()
}
You can also include an Up-button on each fragment other than the home fragment
To do this in main activity`
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// use nav controller to add Up-Button to the app
val navController = this.findNavController(R.id.nav_host_fragment)
// link the navigation controller to the app bar
NavigationUI.setupActionBarWithNavController(this, navController)
}
//override onSupportNavigateUp() to call navigateUp() in the navigation controller
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.nav_host_fragment)
return navController.navigateUp()
}
}`
Sorry my code is in Kotlin

Android kotlin show Navigation Drawer icon instead of Back Button in some fragment

I want to show navigation drawer icon instead of Back button on a certain fragment. I created the App with Navigation graph.
Let's say i have 2 fragments (LoginFragment and DashboardFragment) and one activity (MainActivity)
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
drawerLayout = binding.drawerLayout
val navController = this.findNavController(R.id.myNavHostFragment)
// prevent nav gesture if not on start destination
navController.addOnDestinationChangedListener { nc: NavController, nd: NavDestination, args: Bundle? ->
if (nd.id == nc.graph.startDestination) {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
} else {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
}
}
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
NavigationUI.setupWithNavController(binding.navView, navController)
}
// Set up the back button on action bar
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, drawerLayout)
}
}
LoginFragment.kt
class LoginFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding:FragmentLoginBinding = DataBindingUtil.inflate(inflater,
R.layout.fragment_login, container, false)
// Hide the Action bar
(activity as AppCompatActivity).supportActionBar?.hide()
binding.loginButton.setOnClickListener {
//Some unimportant validation
}
return binding.root
}
}
DashboardFragment.kt
class DashboardFragment : Fragment() {
lateinit var binding : FragmentDashboardBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Binding object for this fragment and the layout
binding = DataBindingUtil.inflate(inflater,
R.layout.fragment_dashboard, container, false)
//Navigate to Product stock fragment when clicked
binding.productStockButton.setOnClickListener(Navigation.createNavigateOnClickListener(
R.id.action_dashboardFragment_to_productStockOutletList
))
//Navigate to Switching History fragment when clicked
binding.switchingHistoryButton.setOnClickListener(Navigation.createNavigateOnClickListener(
R.id.action_dashboardFragment_to_switchingHistoryFragment
))
//Navigate to Outlet List fragment for Outstanding Product when clicked
binding.outstandingOrderButton.setOnClickListener(Navigation.createNavigateOnClickListener(
R.id.action_dashboardFragment_to_outletListFragment
))
// Set action bar title to "Main Dashboard"
(activity as AppCompatActivity).supportActionBar?.title = "Main Dashboard"
// Declare that this fragment has menu
setHasOptionsMenu(true)
(activity as AppCompatActivity).supportActionBar?.show()
(activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(false)
//Return.... i don't know.
return binding.root
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater?.inflate(R.menu.nav_overflow_menu, menu)
}
}
And this is my Navigation graph (I set up LoginFragment as home)
I want to show the navigation drawer in the DashboardFragment instead of LoginFragment. (With LoginFragment still be the start of the graph). I already hide the Up button of the DashboardFragment
This is the current look of the dashboard. As you can see that the back button is already gone.
Is there anything i can do with it ? If there is something unclear let me know.
try this I hope that it will help you, this will hide actionBar on LoginFragment as it's the startDestination on graph and show it otherwise
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// prevent nav gesture if not on start destination
navController.addOnDestinationChangedListener { nc: NavController, nd: NavDestination, args: Bundle? ->
if (nd.id == nc.graph.startDestination) {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
supportActionBar?.hide()
} else {
supportActionBar?.show()
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
}
}
// here this ids are form fragment which should show navigation icon
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home,R.id.nav_gallery, R.id.nav_slideshow), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}

Categories

Resources