Change Nav testapp's top level based on screen size

Update the Navigation testapp to adapt the top level
navigation pattern based on the available screen size:
- On very small screens (such as is common on phones
with multi-window or phones in landscape), use a
navigation drawer to keep navigation out of the way
but accessible
- When there is enough height (such as normal devices in
portrait), use bottom navigation
- On larger tablets in landscape and Chromebooks, use a
persistent navigation drawer that is always visible to
better use the available space

Test: testapp runs, works on multi-window on phones through Pixel C

BUG: 37573313
Change-Id: Ib78090be4ecc0cd7c7c9eb5010f098b51a8d6c57
diff --git a/navigation/integration-tests/testapp/src/main/AndroidManifest.xml b/navigation/integration-tests/testapp/src/main/AndroidManifest.xml
index 26ee9da..127a240 100644
--- a/navigation/integration-tests/testapp/src/main/AndroidManifest.xml
+++ b/navigation/integration-tests/testapp/src/main/AndroidManifest.xml
@@ -21,16 +21,7 @@
         android:supportsRtl="true"
         android:theme="@style/AppTheme"
         tools:ignore="AllowBackup,GoogleAppIndexingWarning,MissingApplicationIcon">
-        <activity android:name="com.android.support.navigation.testapp.DrawerActivity"
-                  android:label="@string/drawer_navigation">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.DEFAULT"/>
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-        <activity android:name="com.android.support.navigation.testapp.BottomNavActivity"
-                android:label="@string/bottom_navigation">
+        <activity android:name="com.android.support.navigation.testapp.NavigationActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.DEFAULT"/>
diff --git a/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/BottomNavActivity.java b/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/BottomNavActivity.java
deleted file mode 100644
index c1f060d..0000000
--- a/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/BottomNavActivity.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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 com.android.support.navigation.testapp;
-
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.design.widget.BottomNavigationView;
-import android.support.navigation.app.nav.NavController;
-import android.support.navigation.app.nav.NavDestination;
-import android.support.navigation.app.nav.NavHostFragment;
-import android.support.navigation.app.nav.Navigation;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.Toast;
-
-/**
- * A simple activity demonstrating use of a NavHostFragment with a bottom navigation bar.
- */
-public class BottomNavActivity extends AppCompatActivity {
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.bottom_nav_activity);
-
-        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
-        setSupportActionBar(toolbar);
-
-        NavHostFragment host = (NavHostFragment) getSupportFragmentManager()
-                .findFragmentById(R.id.my_nav_host_fragment);
-
-        if (host != null) {
-            NavController navController = host.getNavController();
-            NavHelper.setupActionBar(navController, this);
-            BottomNavigationView bottomNavView =
-                    (BottomNavigationView) findViewById(R.id.bottom_nav_view);
-            NavHelper.setupBottomNavigationView(navController, bottomNavView);
-            navController.addOnNavigatedListener(new NavController.OnNavigatedListener() {
-                @Override
-                public void onNavigated(NavController controller, NavDestination destination) {
-                    String dest = getResources().getResourceName(destination.getId());
-                    Toast.makeText(BottomNavActivity.this, "Navigated to "
-                            + dest,
-                            Toast.LENGTH_SHORT).show();
-                    Log.d("BottomNavActivity", "Navigated to " + dest, new Throwable());
-                }
-            });
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        NavController navController = Navigation.findController(this, R.id.my_nav_host_fragment);
-        NavHelper.addChildDestinationsToMenu(navController.getGraph(), menu,
-                NavDestination.NAV_TYPE_SECONDARY);
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        return NavHelper.handleMenuItemSelected(
-                Navigation.findController(this, R.id.my_nav_host_fragment), item)
-                || super.onOptionsItemSelected(item);
-    }
-}
diff --git a/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavHelper.java b/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavHelper.java
index a920dd1..7fb9584 100644
--- a/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavHelper.java
+++ b/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavHelper.java
@@ -213,22 +213,8 @@
      */
     public static void setupActionBar(final NavController navController,
             final AppCompatActivity activity, final DrawerLayout drawerLayout) {
-        ActionBar actionBar = activity.getSupportActionBar();
-        NavDestination currentDestination = navController.getCurrentDestination();
-        if (currentDestination != null && !TextUtils.isEmpty(currentDestination.getLabel())) {
-            actionBar.setTitle(currentDestination.getLabel());
-        }
-        ActionBarOnNavigatedListener actionBarOnNavigatedListener =
-                new ActionBarOnNavigatedListener(activity, drawerLayout);
-        navController.addOnNavigatedListener(actionBarOnNavigatedListener);
-        boolean isStartDestination = currentDestination == null
-                || currentDestination.getId() == navController.getGraph().getStartDestination();
-        actionBar.setDisplayHomeAsUpEnabled(drawerLayout != null || !isStartDestination);
-        // Set the initial state of the up indicator: it should show as the drawer indicator
-        // if there is a DrawerLayout and we're on the starting destination, otherwise it should
-        // show as an Up arrow.
-        actionBarOnNavigatedListener.setActionBarUpIndicator(
-                drawerLayout != null && isStartDestination, false);
+        navController.addOnNavigatedListener(
+                new ActionBarOnNavigatedListener(activity, drawerLayout));
     }
 
     /**
@@ -266,6 +252,9 @@
     public static void setupNavigationView(final NavController navController,
             final NavigationView navigationView,
             final NavigationView.OnNavigationItemSelectedListener listener) {
+        if (navigationView == null) {
+            return;
+        }
         addChildDestinationsToMenu(navController.getGraph(), navigationView.getMenu(),
                 NavDestination.NAV_TYPE_PRIMARY | NavDestination.NAV_TYPE_SECONDARY);
         navigationView.setNavigationItemSelectedListener(
@@ -330,6 +319,9 @@
     public static void setupBottomNavigationView(final NavController navController,
             final BottomNavigationView bottomNavigationView,
             final BottomNavigationView.OnNavigationItemSelectedListener listener) {
+        if (bottomNavigationView == null) {
+            return;
+        }
         addChildDestinationsToMenu(navController.getGraph(), bottomNavigationView.getMenu(),
                 NavDestination.NAV_TYPE_PRIMARY);
         bottomNavigationView.setOnNavigationItemSelectedListener(
@@ -381,15 +373,18 @@
             boolean isStartDestination =
                     controller.getGraph().getStartDestination() == destination.getId();
             actionBar.setDisplayHomeAsUpEnabled(mDrawerLayout != null || !isStartDestination);
-            setActionBarUpIndicator(mDrawerLayout != null && isStartDestination, true);
+            setActionBarUpIndicator(mDrawerLayout != null && isStartDestination);
         }
 
-        void setActionBarUpIndicator(boolean showAsDrawerIndicator, boolean animate) {
+        void setActionBarUpIndicator(boolean showAsDrawerIndicator) {
             ActionBarDrawerToggle.Delegate delegate = mActivity.getDrawerToggleDelegate();
+            boolean animate = true;
             if (mArrowDrawable == null) {
                 mArrowDrawable = new DrawerArrowDrawable(
                         delegate.getActionBarThemedContext());
                 delegate.setActionBarUpIndicator(mArrowDrawable, 0);
+                // We're setting the initial state, so skip the animation
+                animate = false;
             }
             float endValue = showAsDrawerIndicator ? 0f : 1f;
             if (animate) {
diff --git a/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/DrawerActivity.java b/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavigationActivity.java
similarity index 69%
rename from navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/DrawerActivity.java
rename to navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavigationActivity.java
index c4d2f4a..0505325 100644
--- a/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/DrawerActivity.java
+++ b/navigation/integration-tests/testapp/src/main/java/com/android/support/navigation/testapp/NavigationActivity.java
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.design.widget.BottomNavigationView;
 import android.support.design.widget.NavigationView;
 import android.support.navigation.app.nav.NavController;
 import android.support.navigation.app.nav.NavDestination;
@@ -27,19 +28,20 @@
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
 import android.util.Log;
+import android.view.Menu;
 import android.view.MenuItem;
 import android.widget.Toast;
 
 /**
  * A simple activity demonstrating use of a NavHostFragment with a navigation drawer.
  */
-public class DrawerActivity extends AppCompatActivity {
+public class NavigationActivity extends AppCompatActivity {
     private DrawerLayout mDrawerLayout;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.drawer_activity);
+        setContentView(R.layout.navigation_activity);
 
         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
@@ -53,20 +55,39 @@
             NavHelper.setupActionBar(navController, this, mDrawerLayout);
             NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
             NavHelper.setupNavigationView(navController, navigationView);
+            BottomNavigationView bottomNavView =
+                    (BottomNavigationView) findViewById(R.id.bottom_nav_view);
+            NavHelper.setupBottomNavigationView(navController, bottomNavView);
             navController.addOnNavigatedListener(new NavController.OnNavigatedListener() {
                 @Override
                 public void onNavigated(NavController controller, NavDestination destination) {
                     String dest = getResources().getResourceName(destination.getId());
-                    Toast.makeText(DrawerActivity.this, "Navigated to "
+                    Toast.makeText(NavigationActivity.this, "Navigated to "
                             + dest,
                             Toast.LENGTH_SHORT).show();
-                    Log.d("DrawerActivity", "Navigated to " + dest, new Throwable());
+                    Log.d("NavigationActivity", "Navigated to " + dest, new Throwable());
                 }
             });
         }
     }
 
     @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        boolean retValue = super.onCreateOptionsMenu(menu);
+        BottomNavigationView bottomNavView =
+                (BottomNavigationView) findViewById(R.id.bottom_nav_view);
+        // Only add secondary navigation elements to the menu if there is a BottomNavigationView
+        if (bottomNavView != null) {
+            NavController navController =
+                    Navigation.findController(this, R.id.my_nav_host_fragment);
+            NavHelper.addChildDestinationsToMenu(navController.getGraph(), menu,
+                    NavDestination.NAV_TYPE_SECONDARY);
+            return true;
+        }
+        return retValue;
+    }
+
+    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         return NavHelper.handleMenuItemSelected(
                 Navigation.findController(this, R.id.my_nav_host_fragment), item, mDrawerLayout)
diff --git a/navigation/integration-tests/testapp/src/main/res/layout/bottom_nav_activity.xml b/navigation/integration-tests/testapp/src/main/res/layout-h470dp/navigation_activity.xml
similarity index 98%
rename from navigation/integration-tests/testapp/src/main/res/layout/bottom_nav_activity.xml
rename to navigation/integration-tests/testapp/src/main/res/layout-h470dp/navigation_activity.xml
index 9bb1441..54eecb0 100644
--- a/navigation/integration-tests/testapp/src/main/res/layout/bottom_nav_activity.xml
+++ b/navigation/integration-tests/testapp/src/main/res/layout-h470dp/navigation_activity.xml
@@ -1,10 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
   ~ 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.
diff --git a/navigation/integration-tests/testapp/src/main/res/layout-w960dp/navigation_activity.xml b/navigation/integration-tests/testapp/src/main/res/layout-w960dp/navigation_activity.xml
new file mode 100644
index 0000000..203889a
--- /dev/null
+++ b/navigation/integration-tests/testapp/src/main/res/layout-w960dp/navigation_activity.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <android.support.design.widget.NavigationView
+        android:id="@+id/nav_view"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
+        app:elevation="0dp"
+        app:headerLayout="@layout/nav_view_header"/>
+    <View
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        android:layout_toRightOf="@id/nav_view"
+        android:layout_toEndOf="@id/nav_view"
+        android:background="?android:attr/listDivider"/>
+    <android.support.v7.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/colorPrimary"
+        android:theme="@style/ThemeOverlay.AppCompat.Dark"
+        android:layout_toRightOf="@id/nav_view"
+        android:layout_toEndOf="@id/nav_view"
+        android:layout_alignParentTop="true"/>
+    <fragment
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/my_nav_host_fragment"
+        android:name="android.support.navigation.app.nav.NavHostFragment"
+        app:navGraph="@xml/nav_main"
+        app:defaultNavHost="true"
+        android:layout_toRightOf="@id/nav_view"
+        android:layout_toEndOf="@id/nav_view"
+        android:layout_below="@id/toolbar"/>
+</RelativeLayout>
diff --git a/navigation/integration-tests/testapp/src/main/res/layout/main_fragment.xml b/navigation/integration-tests/testapp/src/main/res/layout/main_fragment.xml
index e7f7060..9f797c9 100644
--- a/navigation/integration-tests/testapp/src/main/res/layout/main_fragment.xml
+++ b/navigation/integration-tests/testapp/src/main/res/layout/main_fragment.xml
@@ -13,7 +13,8 @@
   -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical" android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:padding="8dp">
     <TextView android:id="@+id/text"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/navigation/integration-tests/testapp/src/main/res/layout/nav_view_header.xml b/navigation/integration-tests/testapp/src/main/res/layout/nav_view_header.xml
new file mode 100644
index 0000000..d7be09f
--- /dev/null
+++ b/navigation/integration-tests/testapp/src/main/res/layout/nav_view_header.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="?attr/actionBarSize">
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:layout_gravity="bottom"
+        android:background="?android:attr/listDivider"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/navigation/integration-tests/testapp/src/main/res/layout/drawer_activity.xml b/navigation/integration-tests/testapp/src/main/res/layout/navigation_activity.xml
similarity index 100%
rename from navigation/integration-tests/testapp/src/main/res/layout/drawer_activity.xml
rename to navigation/integration-tests/testapp/src/main/res/layout/navigation_activity.xml
diff --git a/navigation/runtime/src/main/java/android/support/navigation/app/nav/NavController.java b/navigation/runtime/src/main/java/android/support/navigation/app/nav/NavController.java
index 377b732..cddbdc2 100644
--- a/navigation/runtime/src/main/java/android/support/navigation/app/nav/NavController.java
+++ b/navigation/runtime/src/main/java/android/support/navigation/app/nav/NavController.java
@@ -150,9 +150,15 @@
      * Adds an {@link OnNavigatedListener} to this controller to receive events when
      * the controller navigates to a new destination.
      *
+     * <p>The current destination, if any, will be immediately sent to your listener.</p>
+     *
      * @param listener the listener to receive events
      */
     public void addOnNavigatedListener(OnNavigatedListener listener) {
+        // Inform the new listener of our current state, if any
+        if (!mBackStack.isEmpty()) {
+            listener.onNavigated(this, mBackStack.peekLast());
+        }
         mOnNavigatedListeners.add(listener);
     }