Slide 1

Slide 1 text

Bottom NavigationͰ λϒͷঢ়ଶΛอ࣋͢Δ Keisuke Kobayashi / @kobakei shibuya.apk #17

Slide 2

Slide 2 text

About me • Keisuke Kobayashi • GitHub, Qiita: kobakei • Twitter: kobakei122 • Kyash, Inc

Slide 3

Slide 3 text

YouTubeͷ Bottom Navigation

Slide 4

Slide 4 text

ԼʹεΫϩʔϧ
 ͨ͠ঢ়ଶ

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

εΫϩʔϧҐஔ͕ લճͷ··

Slide 7

Slide 7 text

λϒ੾Γସ͑࣌ʹ
 ঢ়ଶΛอ࣋Ͱ͖ͯΔʂ

Slide 8

Slide 8 text

Ͳ͏΍ͬͯʁ

Slide 9

Slide 9 text

࣮૷ • ViewPagerΛ࢖͏ • λϒબ୒࣌ʹɺsetSelectionͰϖʔδΛ੾Γସ͑Δ • εϫΠϓͰͷ੾Γସ͑͸ΨΠυϥΠϯతʹNGͳͷͰɺεϫ ΠϓΛແޮԽ͓ͯ͘͠ • YouTube΋ଟ෼͜ͷ࣮૷ • uiautomatorviewerͰViewPagerΛ֬ೝ

Slide 10

Slide 10 text

class FixedViewPager @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null ): ViewPager(context, attrs) { override fun onTouchEvent(ev: MotionEvent?): Boolean { return false } override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { return false } }

Slide 11

Slide 11 text

class FixedViewPager @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null ): ViewPager(context, attrs) { override fun onTouchEvent(ev: MotionEvent?): Boolean { return false } override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { return false } } λονΛແޮԽ

Slide 12

Slide 12 text

class MainPagerAdapter(fm: FragmentManager): FragmentPagerAdapter(fm) { override fun getCount(): Int { return 3 } override fun getItem(position: Int): Fragment { return when (position) { 0 -> OneFragment.newInstance() 1 -> TwoFragment.newInstance() 2 -> ThreeFragment.newInstance() else -> throw IllegalArgumentException() } } }

Slide 13

Slide 13 text

class MainPagerAdapter(fm: FragmentManager): FragmentPagerAdapter(fm) { override fun getCount(): Int { return 3 } override fun getItem(position: Int): Fragment { return when (position) { 0 -> OneFragment.newInstance() 1 -> TwoFragment.newInstance() 2 -> ThreeFragment.newInstance() else -> throw IllegalArgumentException() } } } λϒͷ਺

Slide 14

Slide 14 text

class MainPagerAdapter(fm: FragmentManager): FragmentPagerAdapter(fm) { override fun getCount(): Int { return 3 } override fun getItem(position: Int): Fragment { return when (position) { 0 -> OneFragment.newInstance() 1 -> TwoFragment.newInstance() 2 -> ThreeFragment.newInstance() else -> throw IllegalArgumentException() } } } ֤λϒͷFragmentΛฦ͢

Slide 15

Slide 15 text

Slide 16

Slide 16 text

// MainActivity.kt override fun onCreate(savedInstanceState: Bundle?) { // লུ pager.adapter = MainPagerAdapter(supportFragmentManager) bottomBar.setOnTabSelectListener { tabId -> when (tabId) { R.id.tab1 -> showTab1() R.id.tab2 -> showTab2() R.id.tab3 -> showTab3() } } }

Slide 17

Slide 17 text

// MainActivity.kt override fun onCreate(savedInstanceState: Bundle?) { // লུ pager.adapter = MainPagerAdapter(supportFragmentManager) bottomBar.setOnTabSelectListener { tabId -> when (tabId) { R.id.tab1 -> showTab1() R.id.tab2 -> showTab2() R.id.tab3 -> showTab3() } } } λϒબ୒࣌ʹɺදࣔ಺༰Λ੾Γସ͑

Slide 18

Slide 18 text

// MainActivity.kt private fun showTab1() { // Clear back stack (1..supportFragmentManager.backStackEntryCount).forEach { supportFragmentManager.popBackStack() } // Change page without animation pager.setCurrentItem(0, false) }

Slide 19

Slide 19 text

ϥΠϑαΠΫϧͷ໰୊ • ͋Δλϒ͕දࣔ͞Εͨͱ͖ʹԿ͔ॲཧΛͨ͠ ͍৔߹ɺద੾ͳϥΠϑαΠΫϧΠϕϯτ͕ͳ͍

Slide 20

Slide 20 text

Why? • ViewPager͸εϜʔζʹεϫΠϓͰ͖ΔΑ͏ʹ ͢ΔͨΊɺද͍ࣔͯ͠Δλϒͱ྆ྡͷλϒΛ ද͍ࣔͯ͠Δ • λϒ͕දࣔ͞ΕΔΑΓઌʹonResume͕ݺ͹ ΕΔ

Slide 21

Slide 21 text

ղܾࡦ • BottomBarͷλϒબ୒ɾඇબ୒ΠϕϯτΛ Fragmentʹ౉͢

Slide 22

Slide 22 text

// ֤λϒͷFragement͸͜ͷΠϯλϑΣʔεΛ࣮૷͢Δ interface RootFragment { fun onTabSelected() fun onTabUnselected() }

Slide 23

Slide 23 text

class MainPagerAdapter(fm: FragmentManager): FragmentPagerAdapter(fm) { var currentFragment: Fragment? = null override fun getCount(): Int {...} override fun getItem(position: Int): Fragment {...} override fun setPrimaryItem(container: ViewGroup?, position: Int, obj: Any?) { if (currentFragment != obj) { currentFragment = obj as Fragment } super.setPrimaryItem(container, position, obj) } }

Slide 24

Slide 24 text

class MainPagerAdapter(fm: FragmentManager): FragmentPagerAdapter(fm) { var currentFragment: Fragment? = null override fun getCount(): Int {...} override fun getItem(position: Int): Fragment {...} override fun setPrimaryItem(container: ViewGroup?, position: Int, obj: Any?) { if (currentFragment != obj) { currentFragment = obj as Fragment } super.setPrimaryItem(container, position, obj) } } ݱࡏͷFragmentΛอ࣋

Slide 25

Slide 25 text

// MainActivity.kt
 override fun onCreate(savedInstanceState: Bundle?) { // ... // ViewPager pager.adapter = MainPagerAdapter(supportFragmentManager) // bottomBar.setOnTabSelectListener { tabId -> dispatchUnselect() when (tabId) { R.id.tab1 -> showTab1() R.id.tab2 -> showTab2() R.id.tab3 -> showTab3() } dispatchSelect() } }

Slide 26

Slide 26 text

// MainActivity.kt override fun onCreate(savedInstanceState: Bundle?) { // ... // ViewPager pager.adapter = MainPagerAdapter(supportFragmentManager) // bottomBar.setOnTabSelectListener { tabId -> dispatchUnselect() when (tabId) { R.id.tab1 -> showTab1() R.id.tab2 -> showTab2() R.id.tab3 -> showTab3() } dispatchSelect() } } Fragment੾ସͷલޙͰ
 ΠϕϯτΛൃՐ

Slide 27

Slide 27 text

private fun dispatchSelect() { val mainAdapter = pager.adapter as? MainPagerAdapter val fragment = mainAdapter?.currentFragment as? RootFragment fragment?.onTabSelected() } private fun dispatchUnselect() { val mainAdapter = pager.adapter as? MainPagerAdapter val fragment = mainAdapter?.currentFragment as? RootFragment fragment?.onTabUnselected() }

Slide 28

Slide 28 text

·ͱΊ • BottomNavigationͷλϒͷঢ়ଶอ࣋ʹ͸ɺ
 εϫΠϓ͠ͳ͍ViewPagerΛ࢖͏ • දࣔɾඇදࣔ࣌ʹԿ͔͍ͨ͠৔߹͸ɺ
 λϒબ୒ɾඇબ୒ΠϕϯτΛFragmentʹ౉͢

Slide 29

Slide 29 text

Thanks!