java.lang.Object
↳androidx.navigation.ui.NavigationUI
Overview
Class which hooks up elements typically in the 'chrome' of your application such as global
navigation patterns like a navigation drawer or bottom nav bar with your NavController.
Summary
Methods |
---|
public static boolean | navigateUp(NavController navController, AppBarConfiguration configuration)
Handles the Up button by delegating its behavior to the given NavController. |
public static boolean | navigateUp(NavController navController, Openable openableLayout)
Handles the Up button by delegating its behavior to the given NavController. |
public static boolean | onNavDestinationSelected(MenuItem item, NavController navController)
Attempt to navigate to the NavDestination associated with the given MenuItem. |
public static void | setupActionBarWithNavController(AppCompatActivity activity, NavController navController)
Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar() for use
with a NavController. |
public static void | setupActionBarWithNavController(AppCompatActivity activity, NavController navController, AppBarConfiguration configuration)
Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar() for use
with a NavController. |
public static void | setupActionBarWithNavController(AppCompatActivity activity, NavController navController, Openable openableLayout)
Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar() for use
with a NavController. |
public static void | setupWithNavController(BottomNavigationView bottomNavigationView, NavController navController)
Sets up a for use with a NavController. |
public static void | setupWithNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, NavController navController)
Sets up a and Toolbar for use with a
NavController. |
public static void | setupWithNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, NavController navController, AppBarConfiguration configuration)
Sets up a and Toolbar for use with a
NavController. |
public static void | setupWithNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, NavController navController, Openable openableLayout)
Sets up a and Toolbar for use with a
NavController. |
public static void | setupWithNavController(NavigationView navigationView, NavController navController)
Sets up a for use with a NavController. |
public static void | setupWithNavController(Toolbar toolbar, NavController navController)
Sets up a Toolbar for use with a NavController. |
public static void | setupWithNavController(Toolbar toolbar, NavController navController, AppBarConfiguration configuration)
Sets up a Toolbar for use with a NavController. |
public static void | setupWithNavController(Toolbar toolbar, NavController navController, Openable openableLayout)
Sets up a Toolbar for use with a NavController. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Methods
public static boolean
onNavDestinationSelected(MenuItem item,
NavController navController)
Attempt to navigate to the NavDestination associated with the given MenuItem. This
MenuItem should have been added via one of the helper methods in this class.
Importantly, it assumes the menu item id
matches a valid
action id or
destination id to be navigated to.
By default, the back stack will be popped back to the navigation graph's start destination.
Menu items that have android:menuCategory="secondary"
will not pop the back
stack.
Parameters:
item: The selected MenuItem.
navController: The NavController that hosts the destination.
Returns:
True if the NavController was able to navigate to the destination
associated with the given MenuItem.
Handles the Up button by delegating its behavior to the given NavController. This should
generally be called from AppCompatActivity.onSupportNavigateUp().
If you do not have a Openable layout, you should call
NavController.navigateUp() directly.
Parameters:
navController: The NavController that hosts your content.
openableLayout: The Openable layout that should be opened if you are on the topmost
level of the app.
Returns:
True if the NavController was able to navigate up.
Handles the Up button by delegating its behavior to the given NavController. This is
an alternative to using NavController.navigateUp() directly when the given
AppBarConfiguration needs to be considered when determining what should happen
when the Up button is pressed.
In cases where no Up action is available, the
AppBarConfiguration.getFallbackOnNavigateUpListener() will be called to provide
additional control.
Parameters:
navController: The NavController that hosts your content.
configuration: Additional configuration options for determining what should happen
when the Up button is pressed.
Returns:
True if the NavController was able to navigate up.
Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar() for use
with a NavController.
By calling this method, the title in the action bar will automatically be updated when
the destination changes (assuming there is a valid label).
The start destination of your navigation graph is considered the only top level
destination. On all other destinations, the ActionBar will show the Up button.
Call NavController.navigateUp() to handle the Up button.
Destinations that implement FloatingWindow will be ignored.
Parameters:
activity: The activity hosting the action bar that should be kept in sync with changes
to the NavController.
navController: The NavController that supplies the secondary menu. Navigation actions
on this NavController will be reflected in the title of the action bar.
See also: NavigationUI.setupActionBarWithNavController(AppCompatActivity, NavController, AppBarConfiguration)
Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar() for use
with a NavController.
By calling this method, the title in the action bar will automatically be updated when
the destination changes (assuming there is a valid label).
The start destination of your navigation graph is considered the only top level
destination. On the start destination of your navigation graph, the ActionBar will show
the drawer icon if the given Openable layout is non null. On all other destinations,
the ActionBar will show the Up button.
Call NavigationUI.navigateUp(NavController, Openable) to handle the Up button.
Destinations that implement FloatingWindow will be ignored.
Parameters:
activity: The activity hosting the action bar that should be kept in sync with changes
to the NavController.
navController: The NavController whose navigation actions will be reflected
in the title of the action bar.
openableLayout: The Openable layout that should be toggled from the home button
See also: NavigationUI.setupActionBarWithNavController(AppCompatActivity, NavController, AppBarConfiguration)
Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar() for use
with a NavController.
By calling this method, the title in the action bar will automatically be updated when
the destination changes (assuming there is a valid label).
The AppBarConfiguration you provide controls how the Navigation button is
displayed.
Call NavigationUI.navigateUp(NavController, AppBarConfiguration) to handle the Up button.
Destinations that implement FloatingWindow will be ignored.
Parameters:
activity: The activity hosting the action bar that should be kept in sync with changes
to the NavController.
navController: The NavController whose navigation actions will be reflected
in the title of the action bar.
configuration: Additional configuration options for customizing the behavior of the
ActionBar
Sets up a Toolbar for use with a NavController.
By calling this method, the title in the Toolbar will automatically be updated when
the destination changes (assuming there is a valid label).
The start destination of your navigation graph is considered the only top level
destination. On all other destinations, the Toolbar will show the Up button. This
method will call NavController.navigateUp() when the Navigation button
is clicked.
Destinations that implement FloatingWindow will be ignored.
Parameters:
toolbar: The Toolbar that should be kept in sync with changes to the NavController.
navController: The NavController that supplies the secondary menu. Navigation actions
on this NavController will be reflected in the title of the Toolbar.
See also: NavigationUI.setupWithNavController(Toolbar, NavController, AppBarConfiguration)
Sets up a Toolbar for use with a NavController.
By calling this method, the title in the Toolbar will automatically be updated when
the destination changes (assuming there is a valid label).
The start destination of your navigation graph is considered the only top level
destination. On the start destination of your navigation graph, the Toolbar will show
the drawer icon if the given Openable layout is non null. On all other destinations,
the Toolbar will show the Up button. This method will call
NavigationUI.navigateUp(NavController, Openable) when the Navigation button is clicked.
Destinations that implement FloatingWindow will be ignored.
Parameters:
toolbar: The Toolbar that should be kept in sync with changes to the NavController.
navController: The NavController whose navigation actions will be reflected
in the title of the Toolbar.
openableLayout: The Openable layout that should be toggled from the Navigation button
See also: NavigationUI.setupWithNavController(Toolbar, NavController, AppBarConfiguration)
Sets up a Toolbar for use with a NavController.
By calling this method, the title in the Toolbar will automatically be updated when
the destination changes (assuming there is a valid label).
The AppBarConfiguration you provide controls how the Navigation button is
displayed and what action is triggered when the Navigation button is tapped. This method
will call NavigationUI.navigateUp(NavController, AppBarConfiguration) when the Navigation button
is clicked.
Destinations that implement FloatingWindow will be ignored.
Parameters:
toolbar: The Toolbar that should be kept in sync with changes to the NavController.
navController: The NavController whose navigation actions will be reflected
in the title of the Toolbar.
configuration: Additional configuration options for customizing the behavior of the
Toolbar
public static void
setupWithNavController(CollapsingToolbarLayout collapsingToolbarLayout,
Toolbar toolbar,
NavController navController)
Sets up a and Toolbar for use with a
NavController.
By calling this method, the title in the CollapsingToolbarLayout will automatically be
updated when the destination changes (assuming there is a valid
label).
The start destination of your navigation graph is considered the only top level
destination. On all other destinations, the Toolbar will show the Up button. This
method will call NavController.navigateUp() when the Navigation button
is clicked.
Destinations that implement FloatingWindow will be ignored.
Parameters:
collapsingToolbarLayout: The CollapsingToolbarLayout that should be kept in sync with
changes to the NavController.
toolbar: The Toolbar that should be kept in sync with changes to the NavController.
navController: The NavController that supplies the secondary menu. Navigation actions
on this NavController will be reflected in the title of the Toolbar.
public static void
setupWithNavController(CollapsingToolbarLayout collapsingToolbarLayout,
Toolbar toolbar,
NavController navController,
Openable openableLayout)
Sets up a and Toolbar for use with a
NavController.
By calling this method, the title in the CollapsingToolbarLayout will automatically be
updated when the destination changes (assuming there is a valid
label).
The start destination of your navigation graph is considered the only top level
destination. On the start destination of your navigation graph, the Toolbar will show
the drawer icon if the given Openable layout is non null. On all other destinations,
the Toolbar will show the Up button. This method will call
NavigationUI.navigateUp(NavController, Openable) when the Navigation button is clicked.
Destinations that implement FloatingWindow will be ignored.
Parameters:
collapsingToolbarLayout: The CollapsingToolbarLayout that should be kept in sync with
changes to the NavController.
toolbar: The Toolbar that should be kept in sync with changes to the NavController.
navController: The NavController whose navigation actions will be reflected
in the title of the Toolbar.
openableLayout: The Openable layout that should be toggled from the Navigation button
Sets up a and Toolbar for use with a
NavController.
By calling this method, the title in the CollapsingToolbarLayout will automatically be
updated when the destination changes (assuming there is a valid
label).
The AppBarConfiguration you provide controls how the Navigation button is
displayed and what action is triggered when the Navigation button is tapped. This method
will call NavigationUI.navigateUp(NavController, AppBarConfiguration) when the Navigation button
is clicked.
Destinations that implement FloatingWindow will be ignored.
Parameters:
collapsingToolbarLayout: The CollapsingToolbarLayout that should be kept in sync with
changes to the NavController.
toolbar: The Toolbar that should be kept in sync with changes to the NavController.
navController: The NavController whose navigation actions will be reflected
in the title of the Toolbar.
configuration: Additional configuration options for customizing the behavior of the
Toolbar
public static void
setupWithNavController(NavigationView navigationView,
NavController navController)
Sets up a for use with a NavController. This will call
NavigationUI.onNavDestinationSelected(MenuItem, NavController) when a menu item is selected.
The selected item in the NavigationView will automatically be updated when the destination
changes.
If the is directly contained with an Openable layout,
it will be closed when a menu item is selected.
Similarly, if the has a associated with
it (as is the case when using a ),
the bottom sheet will be hidden when a menu item is selected.
Parameters:
navigationView: The NavigationView that should be kept in sync with changes to the
NavController.
navController: The NavController that supplies the primary and secondary menu.
Navigation actions on this NavController will be reflected in the
selected item in the NavigationView.
public static void
setupWithNavController(BottomNavigationView bottomNavigationView,
NavController navController)
Sets up a for use with a NavController. This will call
NavigationUI.onNavDestinationSelected(MenuItem, NavController) when a menu item is selected. The
selected item in the BottomNavigationView will automatically be updated when the destination
changes.
Parameters:
bottomNavigationView: The BottomNavigationView that should be kept in sync with
changes to the NavController.
navController: The NavController that supplies the primary menu.
Navigation actions on this NavController will be reflected in the
selected item in the BottomNavigationView.
Source
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.navigation.ui;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.customview.widget.Openable;
import androidx.navigation.ActivityNavigator;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.NavGraph;
import androidx.navigation.NavOptions;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.navigation.NavigationView;
import java.lang.ref.WeakReference;
import java.util.Set;
/**
* Class which hooks up elements typically in the 'chrome' of your application such as global
* navigation patterns like a navigation drawer or bottom nav bar with your {@link NavController}.
*/
public final class NavigationUI {
// No instances. Static utilities only.
private NavigationUI() {
}
/**
* Attempt to navigate to the {@link NavDestination} associated with the given MenuItem. This
* MenuItem should have been added via one of the helper methods in this class.
*
* <p>Importantly, it assumes the {@link MenuItem#getItemId() menu item id} matches a valid
* {@link NavDestination#getAction(int) action id} or
* {@link NavDestination#getId() destination id} to be navigated to.</p>
* <p>
* By default, the back stack will be popped back to the navigation graph's start destination.
* Menu items that have <code>android:menuCategory="secondary"</code> will not pop the back
* stack.
*
* @param item The selected MenuItem.
* @param navController The NavController that hosts the destination.
* @return True if the {@link NavController} was able to navigate to the destination
* associated with the given MenuItem.
*/
public static boolean onNavDestinationSelected(@NonNull MenuItem item,
@NonNull NavController navController) {
NavOptions.Builder builder = new NavOptions.Builder()
.setLaunchSingleTop(true);
if (navController.getCurrentDestination().getParent().findNode(item.getItemId())
instanceof 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(R.animator.nav_default_enter_anim)
.setExitAnim(R.animator.nav_default_exit_anim)
.setPopEnterAnim(R.animator.nav_default_pop_enter_anim)
.setPopExitAnim(R.animator.nav_default_pop_exit_anim);
}
if ((item.getOrder() & Menu.CATEGORY_SECONDARY) == 0) {
builder.setPopUpTo(findStartDestination(navController.getGraph()).getId(), false);
}
NavOptions options = builder.build();
try {
//TODO provide proper API instead of using Exceptions as Control-Flow.
navController.navigate(item.getItemId(), null, options);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
/**
* Handles the Up button by delegating its behavior to the given NavController. This should
* generally be called from {@link AppCompatActivity#onSupportNavigateUp()}.
* <p>If you do not have a {@link Openable} layout, you should call
* {@link NavController#navigateUp()} directly.
*
* @param navController The NavController that hosts your content.
* @param openableLayout The Openable layout that should be opened if you are on the topmost
* level of the app.
* @return True if the {@link NavController} was able to navigate up.
*/
public static boolean navigateUp(@NonNull NavController navController,
@Nullable Openable openableLayout) {
return navigateUp(navController, new AppBarConfiguration.Builder(navController.getGraph())
.setOpenableLayout(openableLayout)
.build());
}
/**
* Handles the Up button by delegating its behavior to the given NavController. This is
* an alternative to using {@link NavController#navigateUp()} directly when the given
* {@link AppBarConfiguration} needs to be considered when determining what should happen
* when the Up button is pressed.
* <p>
* In cases where no Up action is available, the
* {@link AppBarConfiguration#getFallbackOnNavigateUpListener()} will be called to provide
* additional control.
*
* @param navController The NavController that hosts your content.
* @param configuration Additional configuration options for determining what should happen
* when the Up button is pressed.
* @return True if the {@link NavController} was able to navigate up.
*/
public static boolean navigateUp(@NonNull NavController navController,
@NonNull AppBarConfiguration configuration) {
Openable openableLayout = configuration.getOpenableLayout();
NavDestination currentDestination = navController.getCurrentDestination();
Set<Integer> topLevelDestinations = configuration.getTopLevelDestinations();
if (openableLayout != null && currentDestination != null
&& matchDestinations(currentDestination, topLevelDestinations)) {
openableLayout.open();
return true;
} else {
if (navController.navigateUp()) {
return true;
} else if (configuration.getFallbackOnNavigateUpListener() != null) {
return configuration.getFallbackOnNavigateUpListener().onNavigateUp();
} else {
return false;
}
}
}
/**
* Sets up the ActionBar returned by {@link AppCompatActivity#getSupportActionBar()} for use
* with a {@link NavController}.
*
* <p>By calling this method, the title in the action bar will automatically be updated when
* the destination changes (assuming there is a valid {@link NavDestination#getLabel label}).
*
* <p>The start destination of your navigation graph is considered the only top level
* destination. On all other destinations, the ActionBar will show the Up button.
* Call {@link NavController#navigateUp()} to handle the Up button.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param activity The activity hosting the action bar that should be kept in sync with changes
* to the NavController.
* @param navController The NavController that supplies the secondary menu. Navigation actions
* on this NavController will be reflected in the title of the action bar.
* @see #setupActionBarWithNavController(AppCompatActivity, NavController, AppBarConfiguration)
*/
public static void setupActionBarWithNavController(@NonNull AppCompatActivity activity,
@NonNull NavController navController) {
setupActionBarWithNavController(activity, navController,
new AppBarConfiguration.Builder(navController.getGraph())
.build());
}
/**
* Sets up the ActionBar returned by {@link AppCompatActivity#getSupportActionBar()} for use
* with a {@link NavController}.
*
* <p>By calling this method, the title in the action bar will automatically be updated when
* the destination changes (assuming there is a valid {@link NavDestination#getLabel label}).
*
* <p>The start destination of your navigation graph is considered the only top level
* destination. On the start destination of your navigation graph, the ActionBar will show
* the drawer icon if the given Openable layout is non null. On all other destinations,
* the ActionBar will show the Up button.
* Call {@link #navigateUp(NavController, Openable)} to handle the Up button.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param activity The activity hosting the action bar that should be kept in sync with changes
* to the NavController.
* @param navController The NavController whose navigation actions will be reflected
* in the title of the action bar.
* @param openableLayout The Openable layout that should be toggled from the home button
* @see #setupActionBarWithNavController(AppCompatActivity, NavController, AppBarConfiguration)
*/
public static void setupActionBarWithNavController(@NonNull AppCompatActivity activity,
@NonNull NavController navController,
@Nullable Openable openableLayout) {
setupActionBarWithNavController(activity, navController,
new AppBarConfiguration.Builder(navController.getGraph())
.setOpenableLayout(openableLayout)
.build());
}
/**
* Sets up the ActionBar returned by {@link AppCompatActivity#getSupportActionBar()} for use
* with a {@link NavController}.
*
* <p>By calling this method, the title in the action bar will automatically be updated when
* the destination changes (assuming there is a valid {@link NavDestination#getLabel label}).
*
* <p>The {@link AppBarConfiguration} you provide controls how the Navigation button is
* displayed.
* Call {@link #navigateUp(NavController, AppBarConfiguration)} to handle the Up button.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param activity The activity hosting the action bar that should be kept in sync with changes
* to the NavController.
* @param navController The NavController whose navigation actions will be reflected
* in the title of the action bar.
* @param configuration Additional configuration options for customizing the behavior of the
* ActionBar
*/
public static void setupActionBarWithNavController(@NonNull AppCompatActivity activity,
@NonNull NavController navController,
@NonNull AppBarConfiguration configuration) {
navController.addOnDestinationChangedListener(
new ActionBarOnDestinationChangedListener(activity, configuration));
}
/**
* Sets up a {@link Toolbar} for use with a {@link NavController}.
*
* <p>By calling this method, the title in the Toolbar will automatically be updated when
* the destination changes (assuming there is a valid {@link NavDestination#getLabel label}).
*
* <p>The start destination of your navigation graph is considered the only top level
* destination. On all other destinations, the Toolbar will show the Up button. This
* method will call {@link NavController#navigateUp()} when the Navigation button
* is clicked.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param toolbar The Toolbar that should be kept in sync with changes to the NavController.
* @param navController The NavController that supplies the secondary menu. Navigation actions
* on this NavController will be reflected in the title of the Toolbar.
* @see #setupWithNavController(Toolbar, NavController, AppBarConfiguration)
*/
public static void setupWithNavController(@NonNull Toolbar toolbar,
@NonNull NavController navController) {
setupWithNavController(toolbar, navController,
new AppBarConfiguration.Builder(navController.getGraph()).build());
}
/**
* Sets up a {@link Toolbar} for use with a {@link NavController}.
*
* <p>By calling this method, the title in the Toolbar will automatically be updated when
* the destination changes (assuming there is a valid {@link NavDestination#getLabel label}).
*
* <p>The start destination of your navigation graph is considered the only top level
* destination. On the start destination of your navigation graph, the Toolbar will show
* the drawer icon if the given Openable layout is non null. On all other destinations,
* the Toolbar will show the Up button. This method will call
* {@link #navigateUp(NavController, Openable)} when the Navigation button is clicked.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param toolbar The Toolbar that should be kept in sync with changes to the NavController.
* @param navController The NavController whose navigation actions will be reflected
* in the title of the Toolbar.
* @param openableLayout The Openable layout that should be toggled from the Navigation button
* @see #setupWithNavController(Toolbar, NavController, AppBarConfiguration)
*/
public static void setupWithNavController(@NonNull Toolbar toolbar,
@NonNull final NavController navController,
@Nullable final Openable openableLayout) {
setupWithNavController(toolbar, navController,
new AppBarConfiguration.Builder(navController.getGraph())
.setOpenableLayout(openableLayout)
.build());
}
/**
* Sets up a {@link Toolbar} for use with a {@link NavController}.
*
* <p>By calling this method, the title in the Toolbar will automatically be updated when
* the destination changes (assuming there is a valid {@link NavDestination#getLabel label}).
*
* <p>The {@link AppBarConfiguration} you provide controls how the Navigation button is
* displayed and what action is triggered when the Navigation button is tapped. This method
* will call {@link #navigateUp(NavController, AppBarConfiguration)} when the Navigation button
* is clicked.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param toolbar The Toolbar that should be kept in sync with changes to the NavController.
* @param navController The NavController whose navigation actions will be reflected
* in the title of the Toolbar.
* @param configuration Additional configuration options for customizing the behavior of the
* Toolbar
*/
public static void setupWithNavController(@NonNull Toolbar toolbar,
@NonNull final NavController navController,
@NonNull final AppBarConfiguration configuration) {
navController.addOnDestinationChangedListener(
new ToolbarOnDestinationChangedListener(toolbar, configuration));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navigateUp(navController, configuration);
}
});
}
/**
* Sets up a {@link CollapsingToolbarLayout} and {@link Toolbar} for use with a
* {@link NavController}.
*
* <p>By calling this method, the title in the CollapsingToolbarLayout will automatically be
* updated when the destination changes (assuming there is a valid
* {@link NavDestination#getLabel label}).
*
* <p>The start destination of your navigation graph is considered the only top level
* destination. On all other destinations, the Toolbar will show the Up button. This
* method will call {@link NavController#navigateUp()} when the Navigation button
* is clicked.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param collapsingToolbarLayout The CollapsingToolbarLayout that should be kept in sync with
* changes to the NavController.
* @param toolbar The Toolbar that should be kept in sync with changes to the NavController.
* @param navController The NavController that supplies the secondary menu. Navigation actions
* on this NavController will be reflected in the title of the Toolbar.
*/
public static void setupWithNavController(
@NonNull CollapsingToolbarLayout collapsingToolbarLayout,
@NonNull Toolbar toolbar,
@NonNull NavController navController) {
setupWithNavController(collapsingToolbarLayout, toolbar, navController,
new AppBarConfiguration.Builder(navController.getGraph()).build());
}
/**
* Sets up a {@link CollapsingToolbarLayout} and {@link Toolbar} for use with a
* {@link NavController}.
*
* <p>By calling this method, the title in the CollapsingToolbarLayout will automatically be
* updated when the destination changes (assuming there is a valid
* {@link NavDestination#getLabel label}).
*
* <p>The start destination of your navigation graph is considered the only top level
* destination. On the start destination of your navigation graph, the Toolbar will show
* the drawer icon if the given Openable layout is non null. On all other destinations,
* the Toolbar will show the Up button. This method will call
* {@link #navigateUp(NavController, Openable)} when the Navigation button is clicked.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param collapsingToolbarLayout The CollapsingToolbarLayout that should be kept in sync with
* changes to the NavController.
* @param toolbar The Toolbar that should be kept in sync with changes to the NavController.
* @param navController The NavController whose navigation actions will be reflected
* in the title of the Toolbar.
* @param openableLayout The Openable layout that should be toggled from the Navigation button
*/
public static void setupWithNavController(
@NonNull CollapsingToolbarLayout collapsingToolbarLayout,
@NonNull Toolbar toolbar,
@NonNull final NavController navController,
@Nullable final Openable openableLayout) {
setupWithNavController(collapsingToolbarLayout, toolbar, navController,
new AppBarConfiguration.Builder(navController.getGraph())
.setOpenableLayout(openableLayout)
.build());
}
/**
* Sets up a {@link CollapsingToolbarLayout} and {@link Toolbar} for use with a
* {@link NavController}.
*
* <p>By calling this method, the title in the CollapsingToolbarLayout will automatically be
* updated when the destination changes (assuming there is a valid
* {@link NavDestination#getLabel label}).
*
* <p>The {@link AppBarConfiguration} you provide controls how the Navigation button is
* displayed and what action is triggered when the Navigation button is tapped. This method
* will call {@link #navigateUp(NavController, AppBarConfiguration)} when the Navigation button
* is clicked.
*
* <p>Destinations that implement {@link androidx.navigation.FloatingWindow} will be ignored.
*
* @param collapsingToolbarLayout The CollapsingToolbarLayout that should be kept in sync with
* changes to the NavController.
* @param toolbar The Toolbar that should be kept in sync with changes to the NavController.
* @param navController The NavController whose navigation actions will be reflected
* in the title of the Toolbar.
* @param configuration Additional configuration options for customizing the behavior of the
* Toolbar
*/
public static void setupWithNavController(
@NonNull CollapsingToolbarLayout collapsingToolbarLayout,
@NonNull Toolbar toolbar,
@NonNull final NavController navController,
@NonNull final AppBarConfiguration configuration) {
navController.addOnDestinationChangedListener(
new CollapsingToolbarOnDestinationChangedListener(
collapsingToolbarLayout, toolbar, configuration));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
navigateUp(navController, configuration);
}
});
}
/**
* Sets up a {@link NavigationView} for use with a {@link NavController}. This will call
* {@link #onNavDestinationSelected(MenuItem, NavController)} when a menu item is selected.
* The selected item in the NavigationView will automatically be updated when the destination
* changes.
* <p>
* If the {@link NavigationView} is directly contained with an {@link Openable} layout,
* it will be closed when a menu item is selected.
* <p>
* Similarly, if the {@link NavigationView} has a {@link BottomSheetBehavior} associated with
* it (as is the case when using a {@link com.google.android.material.bottomsheet.BottomSheetDialog}),
* the bottom sheet will be hidden when a menu item is selected.
*
* @param navigationView The NavigationView that should be kept in sync with changes to the
* NavController.
* @param navController The NavController that supplies the primary and secondary menu.
* Navigation actions on this NavController will be reflected in the
* selected item in the NavigationView.
*/
public static void setupWithNavController(@NonNull final NavigationView navigationView,
@NonNull final NavController navController) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
boolean handled = onNavDestinationSelected(item, navController);
if (handled) {
ViewParent parent = navigationView.getParent();
if (parent instanceof Openable) {
((Openable) parent).close();
} else {
BottomSheetBehavior bottomSheetBehavior =
findBottomSheetBehavior(navigationView);
if (bottomSheetBehavior != null) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
}
}
return handled;
}
});
final WeakReference<NavigationView> weakReference = new WeakReference<>(navigationView);
navController.addOnDestinationChangedListener(
new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController controller,
@NonNull NavDestination destination, @Nullable Bundle arguments) {
NavigationView view = weakReference.get();
if (view == null) {
navController.removeOnDestinationChangedListener(this);
return;
}
Menu menu = view.getMenu();
for (int h = 0, size = menu.size(); h < size; h++) {
MenuItem item = menu.getItem(h);
item.setChecked(matchDestination(destination, item.getItemId()));
}
}
});
}
/**
* Walks up the view hierarchy, trying to determine if the given View is contained within
* a bottom sheet.
*/
@SuppressWarnings("WeakerAccess")
static BottomSheetBehavior findBottomSheetBehavior(@NonNull View view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (!(params instanceof CoordinatorLayout.LayoutParams)) {
ViewParent parent = view.getParent();
if (parent instanceof View) {
return findBottomSheetBehavior((View) parent);
}
return null;
}
CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params)
.getBehavior();
if (!(behavior instanceof BottomSheetBehavior)) {
// We hit a CoordinatorLayout, but the View doesn't have the BottomSheetBehavior
return null;
}
return (BottomSheetBehavior) behavior;
}
/**
* Sets up a {@link BottomNavigationView} for use with a {@link NavController}. This will call
* {@link #onNavDestinationSelected(MenuItem, NavController)} when a menu item is selected. The
* selected item in the BottomNavigationView will automatically be updated when the destination
* changes.
*
* @param bottomNavigationView The BottomNavigationView that should be kept in sync with
* changes to the NavController.
* @param navController The NavController that supplies the primary menu.
* Navigation actions on this NavController will be reflected in the
* selected item in the BottomNavigationView.
*/
public static void setupWithNavController(
@NonNull final BottomNavigationView bottomNavigationView,
@NonNull final NavController navController) {
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
return onNavDestinationSelected(item, navController);
}
});
final WeakReference<BottomNavigationView> weakReference =
new WeakReference<>(bottomNavigationView);
navController.addOnDestinationChangedListener(
new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController controller,
@NonNull NavDestination destination, @Nullable Bundle arguments) {
BottomNavigationView view = weakReference.get();
if (view == null) {
navController.removeOnDestinationChangedListener(this);
return;
}
Menu menu = view.getMenu();
for (int h = 0, size = menu.size(); h < size; h++) {
MenuItem item = menu.getItem(h);
if (matchDestination(destination, item.getItemId())) {
item.setChecked(true);
}
}
}
});
}
/**
* Determines whether the given <code>destId</code> matches the NavDestination. This handles
* both the default case (the destination's id matches the given id) and the nested case where
* the given id is a parent/grandparent/etc of the destination.
*/
@SuppressWarnings("WeakerAccess") /* synthetic access */
static boolean matchDestination(@NonNull NavDestination destination,
@IdRes int destId) {
NavDestination currentDestination = destination;
while (currentDestination.getId() != destId && currentDestination.getParent() != null) {
currentDestination = currentDestination.getParent();
}
return currentDestination.getId() == destId;
}
/**
* Determines whether the given <code>destinationIds</code> match the NavDestination. This
* handles both the default case (the destination's id is in the given ids) and the nested
* case where the given ids is a parent/grandparent/etc of the destination.
*/
@SuppressWarnings("WeakerAccess") /* synthetic access */
static boolean matchDestinations(@NonNull NavDestination destination,
@NonNull Set<Integer> destinationIds) {
NavDestination currentDestination = destination;
do {
if (destinationIds.contains(currentDestination.getId())) {
return true;
}
currentDestination = currentDestination.getParent();
} while (currentDestination != null);
return false;
}
/**
* Finds the actual start destination of the graph, handling cases where the graph's starting
* destination is itself a NavGraph.
*/
@SuppressWarnings("WeakerAccess") /* synthetic access */
static NavDestination findStartDestination(@NonNull NavGraph graph) {
NavDestination startDestination = graph;
while (startDestination instanceof NavGraph) {
NavGraph parent = (NavGraph) startDestination;
startDestination = parent.findNode(parent.getStartDestination());
}
return startDestination;
}
}