Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Navigation Architecture Component 入門 / shibuya....
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
star_zero
December 13, 2018
Programming
790
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Navigation Architecture Component 入門 / shibuya.apk #30
star_zero
December 13, 2018
More Decks by star_zero
See All by star_zero
今からはじめるAndroidアプリ開発 2024 / DevFest 2024
star_zero
0
1.7k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
7.3k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
700
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
520
Coroutines Test 入門 / Android Test Night #8
star_zero
2
1.4k
What's new in Jetpack / I/O Extended Japan 2022
star_zero
1
730
Kotlin 2021 Recap / DevFest 2021
star_zero
3
1.4k
Kotlin Symbol Processing (KSP) を使ったコード生成 / DroidKaigi 2021
star_zero
2
5.3k
What's new Android 12
star_zero
0
640
Other Decks in Programming
See All in Programming
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
1k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
150
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
5.1k
すこし踏み込む CancellationToken
htkym
2
1.7k
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
290
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
160
R8 の設定見直しでアプリサイズ削減
andpad
0
220
IBM Bob でAI駆動開発『QC-Playbook』
ichirokano2
0
110
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
phperだってパンチカードでコーディングしたい
o0h
PRO
0
330
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
Featured
See All Featured
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Agile that works and the tools we love
rasmusluckow
331
22k
Ruling the World: When Life Gets Gamed
codingconduct
0
400
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Design in an AI World
tapps
1
350
GitHub's CSS Performance
jonrohan
1033
470k
Deep Space Network (abreviated)
tonyrice
0
370
Producing Creativity
orderedlist
PRO
348
41k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.9k
Transcript
Navigation Architecture Component 入門 shibuya.apk #30
About Me • Kenji Abe • Cookpad Inc. • Android
Developer • Twitter: @STAR_ZERO
Navigation Architecture Component
⚠注意⚠ まだ alpha08
Navigation Architecture Component • XMLで画面遷移を定義できる • Android StudioでGUIが使える • 引数も定義できる
(SafeArgs) • DeepLinkできる • Shared Element Transitionsできる • カスタマイズできる
Navigation Architecture Component • 基本は Fragment -> Fragment • Fragment
-> Activityはできる • Activity -> Activityは簡単にはできない (できないことはない)
基本的な使い方
build.gradle // build.gradle buildscript { dependencies { classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0- alpha08"
} } // app/build.gradle apply plugin: "androidx.navigation.safeargs" dependencies { implementation "android.arch.navigation:navigation-fragment-ktx:1.0.0-alpha08" implementation "android.arch.navigation:navigation-ui-ktx:1.0.0-alpha08" }
Navigation Graph (Navigation Editor) res/navigation/nav_graph.xml
Navigation Graph (XML) <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph"
app:startDestination="@id/firstFragment"> <fragment android:id="@+id/firstFragment" android:name="com.star_zero.samplenavigation.FirstFragment" android:label="FirstFragment"> <action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" /> </fragment> <fragment android:id="@+id/secondFragment" android:name="com.star_zero.samplenavigation.SecondFragment" android:label="SecondFragment"> <action android:id="@+id/action_secondFragment_to_thirdFragment" app:destination="@id/thirdFragment" /> </fragment> <fragment android:id="@+id/thirdFragment" android:name="com.star_zero.samplenavigation.ThirdFragment" android:label="ThirdFragment" /> </navigation>
Navigation Graph (XML) <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph"
app:startDestination="@id/firstFragment"> <fragment android:id="@+id/firstFragment" android:name="com.star_zero.samplenavigation.FirstFragment" android:label="FirstFragment"> <action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" /> </fragment> </navigation> Fragmentの定義
Navigation Graph (XML) <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph"
app:startDestination="@id/firstFragment"> <fragment android:id="@+id/firstFragment" android:name="com.star_zero.samplenavigation.FirstFragment" android:label="FirstFragment"> <action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" /> </fragment> </navigation> 最初に表示されるFragment
Navigation Graph (XML) <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph"
app:startDestination="@id/firstFragment"> <fragment android:id="@+id/firstFragment" android:name="com.star_zero.samplenavigation.FirstFragment" android:label="FirstFragment"> <action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" /> </fragment> </navigation> 画面遷移の定義
Layout <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/nav_graph" />
Layout <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/nav_graph" /> Navigtion用のFragment BackButtonの制御 画面遷移を定義したXML
Code fun navigate() { val navController = findNavController() navController .navigate(R.id.action_firstFragment_to_secondFragment)
} NavController取得 <action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" /> Nav Graphに設定した <action>のid
引数
Navigation Graph (Navigation Editor)
<fragment android:id="@+id/secondFragment" android:name="com.star_zero.samplenavigation.SecondFragment" android:label="SecondFragment"> <action android:id="@+id/action_secondFragment_to_thirdFragment" app:destination="@id/thirdFragment" /> <argument android:name="user_id"
app:argType="integer" /> <argument android:name="user_name" android:defaultValue="ABC" app:argType="string" /> </fragment> Navigation Graph (XML)
引数の型いろいろ <!-- boolean --> <argument android:name="flag" android:defaultValue="false" app:argType="boolean" /> <!--
int array --> <argument android:name="integers" app:argType="integer[]" /> <!-- enum --> <argument android:name="type" android:defaultValue="Hoge" app:argType="com.star_zero.samplenavigation.Type" />
<!-- Parcelable --> <argument android:name="user" app:argType="com.star_zero.samplenavigation.User" app:nullable="true" /> <!-- Parcelable
array --> <argument android:name="users" app:argType="com.star_zero.samplenavigation.User[]" /> 引数の型いろいろ https://android.googlesource.com/platform/frameworks/support/+/ 6f59e3d74d0da5a4bf79c8480f56964e3af47f1c/navigation/safe-args-generator/src/main/kotlin/ androidx/navigation/safe/args/generator/Types.kt
Code (ワタス側) val userId = getUserId() val userName = getUserName()
val action = FirstFragmentDirections .actionFirstFragmentToSecondFragment(userId) action.setUserName(userName) findNavController().navigate(action)
Code (ワタス側) val userId = getUserId() val userName = getUserName()
val action = FirstFragmentDirections .actionFirstFragmentToSecondFragment(userId) action.setUserName(userName) findNavController().navigate(action) ワタス側のFragmentクラス名 + Directions
Code (ワタス側) val userId = getUserId() val userName = getUserName()
val action = FirstFragmentDirections .actionFirstFragmentToSecondFragment(userId) action.setUserName(userName) findNavController().navigate(action) <action>のidから生成されたメソッド これに引数をワタス(default値がないもののみ)
Code (ワタス側) val userId = getUserId() val userName = getUserName()
val action = FirstFragmentDirections .actionFirstFragmentToSecondFragment(userId) action.setUserName(userName) findNavController().navigate(action) default値が設定されてるものは setterにワタス
Code (ワタス側) val userId = getUserId() val userName = getUserName()
val action = FirstFragmentDirections .actionFirstFragmentToSecondFragment(userId) action.setUserName(userName) findNavController().navigate(action) 最後にnavigateメソッドにワタス
Code (モラウ側) val args = SecondFragmentArgs.fromBundle(arguments) // Activityの場合 val args
= SecondActivityArgs.fromBundle(intent.extras) Timber.d("user_id: ${args.userId}") Timber.d("user_name: ${args.userName}") fromBundleで引数を取得
Deep Link
Navigation Graph (Navigation Editor)
Navigation Graph (XML) <fragment android:id="@+id/deepLinkFragment" android:name="com.star_zero.samplenavigation.DeepLinkFragment" android:label="DeepLinkFragment"> <deepLink app:uri="star-zero.com/{id}" />
</fragment> スキーマ省略時はhttpとhttpsに対応 {id}はプレースホルダー パラメーターとして取得可能
AndroidManifest.xml <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> <nav-graph android:value="@navigation/nav_graph" /> </activity>
Code (パラメーターをモラウ) val args = arguments?.getString("id") Timber.d("args: ${args}")
NavigationUI
ActionBar
None
ActionBar class MainActivity : AppCompatActivity() { private lateinit var appBarConfiguration:
AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) appBarConfiguration = AppBarConfiguration(navController.graph) setupActionBarWithNavController(navController, appBarConfiguration) } override fun onSupportNavigateUp(): Boolean { return findNavController(R.id.nav_host_fragment) .navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } }
ActionBar class MainActivity : AppCompatActivity() { private lateinit var appBarConfiguration:
AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) appBarConfiguration = AppBarConfiguration(navController.graph) setupActionBarWithNavController(navController, appBarConfiguration) } override fun onSupportNavigateUp(): Boolean { return findNavController(R.id.nav_host_fragment) .navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } } AppBarConfigurationを使って NavGraphとActionBarを連携
ActionBar class MainActivity : AppCompatActivity() { private lateinit var appBarConfiguration:
AppBarConfiguration override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) appBarConfiguration = AppBarConfiguration(navController.graph) setupActionBarWithNavController(navController, appBarConfiguration) } override fun onSupportNavigateUp(): Boolean { return findNavController(R.id.nav_host_fragment) .navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } } 左上の矢印ボタンを押したとき
Toolbar
Toolbar class MainActivity : AppCompatActivity() { private lateinit var binding:
ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil .setContentView(this, R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) val appBarConfiguration = AppBarConfiguration(navController.graph) binding.toolbar .setupWithNavController(navController, appBarConfiguration) } }
Toolbar class MainActivity : AppCompatActivity() { private lateinit var binding:
ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil .setContentView(this, R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) val appBarConfiguration = AppBarConfiguration(navController.graph) binding.toolbar .setupWithNavController(navController, appBarConfiguration) } } ActionBarの時と同様 onSupportNavigateUpは設定しなくて良い
Menu Item
None
Navigation Graph - Menu Item <fragment android:id="@+id/menuFragment" android:name="com.star_zero.samplenavigation.MenuFragment" android:label="MenuFragment" />
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menuFragment" android:icon="@drawable/ic_star" android:title="@string/menu" app:showAsAction="ifRoom" /> </menu>
Navigation Graph - Menu Item <fragment android:id="@+id/menuFragment" android:name="com.star_zero.samplenavigation.MenuFragment" android:label="MenuFragment" />
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menuFragment" android:icon="@drawable/ic_star" android:title="@string/menu" app:showAsAction="ifRoom" /> </menu> idを一致させる
Code override fun onOptionsItemSelected(item: MenuItem): Boolean { val navController =
findNavController() return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item) }
Bottom Navigation
Navigation Graph <fragment android:id="@+id/menu_home" android:name="com.star_zero.samplenavigation.HomeFragment" android:label="HomeFragment" /> <fragment android:id="@+id/menu_favorite" android:name="com.star_zero.samplenavigation.FavoriteFragment"
android:label="FavoriteFragment" /> <fragment android:id="@+id/menu_search" android:name="com.star_zero.samplenavigation.SearchFragment" android:label="SearchFragment" />
bottom_nav.xml <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_home" android:icon="@drawable/ic_home" android:title="@string/menu_home" /> <item android:id="@+id/menu_favorite"
android:icon="@drawable/ic_favorite" android:title="@string/menu_favorite" /> <item android:id="@+id/menu_search" android:icon="@drawable/ic_search" android:title="@string/menu_search" /> </menu>
Navigation Graph - bottom_nav.xml <fragment android:id="@+id/menu_home" android:name="com.star_zero.samplenavigation.HomeFragment" android:label="HomeFragment" /> <!--
... --> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_home" android:icon="@drawable/ic_home" android:title="@string/menu_home" /> <!-- ... --> </menu> idを一致させる
Code class MainActivity : AppCompatActivity() { private lateinit var binding:
ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil .setContentView(this, R.layout.activity_main) val navController = findNavController(R.id.nav_host_fragment) binding.bottomNav.setupWithNavController(navController) } }
Shared Element Transitions https://github.com/STAR-ZERO/navigation-shared-element
Activity val options = ActivityOptionsCompat.makeSceneTransitionAnimation( requireActivity(), view, "image" ) val
extras = ActivityNavigator.Extras.Builder() .setActivityOptions(options) .build() findNavController().navigate( R.id.action_hoge_to_foo, null, null, extras )
Fragment val extra = FragmentNavigatorExtras(view to "image") findNavController().navigate( R.id.action_gridFragment_to_imageFragment, null,
null, extra )
カスタマイズ https://github.com/STAR-ZERO/navigation-keep-fragment-sample
Navigator @Navigator.Name("keep_state_fragment") class KeepStateNavigator( private val context: Context, private val
manager: FragmentManager, private val containerId: Int ) : FragmentNavigator(context, manager, containerId) { override fun navigate( destination: Destination, args: Bundle?, navOptions: NavOptions?, navigatorExtras: Navigator.Extras? ): NavDestination? { // ... } }
Navigation Graph <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/nav_graph" app:startDestination="@id/firstFragment">
<keep_state_fragment android:id="@+id/firstFragment" android:name="com.star_zero.samplenavigation.FirstFragment" android:label="FirstFragment" /> <keep_state_fragment android:id="@+id/secondFragment" android:name="com.star_zero.samplenavigation.SecondFragment" android:label="SecondFragment" /> </keep_state_fragment> <keep_state_fragment android:id="@+id/thirdFragment" android:name="com.star_zero.samplenavigation.ThirdFragment" android:label="ThirdFragment" /> </navigation>
Activity val navController = findNavController(R.id.nav_host_fragment) val navHostFragment = supportFragmentManager .findFragmentById(R.id.nav_host_fragment)!!
val navigator = KeepStateNavigator( this, navHostFragment.childFragmentManager, R.id.nav_host_fragment ) navController.navigatorProvider += navigator navController.setGraph(R.navigation.nav_graph)
まとめ
まとめ • 単純な画面遷移は難しくない • SafeArgs便利 • ちょっと凝ったことする時はカスタマイズ必要 • ちょっとずつ導入可能 •
Single Activity
ありがとうございました