Android NavGraph android:label"sample tile" not working - android

I am working on adding a toolbar title in the NavGraph. I used android:label"sample tile" in the NavGraph, but its not updating the toolbar with the label.
Tried using android:label in the NavGraph, but its not updating the title of the toolbar.

Using android:label alone won't be fully integrated with jetpack navigation.
In documentation:
NavigationUI contains methods that automatically update content in
your top app bar as users navigate through your app. For example,
NavigationUI uses the destination labels from your navigation graph to
keep the title of the top app bar up-to-date.
So, you need to configure the top app bar to work with NavigationUI and this is done through setupWithNavController().
This section in documentations provides an example:
// Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
...
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(navController.graph)
findViewById<Toolbar>(R.id.toolbar)
.setupWithNavController(navController, appBarConfiguration)
}
// Java
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
...
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
AppBarConfiguration appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()).build();
Toolbar toolbar = findViewById(R.id.toolbar);
NavigationUI.setupWithNavController(
toolbar, navController, appBarConfiguration);
}

Related

androidx navigation api: can we make the menu button always visible?

I have an app that uses the androidx navigation api. it works as expected. but i don't understand why the menu button would change from the hamburger icon to the up arrow, since we have a global one available to us. So, I was wondering if it was possible to force the api to keep the hamburger button at all times. I have found that if you use the following code;
val navSet = setOf(R.id.nav_journal, R.id.nav_copyright)
val drawerLayout: DrawerLayout? = findViewById(R.id.drawer_layout)
appBarConfiguration = AppBarConfiguration(navSet, drawerLayout)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
setupActionBarWithNavController(navController, appBarConfiguration)
then the hamburger icon will appear for both activities but it seems unwieldy to maintain a list of possible navigation activities.
Try this:
navController.addOnDestinationChangedListener { controller, destination, _ ->
if (destination.id == R.id.xxx || destination.id == R.id.xxx || ... ) {
supportActionBar?.setHomeAsUpIndicator(R.drawable.hamburger)
}
}
Find Hamburger icon here: https://materialdesignicons.com/
And add this to each of your other Activity or Fragment:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
requireActivity().drawerLayout.open()
}
return true
}
Try to use setOpenableLayout() to attach the drawerLayout into the appBarConfiguration
This requires to use AppBarConfiguration.Builder pattern:
val appBarConfiguration = AppBarConfiguration.Builder(
R.id.nav_journal, R.id.nav_copyright
).setOpenableLayout(drawerLayout).build()
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController: NavController = navHostFragment.navController
setupActionBarWithNavController(this, navController, appBarConfiguration);
Also make sure you add all the fragments that you don't want to show the up/back button in, into the appBarConfiguration. You already added a couple of them (R.id.nav_journal, R.id.nav_copyright), if you have more fragments in the drawer, then you need to add them as well.

Android: change current content in navigation drawer app, without showing item in drawer menu

I'm a beginner in Android development, and I'd like to create an app with a Navigation Drawer. I started with the default template from the Android Studio 'create project' window.
This is the code from the MainActivity, that sets up the drawer navigation.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_customers, R.id.nav_notes, R.id.nav_stats, R.id.nav_settings)
.setDrawerLayout(drawer)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
I've got a fragment that is the 'customers' page. This page contains a button the user can click on to create a new customer. When that button is clicked, a new page should be opened that takes the input for creating the customer.
This new page should not be a navigation item the user can navigate to directly. The only way and reason to open that page should be by using the 'create customer' button in the customers view I mentioned.
So, that new page should not be included in the menu of the navigation drawer. At the same time, I do want to give this page its own Toolbar.
The two most important things to do, seem to be:
Add a navigation destination / page to the activity. This page should not be included in the navigation drawer's menu. Opening the page should be done programmatically.
The page must have its own Toolbar at the top of the screen.
It seems simple and I tried a lot, but I didn't find any solution so far.
You can check the doc:
Define in your graph something like:
<fragment android:id="#+id/a"
android:name="com.example.myapplication.FragmentA"
android:label="a"
tools:layout="#layout/a">
<action android:id="#+id/action_a_to_b"
app:destination="#id/b"/>
</fragment>
<fragment android:id="#+id/b"
android:name="com.example.myapplication.FragmentB"
android:label="b"
tools:layout="#layout/b">
</fragment>
and then just use to navigate:
findNavController().navigate(R.id.action_a_to_b)
Check also this page:
Adding the top app bar to your activity works well when the app bar’s layout is similar for each destination in your app. If, however, your top app bar changes substantially across destinations, then consider removing the top app bar from your activity and defining it in each destination fragment, instead.
In the FragmentB in the on onCreateView you can inflate your layout
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_B container, false)
In this layout you can put a Toolbar:
<LinearLayout>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
... />
...
</LinearLayout>
and:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navController = findNavController()
val appBarConfiguration = AppBarConfiguration(navController.graph)
view.findViewById<Toolbar>(R.id.toolbar)
.setupWithNavController(navController, appBarConfiguration)
}
The alternative is to setup the navigation in the Activity and use the OnDestinationChangedListener:
navController.addOnDestinationChangedListener { _, destination, _ ->
if(destination.id == R.id.b) {
toolbar.visibility = View.GONE
//....
} else {
toolbar.visibility = View.VISIBLE
//.....
}

Use default back button behavior with android navigation component

I am using a navigation graph in my app. I have a bottom navigation bar. I am staring my navigation components with the following in my Main Activity:
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_artist_list, R.id.navigation_dashboard, R.id.navigation_notifications))
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
This starts my navigation components, which inflate the fragement setup in R.id.navigation_artist_list.
From an observer in that fragment I am navigating to another fragment with:
viewModel.selectedAlbum.observe(this, Observer { artist ->
val action = HomeFragmentDirections.actionNavigationHomeToAlbumFragment(artist)
root.findNavController().navigate(action)
})
However, none of the mechanisms available for navigation work properly. The back button just refreshes the fragment and populates the list in the fragment again. The back button on the action bar is completely ignored.
Do I need to do something else to have the proper back button behavior, to go back to the previous fragment?
In yout MainActivity, override the onSupportNavigateUp() method to call navigateUp() in the navigation controller
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.nav_host_fragment)
return navController.navigateUp()
}

Update actionbar title from child fragment

In my mainactivity I have:
val navController = findNavController(R.id.navhostApp)
val navView = findViewById<NavigationView>(R.id.nvAppDrawer)
drawerLayout = findViewById<DrawerLayout>(R.id.drawerLayout)
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
NavigationUI.setupWithNavController(navView, navController)
I have a navcontroller (drawer style) as my main app navigation, and then in one of the hosted fragments another nav controller for a bottom navigation. I want to have these fragments update the action bar title but the title is only for the container fragment. Is there a way to programmatically get the actionbar to change the title?
I've tried using
requireActivity and actionBar.title but it returns null.
And of course after posting I figure it out.
val actionBar = (requireActivity() as MainActivity).supportActionBar
Then actionBar.title = "Title"

Using Android navigation component with single activiy, layout drawer and toolbars inside fragments

Is it possible to use Android Navigation component/graph in the single activity app in which each fragment has its own toolbar?
Also, container activity has a navigation drawer that needs setup with toolbar and navigation controller, but at the time of activity creation I don't have yet the toolbar.
I am using this code (called in onCreate)
private fun setupNavigation() {
// val toolbar = findViewById<Toolbar>(R.id.toolbar);
// setSupportActionBar(toolbar);
// supportActionBar!!.setDisplayHomeAsUpEnabled(true);
// supportActionBar!!.setDisplayShowHomeEnabled(true);
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout);
val navigationView = findViewById<NavigationView>(R.id.drawer_navigation_view);
val navController = Navigation.findNavController(this, R.id.navigation_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
NavigationUI.setupWithNavController(navigationView, navController)
navigationView.setNavigationItemSelectedListener(this)
}
But since I don't have toolbar at the time it throws an error (ActionBar.setTitle called on a null object).
Is it possible to have this, or I need to drop the idea to use navigation component in this case?
The only requirement is that you call setupActionBarWithNavController after you call setSupportActionBar(). If you're doing that in your Fragment, then just call setupActionBarWithNavController directly after that.
For example, in your Fragment:
private fun onViewCreated(view: View, bundle: savedInstanceState) {
val toolbar = view.findViewById<Toolbar>(R.id.toolbar);
// Set the Toolbar as your activity's ActionBar
requireActivity().setSupportActionBar(toolbar);
// Find the activity's DrawerLayout
val drawerLayout = requireActivity().findViewById<DrawerLayout>(R.id.drawer_layout);
// Find this Fragment's NavController
val navController = NavHostFragment.findNavController(this);
// And set up the ActionBar
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
}
There's also a separate NavigationUI.setupWithNavController() method that takes a Toolbar. This would be appropriate if you aren't actually using any of the other ActionBar APIs.

Categories

Resources