## Responsive UI and navigation

To provide the best possible navigation experience to your users, you should provide a navigation UI that is tailored to the width, height, and smallest-width of the user's device. You may wish to use a[bottom app bar](https://material.io/components/app-bars-bottom/), an always-present or collapsible[navigation drawer](https://material.io/components/navigation-drawer/), a[rail](https://material.io/design/material-studies/reply.html#product-architecture), or perhaps something completely new based on the available screen space and your app's unique style.
![examples of a rail, navigation drawers, and a bottom app bar](https://developer.android.com/static/images/guide/navigation/nav-ui-elements.png)**Figure 1.**Examples of a rail, navigation drawers, and a bottom app bar.

The material design[guide to product architecture](https://material.io/design/material-studies/reply.html#product-architecture)provides additional context and considerations for building a responsive UI---that is, a UI that dynamically adapts to environmental changes. A few examples of environmental changes include adjustments to width, height, orientation, and user language preference. These environmental properties are collectively referred to as the device's*configuration*.

When one or more of these properties change at runtime, the Android OS responds by[destroying and then recreating your app's activities and fragments](https://developer.android.com/guide/topics/resources/runtime-changes). Therefore, the best thing you can do to support a responsive UI on Android is to ensure that you're using[resource configuration qualifiers](https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources)where appropriate and[avoiding the use of hard-coded layout sizes](https://developer.android.com/training/multiscreen/screensizes#TaskUseWrapMatchPar).
| **Note:** To learn more about configuration changes, how to restrict Activity recreation if needed, and how to react to those configuration changes from the View system and Jetpack Compose, check out the[Handle configuration changes](https://developer.android.com/guide/topics/resources/runtime-changes)page.

## Implementing global navigation in a responsive UI

Implementing global navigation as part of a responsive UI starts with the activity that is hosting your navigation graph. For a hands-on example, check out the[Navigation codelab](https://codelabs.developers.google.com/codelabs/android-navigation). The codelab uses a[`NavigationView`](https://developer.android.com/reference/com/google/android/material/navigation/NavigationView)to display the navigation menu, as shown in figure 2. When running on a device that renders at a width of at least 960dp, this`NavigationView`is always on-screen.
![the navigation codelab uses a navigation view that is always visible when device width is at least 960dp](https://developer.android.com/static/images/guide/navigation/omnipresent-navigation-view.png)**Figure 2.** The Navigation codelab uses a`NavigationView`to display the navigation menu.

Other device sizes and orientations dynamically switch between[`DrawerLayout`](https://developer.android.com/reference/androidx/drawerlayout/widget/DrawerLayout)or[`BottomNavigationView`](https://developer.android.com/reference/com/google/android/material/bottomnavigation/BottomNavigationView)as needed.
![a bottomnavigationview and a drawerlayout, used for the navigation menu as needed in smaller device layouts](https://developer.android.com/static/images/guide/navigation/bottom-or-drawer.png)**Figure 3.** The Navigation codelab uses`BottomNavigationView`and`DrawerLayout`to display the navigation menu on smaller devices.

You can implement this behavior by creating three different layouts, where each layout defines the desired navigation elements and view hierarchy based on the current device configuration.

The configuration to which each layout applies is determined by the directory structure in which the layout file is placed. For example, the`NavigationView`layout file is found in the`res/layout-w960dp`directory.  

    <!-- res/layout-w960dp/navigation_activity.xml -->
    <RelativeLayout
       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:layout_width="match_parent"
       android:layout_height="match_parent"
       tools:context="com.example.android.codelabs.navigation.MainActivity">

       <com.google.android.material.navigation.NavigationView
           android:id="@+id/nav_view"
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_alignParentStart="true"
           app:elevation="0dp"
           app:headerLayout="@layout/nav_view_header"
           app:menu="@menu/nav_drawer_menu" />

       <View
           android:layout_width="1dp"
           android:layout_height="match_parent"
           android:layout_toEndOf="@id/nav_view"
           android:background="?android:attr/listDivider" />

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_alignParentTop="true"
           android:layout_toEndOf="@id/nav_view"
           android:background="@color/colorPrimary"
           android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

       <androidx.fragment.app.FragmentContainerView
           android:id="@+id/my_nav_host_fragment"
           android:name="androidx.navigation.fragment.NavHostFragment"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:layout_below="@id/toolbar"
           android:layout_toEndOf="@id/nav_view"
           app:defaultNavHost="true"
           app:navGraph="@navigation/mobile_navigation" />
    </RelativeLayout>

The bottom navigation view is found in the`res/layout-h470dp`directory:  

    <!-- res/layout-h470dp/navigation_activity.xml -->
    <LinearLayout
       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:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       tools:context="com.example.android.codelabs.navigation.MainActivity">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:background="@color/colorPrimary"
           android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

       <androidx.fragment.app.FragmentContainerView
           android:id="@+id/my_nav_host_fragment"
           android:name="androidx.navigation.fragment.NavHostFragment"
           android:layout_width="match_parent"
           android:layout_height="0dp"
           android:layout_weight="1"
           app:defaultNavHost="true"
           app:navGraph="@navigation/mobile_navigation" />

       <com.google.android.material.bottomnavigation.BottomNavigationView
           android:id="@+id/bottom_nav_view"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           app:menu="@menu/bottom_nav_menu" />
    </LinearLayout>

The drawer layout is found in the`res/layout`directory. Use this directory for default layouts with no configuration-specific qualifiers:  

    <!-- res/layout/navigation_activity.xml -->
    <androidx.drawerlayout.widget.DrawerLayout
       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/drawer_layout"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       tools:context="com.example.android.codelabs.navigation.MainActivity">

       <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:orientation="vertical">

           <androidx.appcompat.widget.Toolbar
               android:id="@+id/toolbar"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:background="@color/colorPrimary"
               android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

           <androidx.fragment.app.FragmentContainerView
               android:id="@+id/my_nav_host_fragment"
               android:name="androidx.navigation.fragment.NavHostFragment"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               app:defaultNavHost="true"
               app:navGraph="@navigation/mobile_navigation" />
       </LinearLayout>

       <com.google.android.material.navigation.NavigationView
           android:id="@+id/nav_view"
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_gravity="start"
           app:menu="@menu/nav_drawer_menu" />
    </androidx.drawerlayout.widget.DrawerLayout>

Android follows an[order of precedence](https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources)when determining which resources to apply. Specific to this example,`-w960dp`(or available width \>= 960dp) takes precedence over`-h470dp`(or available height \>= 470). If the device configuration doesn't match either of those conditions, then the default layout resource (`res/layout/navigation_activity.xml`) is used.

In handling navigation events, you need to wire up only the events that correspond to the widgets that are currently present, as shown in the following example.  

### Kotlin

```kotlin
class MainActivity : AppCompatActivity() {

   private lateinit var appBarConfiguration : AppBarConfiguration

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.navigation_activity)
      val drawerLayout : DrawerLayout? = findViewById(R.id.drawer_layout)
      appBarConfiguration = AppBarConfiguration(
                  setOf(R.id.home_dest, R.id.deeplink_dest),
                  drawerLayout)

      ...

      // Initialize the app bar with the navigation drawer if present.
      // If the drawerLayout is not null here, a Navigation button will be added
      // to the app bar whenever the user is on a top-level destination.
      setupActionBarWithNavController(navController, appBarConfig)

      // Initialize the NavigationView if it is present,
      // so that clicking an item takes
      // the user to the appropriate destination.
      val sideNavView = findViewById<NavigationView>(R.id.nav_view)
      sideNavView?.setupWithNavController(navController)

      // Initialize the BottomNavigationView if it is present,
      // so that clicking an item takes
      // the user to the appropriate destination.
      val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
      bottomNav?.setupWithNavController(navController)

      ...
    }

    ...
}
```

### Java

```java
public class MainActivity extends AppCompatActivity {

   private AppBarConfiguration appBarConfiguration;

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.navigation_activity);
       NavHostFragment host = (NavHostFragment) getSupportFragmentManager()
               .findFragmentById(R.id.my_nav_host_fragment);
       NavController navController = host.getNavController();

       DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
       appBarConfiguration = new AppBarConfiguration.Builder(
               R.id.home_dest, R.id.deeplink_dest)
               .setDrawerLayout(drawerLayout)
               .build();

       // Initialize the app bar with the navigation drawer if present.
       // If the drawerLayout is not null here, a Navigation button will be added to
       // the app bar whenever the user is on a top-level destination.
       NavigationUI.setupActionBarWithNavController(
               this, navController, appBarConfiguration);


       // Initialize the NavigationView if it is present,
       // so that clicking an item takes
       // the user to the appropriate destination.
       NavigationView sideNavView = findViewById(R.id.nav_view);
       if(sideNavView != null) {
           NavigationUI.setupWithNavController(sideNavView, navController);
       }

       // Initialize the BottomNavigationView if it is present,
       // so that clicking an item takes
       // the user to the appropriate destination.
       BottomNavigationView bottomNav = findViewById(R.id.bottom_nav_view);
       if(bottomNav != null) {
           NavigationUI.setupWithNavController(bottomNav, navController);
       }

   }
}
```

If the device configuration changes, unless explicitly[configured otherwise](https://developer.android.com/guide/topics/resources/runtime-changes#HandlingTheChange), Android destroys the activity from the previous configuration along with its associated views. It then recreates the activity with resources designed for the new configuration. The activity, being destroyed and recreated, then automatically wires up the proper global navigation elements in`onCreate()`.
| **Note:** While the navigation UI might change, the navigation graph should not change between configurations.`NavHostFragment`saves and restores the current graph state between configuration changes. During the restoration process, all restored destinations are assumed to exist on the current graph.

## Consider alternatives to split-view layouts

Split-view layouts, or*master/detail layouts*, were once a very popular and recommended way to design for tablets and other large screen devices.

Since the introduction of Android tablets, the ecosystem of devices has grown rapidly. One factor that has considerably influenced the design space for large screen devices has been the introduction of multi-window modes, particularly free-form windows that are fully resizable, such as those on ChromeOS devices. This puts a significantly higher emphasis on every screen of your app being responsive, rather than changing your navigation structure based on the screen size.

While it's possible to implement a split-view layout interface using the Navigation library, you should[consider other alternatives](https://medium.com/androiddevelopers/building-a-responsive-ui-in-android-7dc7e4efcbb3).

## Destination names

If you provide destination names in your graph using the`android:label`attribute, be sure to always use resource values so that your content can still be localized.  

    <navigation ...>
        <fragment
            android:id="@+id/my_dest"
            android:name="com.example.MyFragment"
            android:label="@string/my_dest_label"
            tools:layout="@layout/my_fragment" />
        ...

With resource values, your destinations automatically have the most appropriate resources applied whenever your configuration changes.