Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Navigation Component 実践編
Search
yoppie
December 03, 2019
Technology
300
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Navigation Component 実践編
yoppie
December 03, 2019
More Decks by yoppie
See All by yoppie
AmperとFleetを使ったAndroidアプリ
yoppie
0
1k
Androidエンジニアが Flutterでアプリを リリースするまでの苦悩
yoppie
0
550
FragmentContainerViewとは
yoppie
0
800
Recent tips collection
yoppie
0
1.1k
Distribute Android app updates with bitrise
yoppie
0
1.4k
EC2 using Lumen and DynamoDB and SNS
yoppie
1
290
sabotage
yoppie
1
990
Play with Kotlin
yoppie
1
650
Other Decks in Technology
See All in Technology
AI Agent SaaS を支える自社仮想化基盤への挑戦と実運用 / ai-agent-saas-virtualization
flatt_security
0
310
#エンジニアBooks 30分でわかる 「技術記事を書く技術」 / engineer-books 2026-06-30
jnchito
1
180
Claude Codeとハーネスについて考えてみる
oikon48
16
7.4k
製造現場での生成AIの活用、およびエージェントAIの実装のあり方、AVEVAの取り組み
iotcomjpadmin
0
220
AI時代のエンジニアキャリアについて今一度考える
sakamoto_582
1
1k
AWS Summit 2026で見えたSIerにとっての Amazon Quickの位置づけ
maf_0521
0
160
最近評価が難しくなった
maroon8021
0
210
AWS Summit Japan 2026の振り返りと2027へ向けて / AWS Summit Japan 2026 Recap and Prospects for 2027
kaminashi
1
190
デジタル・デザイン構想 by Sayaka Ishizuka
y150saya
0
180
Oracle Exadata Database Service on Cloud@Customer X11M (ExaDB-C@C) サービス概要
oracle4engineer
PRO
2
8.3k
認証認可だけじゃない! ID管理の構成要素と ライフサイクルを意識しよう
ritou
1
460
「ちゃんとやっている」は独りよがりだった ― 不安に寄り添うインシデント対応へ / Towards incident response that addresses anxieties
chmikata
1
330
Featured
See All Featured
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
The Curious Case for Waylosing
cassininazir
1
420
WCS-LA-2024
lcolladotor
0
670
New Earth Scene 8
popppiees
3
2.4k
The Cult of Friendly URLs
andyhume
79
6.9k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
250
Chasing Engaging Ingredients in Design
codingconduct
0
230
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
240
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
Paper Plane
katiecoart
PRO
1
52k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.4k
Transcript
/BWJHBUJPO$PNQPOFOU ࣮ફฤ
'BDFCPPLIJLPXBJJEF5XJUUFS!ZPQQJF@Y (JUIVCZPTIJZB92JJUBZPQQJF@Y ϒϩάIUUQTZPQQJFYIBUFOBCMPHDPN ZPQQJF
ͪΐͬͱখ
None
%SPJE,BJHJ
'SBHNFOU$POUBJOFS7JFX ͱ
/BWJHBUJPO$PNQPOFOU ࣮ફฤ
w "OESPJE+FUQBDLʹؚ·Ε͍ͯΔίϯϙʔωϯτ w "DUJWJUZ'SBHNFOUؒͷը໘ભҠΛγϯϓϧʹ࣮Ͱ͖Δ w ར w 'SBHNFOU5SBOTBDUJPOͷॲཧΛϥΠϒϥϦ͕ߦ͏ w %FFQ-JOLͷ࣮ͷ؆қԽ
w 4BGF"SHTΛ༻͍ͨܕ҆શͷ͠ w ը໘ભҠͷύλʔϯΛ9.-ʹఆٛ͠ՄࢹԽ /BWJHBUJPO(SBQI /BWJHBUJPO$PNQPOFOU
None
4IBSFE7JFX.PEFM Λ༻͍ͨڞ༗
՝ 'SBHNFOU͔Β'SBHNFOU͠Λ͢Δ߹ ௨ৗ4BGF"SHTΛ༻͍ͨܕ҆શͷ͢͠Δ ͔͠͠ϗετ͍ͯ͠Δ"DUJWJUZͱ֤'SBHNFOUͰԿ͔Λ ڞ༗͢Δ͜ͱ͕Ͱ͖ͳ͍ 5PPMCBSͷ5JUMFͷมߋɺ4OBDLCBSͷදࣔΛ ֤'SBHNFOUͰߦͳΘͣ"DUJWJUZʹ·ͱΊ͍ͨ
Activity Fragment 1 Fragment 4 Fragment 3 Fragment 2 SharedViewModel
ղܾࡦ
4IBSFE7JFX.PEFMͷྫ class SharedViewModel : ViewModel(){ val fragmentType = MutableLiveData<FragmentType>().apply {
this.value = FragmentType.FIRST } } enum class FragmentType(val type: String) { FIRST("first"), SECOND("second"), THIRD("third"), FOURTH("fourth") }
"DUJWJUZͰ0CTFSWF val sharedViewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java) sharedViewModel.fragmentType.observe(this, Observer { value ->
value?.let { Snackbar.make( findViewById(android.R.id.content), it.type, Snackbar.LENGTH_SHORT ).show() } }) 4IBSFE7JFX.PEFMͷGSBHNFOU5ZQF͕มߋ͞Εͨ࣌ʹ 4OBDLCBS͕දࣔ͞ΕΔ
'SBHNFOUͰQPTU7BMVF sharedViewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java) snackbarButton.clicks().subscribe { sharedViewModel.fragmentType.postValue(FragmentType.FIRST) } "DUJWJUZͰ0CTFSWF͍ͯ͠ΔͷͰɺ 'SBHNFOUͷ4IBSFE7JFX.PEFMͷΠϯελϯεΛ
7JFX.PEFM1SPWJEFSTPG ͷҾʹSFRVJSF"DUJWJUZ Λ ࢦఆ͠ͷ"DUJWJUZʹͻ͚ͮͯ࡞
݁Ռ 4IBSFE7JFX.PEFMΛ࡞Δ͜ͱͰɺ ϗετ͍ͯ͠Δ"DUJWJUZͱ ֤'SBHNFOUͰΛڞ༗ "DUJWJUZʹॲཧΛू
ը໘ભҠޙͱ ը໘ભҠ࣌ͷذॲཧ
՝ "DUJWJUZ͕࣋ͭ5PPMCBS'MPBUJOH"DUJPO#VUUPOͳͲͷ 7JFXͷڍಈΛ'SBHNFOUʹґଘͯ͠มߋͨ͠Γɺ 'SBHNFOUؒͷը໘ભҠ࣌ʹม͍͑ͨ ͔͠͠ɺ'SBHNFOUʹ"DUJWJUZ͕࣋ͭ7JFXͷڍಈͷॲཧΛ ॻ͖ͨ͘ͳ͍ why? val toolbar =
view.findViewById<Toolbar>(R.id.toolbar) requireActivity().setSupportActionBar(toolbar)
'SBHNFOUʹґଘͨ͠ڍಈͷมߋ ͳͷͰ'SBHNFOUͰॻ͖ͨ͘ͳΔ ͔͠͠5PPMCBS"DUJWJUZ͕อ༗ͯ͠ ͍ΔͷͰɺอकੑͷ؍͔Β "DUJWJUZͰॻ͖͘ )PNF'SBHNFOUͷ߹ͷΈ 5PPMCBSͷΔϘλϯԡԼ࣌ ͷڍಈΛมߋ͍ͨ͠
ղܾࡦ /BW$POUSPMMFSͷ DVSSFOU%FTUJOBUJPO BEE0O%FTUJOBUJPO$IBOHFE-JTUFOFS Λར༻
binding.toolbar .navigationClicks() .filter { navController.currentDestination != null } .subscribe {
when (navController.currentDestination!!.id) { R.id.homeFragment -> finish() R.id.secondFragment -> navController.navigate( SecondFragmentDirections.homeToFirst() ) } } navController = findNavController(R.id.container_fragment) 'SBHNFOU͝ͱʹ 5PPMCBSͷॲཧΛذ
navController.addOnDestinationChangedListener { _, destination, _ -> when (destination.id) { R.id.firstFragment
-> binding.toolbarButton.visibility = View.GONE R.id.secondFragment -> binding.toolbarButton.visibility = View.VISIBLE } } 'SBHNFOUؒͷը໘ભҠ࣌ ը໘ભҠ࣌ʹ5PPMCBSʹ͋Δ#VUUPOͷWJTJWJMJUZΛมߋ
'SBHNFOUʹґଘ͘͠'SBHNFOU ؒͷը໘ભҠʹΑΔ"DUJWJUZ͕࣋ͭ 7JFX ࠓճͷྫͩͱ5PPMCBS ͷ ڍಈมߋΛ'SBHNFOUʹॻ͔ͣʹ "DUJWJUZʹهࡌͰ͖ͨ ݁Ռ
#PUUPN/BWJHBUJPO7JFXͱͷ ซ༻࣌ͷঢ়ଶอ࣋
՝ #PUUPN/BWJHBUJPO7JFXͱ/BWJHBUJPO$PNQPOFOUΛซ༻ ͢Δ߹ɺσϑΥϧτͰλϒΓସ͑࣌ʹ'SBHNFOU͕࠶ ੜ͞Ε·͢ɻ Αͬͯɺ࠶ੜ͞Εͳ͍Α͏ʹ͢ΔͨΊʹ 'SBHNFOUͷঢ়ଶอ࣋Λ࣮͢Δඞཁ͕ ͋Γ·͢ɻ #PUUPN/BWJHBUJPO7JFX
ղܾࡦ 'SBHNFOU/BWJHBUPSΫϥεΛܧঝͨ͠ $VTUPN/BWJHBUPSΫϥεΛ࡞͠ɺ ঢ়ଶอ࣋͞ΕΔΑ͏ʹOBWJHBUF Λ্ॻ͖
@Navigator.Name("custom_fragment") class CustomNavigator( private val context: Context, private val manager:
FragmentManager, private val containerId: Int ) : FragmentNavigator(context, manager, containerId) { @Suppress("DEPRECATION") override fun navigate( destination: Destination, args: Bundle?, navOptions: NavOptions?, navigatorExtras: Navigator.Extras? ): NavDestination? { // ... } }
if (manager.isStateSaved) { return null } var className = destination.className
if (className[0] == '.') { className = context.packageName + className } val tag = destination.id.toString() val transaction = manager.beginTransaction() val currentFragment = manager.primaryNavigationFragment if (currentFragment != null) { transaction.hide(currentFragment) } var fragment = manager.findFragmentByTag(tag) if (fragment == null) { fragment = instantiateFragment(context, manager, className, args) transaction.add(containerId, fragment, tag) } fragment.arguments = args transaction.show(fragment) transaction.setPrimaryNavigationFragment(fragment) transaction.commit() return destination Ξχϝʔγϣϯͱ #BDL4UBDLपΓͷ ॲཧল͍͍ͯ·͢
class CustomNavHostFragment : NavHostFragment() { override fun createFragmentNavigator( ): Navigator<out
FragmentNavigator.Destination> { return CustomNavigator(requireContext(), childFragmentManager, id) } } /BW)PTU'SBHNFOUͷDSFBUF'SBHNFOU/BWJHBUPS ͷ Γ͕'SBHNFOU/BWJHBUPSͳͷͰܧঝͨ͠ $VTUPN/BW)PTU'SBHNFOUΛ࡞্͠ॻ͖
<navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/bottom_navigation" app:startDestination="@+id/tab1"> <custom_fragment android:id="@+id/tab1" android:name="hoge.HogeFragment" android:label="tab1" android:tag="tab1"
/> OBWJHBUJPOϨΠΞτ $VTUPN/BWJHBUPSΫϥεʹ͚ͭͨ !/BWJHBUPS/BNFΞϊςʔγϣϯͷҾʹࢦఆ͍ͯ͠Δ DVTUPN@GSBHNFOUΛར༻
<fragment android:id="@+id/bottom_navigation_view_fragment" android:name="hoge.navigation.CustomNavHostFragment" android:layout_width="match_parent" android:layout_height="wrap_content" app:defaultNavHost="true" app:layout_constraintBottom_toTopOf="@id/bottom_navigation_view" app:layout_constraintTop_toBottomOf="@+id/toolbar" app:navGraph="@navigation/navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/windowBackground" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:menu="@menu/bottom_navigation_menu" /> BOESPJEYOBWJHBUJPOGSBHNFOU/BW)PTU'SBHNFOU Ͱͳࣗ͘࡞ͨ͠$VTUPN/BW)PTU'SBHNFOUΛࢦఆ
݁Ռ 'SBHNFOUͷঢ়ଶอ࣋ʹޭ
࠷ޙʹ /BWJHBUJPO$PNQPOFOUΛ͏ͱ "DUJWJUZ'SBHNFOUؒͷը໘ભҠΛ γϯϓϧʹ࣮Ͱ͖Δ ࣮ફͰಋೖ͢ΔͱͳΔͱ ӡ༻อकੑΛߟྀ͢ΔΑ͏ʹͳΓ ҙ͕ඞཁ