├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── navigation │ │ └── component │ │ └── sample │ │ ├── data │ │ └── MyParcelableDataArgs.kt │ │ └── ui │ │ ├── activity │ │ └── MainActivity.kt │ │ ├── fragments │ │ ├── DeepLinkFragment.kt │ │ ├── MyHomeFragment.kt │ │ ├── MySecondFragment.kt │ │ ├── MyThirdFragment.kt │ │ └── SettingsFragment.kt │ │ └── widget │ │ └── DeepLinkAppWidgetProvider.kt │ └── res │ ├── anim │ ├── fade_in.xml │ ├── fade_out.xml │ ├── slide_in_left.xml │ ├── slide_in_right.xml │ ├── slide_out_left.xml │ └── slide_out_right.xml │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable-xhdpi │ ├── congrats.png │ ├── ic_lets_start.png │ └── wow.png │ ├── drawable │ ├── ic_android.xml │ ├── ic_help.xml │ ├── ic_home.xml │ ├── ic_launcher_background.xml │ ├── ic_settings.xml │ └── ic_shopping_cart_white.xml │ ├── layout-h470dp │ └── navigation_activity.xml │ ├── layout-w960dp │ └── navigation_activity.xml │ ├── layout │ ├── activity_main.xml │ ├── deep_link_appwidget.xml │ ├── deeplink_fragment.xml │ ├── fragment_my_home.xml │ ├── fragment_my_second.xml │ ├── fragment_my_third.xml │ ├── nav_view_header.xml │ ├── navigation_activity.xml │ ├── settings_fragment.xml │ └── shopping_fragment.xml │ ├── menu │ ├── bottom_nav_menu.xml │ ├── main_menu.xml │ ├── nav_drawer_menu.xml │ └── overflow_menu.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── navigation │ └── app_navigation.xml │ ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── deep_link_appwidget_info.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | /.gradle 15 | /.idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NavigationComponentSample 2 | The Navigation Architecture Component simplifies implementing navigation, while also helping you visualize your app's navigation flow. 3 | 4 | ![alt text](https://cdn-images-1.medium.com/max/1200/1*-zvE1oOJwo-LX6Elyrgazg.png) 5 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | apply plugin: "androidx.navigation.safeargs.kotlin" 7 | 8 | def nav_version = "2.1.0-beta01" 9 | def nav_version_ktx = "2.1.0-beta01" 10 | 11 | android { 12 | compileSdkVersion 28 13 | defaultConfig { 14 | applicationId "com.navigation.component.sample" 15 | minSdkVersion 21 16 | targetSdkVersion 28 17 | versionCode 1 18 | versionName "1.0" 19 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 20 | } 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | compileOptions { 28 | sourceCompatibility = 1.8 29 | targetCompatibility = 1.8 30 | } 31 | 32 | kotlinOptions { 33 | jvmTarget = "1.8" 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: 'libs', include: ['*.jar']) 39 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 40 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 41 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 42 | testImplementation 'junit:junit:4.12' 43 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 44 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 45 | // Kotlin 46 | implementation "androidx.navigation:navigation-fragment-ktx:$nav_version_ktx" 47 | implementation "androidx.navigation:navigation-ui-ktx:$nav_version_ktx" 48 | implementation "com.google.android.material:material:$rootProject.materialVersion" 49 | implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion" 50 | implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerVersion" 51 | 52 | implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion" 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/navigation/component/sample/data/MyParcelableDataArgs.kt: -------------------------------------------------------------------------------- 1 | package com.navigation.component.sample.data 2 | 3 | import android.os.Parcel 4 | import android.os.Parcelable 5 | 6 | data class MyParcelableDataArgs(val data1:Int): Parcelable { 7 | var data2: Long=1 8 | var data3: String?=null 9 | var data4: Int=1 10 | 11 | constructor(parcel: Parcel) : this(parcel.readInt()) { 12 | data2 = parcel.readLong() 13 | data3 = parcel.readString() 14 | data4 = parcel.readInt() 15 | } 16 | 17 | override fun writeToParcel(parcel: Parcel, flags: Int) { 18 | parcel.writeInt(data1) 19 | parcel.writeLong(data2) 20 | parcel.writeString(data3) 21 | parcel.writeInt(data4) 22 | } 23 | 24 | override fun describeContents(): Int { 25 | return 0 26 | } 27 | 28 | companion object CREATOR : Parcelable.Creator { 29 | override fun createFromParcel(parcel: Parcel): MyParcelableDataArgs { 30 | return MyParcelableDataArgs(parcel) 31 | } 32 | 33 | override fun newArray(size: Int): Array { 34 | return arrayOfNulls(size) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/navigation/component/sample/ui/activity/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.navigation.component.sample.ui.activity 18 | 19 | import android.content.res.Resources 20 | import android.os.Bundle 21 | import android.util.Log 22 | import android.view.Menu 23 | import android.view.MenuItem 24 | import android.widget.Toast 25 | import androidx.appcompat.app.AppCompatActivity 26 | import androidx.appcompat.widget.Toolbar 27 | import androidx.drawerlayout.widget.DrawerLayout 28 | import androidx.navigation.NavController 29 | import androidx.navigation.findNavController 30 | import androidx.navigation.fragment.NavHostFragment 31 | import androidx.navigation.ui.* 32 | import com.google.android.material.bottomnavigation.BottomNavigationView 33 | import com.google.android.material.navigation.NavigationView 34 | import com.navigation.component.sample.R 35 | 36 | /** 37 | * A simple activity demonstrating use of a NavHostFragment with a navigation drawer. 38 | */ 39 | class MainActivity : AppCompatActivity() { 40 | 41 | private lateinit var appBarConfiguration : AppBarConfiguration 42 | 43 | override fun onCreate(savedInstanceState: Bundle?) { 44 | super.onCreate(savedInstanceState) 45 | setContentView(R.layout.navigation_activity) 46 | 47 | val toolbar = findViewById(R.id.toolbar) 48 | setSupportActionBar(toolbar) 49 | 50 | val host: NavHostFragment = supportFragmentManager 51 | .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return 52 | 53 | // Set up Action Bar 54 | val navController = host.navController 55 | 56 | appBarConfiguration = AppBarConfiguration(navController.graph) 57 | 58 | setupNavigationMenu(navController) 59 | // TODO STEP 9.5 - Create an AppBarConfiguration with the correct top-level destinations 60 | // You should also remove the old appBarConfiguration setup above 61 | val drawerLayout : DrawerLayout? = findViewById(R.id.drawer_layout) 62 | appBarConfiguration = AppBarConfiguration( 63 | setOf(R.id.myHomeFragment, R.id.deepLinkFragment), 64 | drawerLayout) 65 | // TODO END STEP 9.5 66 | 67 | setupActionBar(navController, appBarConfiguration) 68 | 69 | 70 | setupBottomNavMenu(navController) 71 | 72 | navController.addOnDestinationChangedListener { _, destination, _ -> 73 | val dest: String = try { 74 | resources.getResourceName(destination.id) 75 | } catch (e: Resources.NotFoundException) { 76 | Integer.toString(destination.id) 77 | } 78 | 79 | Toast.makeText(this@MainActivity, "Navigated to $dest", 80 | Toast.LENGTH_SHORT).show() 81 | Log.d("NavigationActivity", "Navigated to $dest") 82 | } 83 | } 84 | 85 | private fun setupBottomNavMenu(navController: NavController) { 86 | 87 | // TODO STEP 9.3 - Use NavigationUI to set up Bottom Nav 88 | val bottomNav = findViewById(R.id.bottom_nav_view) 89 | bottomNav?.setupWithNavController(navController) 90 | // TODO END STEP 9.3 91 | } 92 | 93 | private fun setupNavigationMenu(navController: NavController) { 94 | // TODO STEP 9.4 - Use NavigationUI to set up a Navigation View 95 | // // In split screen mode, you can drag this view out from the left 96 | // // This does NOT modify the actionbar 97 | val sideNavView = findViewById(R.id.nav_view) 98 | sideNavView?.setupWithNavController(navController) 99 | // TODO END STEP 9.4 100 | } 101 | 102 | private fun setupActionBar(navController: NavController, 103 | appBarConfig : AppBarConfiguration) { 104 | // TODO STEP 9.6 - Have NavigationUI handle what your ActionBar displays 105 | // // This allows NavigationUI to decide what label to show in the action bar 106 | // // By using appBarConfig, it will also determine whether to 107 | // // show the up arrow or drawer menu icon 108 | setupActionBarWithNavController(navController, appBarConfig) 109 | // TODO END STEP 9.6 110 | } 111 | 112 | override fun onCreateOptionsMenu(menu: Menu): Boolean { 113 | val retValue = super.onCreateOptionsMenu(menu) 114 | val navigationView = findViewById(R.id.nav_view) 115 | // The NavigationView already has these same navigation items, so we only add 116 | // navigation items to the menu here if there isn't a NavigationView 117 | if (navigationView == null) { 118 | menuInflater.inflate(R.menu.overflow_menu, menu) 119 | return true 120 | } 121 | return retValue 122 | } 123 | 124 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 125 | return super.onOptionsItemSelected(item) 126 | // TODO STEP 9.2 - Have Navigation UI Handle the item selection - make sure to delete 127 | // the old return statement above 128 | // // Have the NavigationUI look for an action or destination matching the menu 129 | // // item id and navigate there if found. 130 | // // Otherwise, bubble up to the parent. 131 | return item.onNavDestinationSelected(findNavController(R.id.my_nav_host_fragment)) 132 | || super.onOptionsItemSelected(item) 133 | // TODO END STEP 9.2 134 | } 135 | 136 | // TODO STEP 9.7 - Have NavigationUI handle up behavior in the ActionBar 137 | override fun onSupportNavigateUp(): Boolean { 138 | // Allows NavigationUI to support proper up navigation or the drawer layout 139 | // drawer menu, depending on the situation 140 | return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration) 141 | } 142 | // TODO END STEP 9.7 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/com/navigation/component/sample/ui/fragments/DeepLinkFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.navigation.component.sample.ui.fragments 18 | 19 | import android.app.NotificationChannel 20 | import android.app.NotificationManager 21 | import android.content.Context 22 | import android.os.Build 23 | import android.os.Bundle 24 | import android.view.LayoutInflater 25 | import android.view.View 26 | import android.view.ViewGroup 27 | import android.widget.Button 28 | import android.widget.EditText 29 | import android.widget.TextView 30 | import androidx.core.app.NotificationCompat 31 | import androidx.fragment.app.Fragment 32 | import androidx.navigation.fragment.findNavController 33 | import com.navigation.component.sample.R 34 | 35 | /** 36 | * Fragment used to show how to deep link to a destination 37 | */ 38 | class DeepLinkFragment : Fragment() { 39 | override fun onCreateView( 40 | inflater: LayoutInflater, 41 | container: ViewGroup?, 42 | savedInstanceState: Bundle? 43 | ): View? { 44 | return inflater.inflate(R.layout.deeplink_fragment, container, false) 45 | } 46 | 47 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 48 | super.onViewCreated(view, savedInstanceState) 49 | 50 | val textView = view.findViewById(R.id.text) 51 | textView.text = arguments?.getString("myarg") 52 | 53 | val notificationButton = view.findViewById