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 Component 実践編
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
1.1k
Androidエンジニアが Flutterでアプリを リリースするまでの苦悩
yoppie
0
560
FragmentContainerViewとは
yoppie
0
810
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
300
sabotage
yoppie
1
1k
Play with Kotlin
yoppie
1
660
Other Decks in Technology
See All in Technology
[2026-09-11]SREは誰のもの?運用エンジニアが始める 「SRE領域への越境」とチームの進化の軌跡 〜Road to NEXT CRE
tosite
0
180
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
5
25k
Claude Code本って、 読む必要あるの?
oikon48
2
440
AI 駆動 Terraform 開発/SRE_BizReach_MIXI_2
visional_engineering_and_design
5
2.1k
幾何アルゴリズムで なめらかなピン操作を / iOSDC Japan 2026 / smoothpin
kazumanagano
0
310
日経電子版を支えていく Kasane Design System/fec_fukuoka
nikkei_engineer_recruiting
0
1.2k
ASTを使って影響範囲を特定する
nealle
0
180
2026-09-09 【sigma_ucj#1】Sigma を IaC 管理したい! / IaC for Sigma
civitaspo
0
130
コスト最適化の「めんどくさい」を AWS FinOps Agent でチョット楽にする
classmethod_kaz
0
330
越境するなら専門用語を使うな高校校歌 / If you wanna cross border, you shouldn't use jargon
vtryo
0
130
OpenTelemetryのメトリクスをCloudWatchに送ってPromQLで見てみた
ota1022
0
140
事業課題から技術的負債に向き合う
sansantech
PRO
2
540
Featured
See All Featured
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
380
Skip the Path - Find Your Career Trail
mkilby
1
230
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Docker and Python
trallard
47
4.2k
A better future with KSS
kneath
240
18k
The Curious Case for Waylosing
cassininazir
1
500
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.9k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
4
640
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
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ؒͷը໘ભҠΛ γϯϓϧʹ࣮Ͱ͖Δ ࣮ફͰಋೖ͢ΔͱͳΔͱ ӡ༻อकੑΛߟྀ͢ΔΑ͏ʹͳΓ ҙ͕ඞཁ