Skip to content

Instantly share code, notes, and snippets.

@Audhil
Last active November 27, 2020 17:22
Show Gist options
  • Save Audhil/6df90360880851d42e7749df5c7824ae to your computer and use it in GitHub Desktop.
Save Audhil/6df90360880851d42e7749df5c7824ae to your computer and use it in GitHub Desktop.
A simple activity demonstrating use of a NavHostFragment with a navigation drawer or overflow menu. for ref: https://codelabs.developers.google.com/codelabs/android-navigation/#8 explore for deeplinks with navigations and more src code @ https://drive.google.com/drive/folders/10El0eDzCEL1OnTKlFBXwZfq4XdtukGMA?usp=sharing
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.navigation_activity)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val host: NavHostFragment = supportFragmentManager
.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return
// Set up Action Bar
val navController = host.navController
navController.addOnDestinationChangedListener { _, destination, _ ->
val dest: String = try {
resources.getResourceName(destination.id)
} catch (e: Resources.NotFoundException) {
Integer.toString(destination.id)
}
Toast.makeText(this@MainActivity, "Navigated to $dest",
Toast.LENGTH_SHORT).show()
Log.d("NavigationActivity", "Navigated to $dest")
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.overflow_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return item.onNavDestinationSelected(findNavController(R.id.my_nav_host_fragment))
|| super.onOptionsItemSelected(item)
}
}
resources
phone in portrait mode layout
layout-h470dp/navigation_activity.xml
* res/layout/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" />
<fragment
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" />
... any view
</LinearLayout>
res/menu/overflow_menu.menu
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/settings_dest"
android:icon="@drawable/ic_settings"
android:menuCategory="secondary"
android:title="@string/settings" />
</menu>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.navigation_activity)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val host: NavHostFragment = supportFragmentManager
.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return
// Set up Action Bar
val navController = host.navController
setupBottomNavMenu(navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
val dest: String = try {
resources.getResourceName(destination.id)
} catch (e: Resources.NotFoundException) {
Integer.toString(destination.id)
}
Toast.makeText(this@MainActivity, "Navigated to $dest",
Toast.LENGTH_SHORT).show()
Log.d("NavigationActivity", "Navigated to $dest")
}
}
private fun setupBottomNavMenu(navController: NavController) {
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
bottomNav?.setupWithNavController(navController)
}
}
resources
*
* phone in portrait mode layout
* layout-h470dp/navigation_activity.xml
* res/layout/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" />
<fragment
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>
* res/menu/bo
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/home_dest"
android:icon="@drawable/ic_home"
android:title="@string/home" />
<item
android:id="@id/deeplink_dest"
android:icon="@drawable/ic_android"
android:title="@string/deeplink" />
</menu>
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.navigation_activity)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val host: NavHostFragment = supportFragmentManager
.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return
val navController = host.navController
val drawerLayout: DrawerLayout? = findViewById(R.id.drawer_layout)
// add this to make hamburger icon clickable, if you use return findNavController(R.id.my_nav_host_fragment).navigateUp() at line : 158
// ActionBarDrawerToggle(
// this,
// drawerLayout,
// toolbar,
// R.string.open,
// R.string.close
// )
appBarConfiguration = AppBarConfiguration(setOf(R.id.home_dest, R.id.deeplink_dest), drawerLayout)
// handles, 1. hamburger icon for top-level dest, 2. up icon for other dests
setupActionBar(navController, appBarConfiguration)
setupNavigationMenu(navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
val dest: String = try {
resources.getResourceName(destination.id)
} catch (e: Resources.NotFoundException) {
Integer.toString(destination.id)
}
Toast.makeText(this@MainActivity, "Navigated to $dest",
Toast.LENGTH_SHORT).show()
Log.d("NavigationActivity", "Navigated to $dest")
}
}
private fun setupNavigationMenu(navController: NavController) {
// In split screen mode, you can drag this view out from the left
// This does NOT modify the actionbar
val sideNavView = findViewById<NavigationView>(R.id.nav_view)
sideNavView?.setupWithNavController(navController)
}
private fun setupActionBar(navController: NavController,
appBarConfig: AppBarConfiguration) {
// This allows NavigationUI, it will to decide what label to show in the action bar
// By using appBarConfig also determine whether to
// show the up arrow or drawer menu icon
setupActionBarWithNavController(navController, appBarConfig)
}
// actionbar up btn listener - non-top level dest fragments
override fun onSupportNavigateUp(): Boolean {
// Allows NavigationUI to support proper up navigation or the drawer layout
// drawer menu, depending on the situation
// return findNavController(R.id.my_nav_host_fragment).navigateUp()
return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)
}
}
resources
* view app in split screen to see nav drawer, since we used layout at layout-h470dp/ to support portrait mode
* tablet layout
* res/layout-w960dp/navigation_activity.xml
*
* <?xml version="1.0" encoding="utf-8"?>
<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" />
<fragment
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>
* phone layout
* 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" />
<fragment
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>
* menu is
* <menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/primary">
<item
android:id="@id/home_dest"
android:icon="@drawable/ic_home"
android:title="@string/home" />
<item
android:id="@id/deeplink_dest"
android:icon="@drawable/ic_android"
android:title="@string/deeplink" />
</group>
<item
android:id="@+id/settings_dest"
android:icon="@drawable/ic_settings"
android:title="@string/settings" />
</menu>
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2018 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.
-->
<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"
app:startDestination="@+id/home_dest">
<!-- home-->
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
android:label="@string/home"
tools:layout="@layout/home_fragment">
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_one_dest"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
<!-- step 1-->
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
android:name="flowStepNumber"
android:defaultValue="1"
app:argType="integer" />
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest" />
</fragment>
<!-- step 2-->
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_two_fragment">
<argument
android:name="flowStepNumber"
android:defaultValue="2"
app:argType="integer" />
<action
android:id="@+id/next_action"
app:popUpTo="@id/home_dest" />
</fragment>
<fragment
android:id="@+id/deeplink_dest"
android:name="com.example.android.codelabs.navigation.DeepLinkFragment"
android:label="@string/deeplink"
tools:layout="@layout/deeplink_fragment">
<argument
android:name="myarg"
android:defaultValue="Android!" />
<!-- TODO STEP 11.1 - Add a deep link to www.example.com/{myarg}/ -->
<!--<deepLink app:uri="www.example.com/{myarg}" />-->
<!-- TODO END STEP 11.1 -->
</fragment>
<fragment
android:id="@+id/settings_dest"
android:name="com.example.android.codelabs.navigation.SettingsFragment"
android:label="settings_fragment"
tools:layout="@layout/settings_fragment" />
</navigation>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment