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
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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.6k
Jetpack Compose の Side-effect を使いこなす / DroidKaigi 2023
star_zero
5
7.2k
Android 14 新機能 / Android 14 Meetup Nagoya
star_zero
1
700
Android 14 と Predictive back gesture / Shibuya.apk #42
star_zero
0
510
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
630
Other Decks in Programming
See All in Programming
Agents on Rails - Rails at Scale 2026
irinanazarova
0
260
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
18
17k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
300
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
260
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
150
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
200
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
510
Building an Out-of-Order CPU
latte72
1
800
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
580
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
520
Jetpack Compose メカニズム
skydoves
0
480
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
110
Featured
See All Featured
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.5k
Claude Code のすすめ
schroneko
67
230k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
500
YesSQL, Process and Tooling at Scale
rocio
174
15k
Product Roadmaps are Hard
iamctodd
55
13k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
720
Odyssey Design
rkendrick25
PRO
2
820
Scaling GitHub
holman
464
140k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
2k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
How to Think Like a Performance Engineer
csswizardry
28
2.8k
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
ありがとうございました