Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Navigationの採用を検討してみて、 色々考えた話を共有するよ

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Navigationの採用を検討してみて、 色々考えた話を共有するよ

Avatar for kobashin

kobashin

July 25, 2019
Tweet

More Decks by kobashin

Other Decks in Programming

Transcript

  1. ΏΔΏΔͱ͓࿩͠·͢ ࠓ೔ͷAgenda • Android Jetpack Navigationͱ͸ʁ • SingleActivity or Multi-Activityʁ

    • BottomNavigationͱҰॹʹ࢖͍͍ͨ • ͦͷଞ (※࣌ؒ଍Γͳ͍৔߹͸ඈ͹͔͢΋)
  2. 3෼࢖͍ํߨ࠲ ActivityʹNavHostFragmentΛ഑ஔ͢Δ <androidx.constraintlayout.widget.ConstraintLayout > <fragment android:layout_width="0dp" android:layout_height="0dp" android:id="@+id/root_nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" app:navGraph="@navigation/navigation_graph_with_bottom_nav"

    app:defaultNavHost="true" app:layout_goneMarginBottom="0dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@id/bottom_navigation" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/> LayoutʹNavHostFragment Λ഑ஔ͢Δ ઌఔ࡞੒ͨ͠ɺnavigation.xml Λࢦఆ͢Δ layout/activity_main.xml
  3. ࠷ۙͷ New Features(ݸਓతʹྑ͍ͱࢥͬͨ΍ͭ) 2.1.0-alpha02 • NaviGraphͷείʔϓʹ߹ΘͤͨViewModel͕ੜ੒Մೳʹ private val viewModel: SearchViewModel

    by navGraphViewModels<SearchViewModel>(R.id.nav_search) ͜ͷείʔϓͰར༻͍ͨ͠ ViewModeΛએݴͰ͖Δ src/SearchFragment.kt
  4. ࠷ۙͷ New Features(ݸਓతʹྑ͍ͱࢥͬͨ΍ͭ) 2.1.0-alpha03ɹ<dialog />͕ར༻Մೳʹ <navigation> <fragment android:id="@+id/nav_fav" android:name="kobashin.com.navigation_sample.FavoriteFragment" android:label="FavoriteFragment"

    tools:layout="@layout/fragment_favorite" > <action android:id="@+id/action_nav_fav_to_nav_modal" app:destination="@id/nav_modal" /> </fragment> <dialog android:id="@+id/nav_modal" android:name="kobashin.com.navigation_sample.BottomSheetFragment" android:label="BottomSheet" tools:layout="@layout/fragment_bottom_sheet"/> </navigation> BottomSheetDialogFragment ΋DialogFragmentͳͷͰ ར༻Ͱ͖Δ navigation/navigation_graph.xml
  5. Ϣʔβʔͷಋઢ͔Βݕ౼͢Δ Top SearchTop Search ItemDetail Top TOP SearchTop TOP SearchTop

    Search TOP SearchTop Search ItemDetail ͜͜ͷભҠΛؾ࣋ͪΑ͘ ͍ͨ͠ʂ
  6. ద౰ͳΞϓϦͰը໘ભҠΛ܁Γฦͯ͠ΈΔ Activityฤ @Test fun mainActivityTest() { for (x in 0..1000)

    { val appCompatButton = onView( allOf( withId(R.id.button), withText("button"), childAtPosition( childAtPosition( withId(android.R.id.content), 0 ), 1 ), isDisplayed() ) ) appCompatButton.perform(click()) } } class SearchActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_search) button.setOnClickListener { startActivity(Intent(this, ItemDetailActivity::class.java)) } } } src/SearchActivity.kt androidTest/MainActivityTest.kt
  7. ద౰ͳΞϓϦͰը໘ભҠΛ܁Γฦͯ͠ΈΔ Fragmentฤ class SearchFragment : Fragment() { override fun onCreateView(

    inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_search, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) button.setOnClickListener { findNavController() .navigate(R.id.action_searchFragment_to_itemDetailFragment) } } } ※ςετίʔυ͸΄΅ಉ͡ src/SearchFragment.kt
  8. BottomNavigationͱҰॹʹ࢖͏ʹ͸ʁ <menu xmlns:android="http://schemas.android.com/apk/res/ android"> <item android:id="@+id/nav_top" android:icon="@drawable/ic_baseline_home_24px" android:title="top" /> <item

    android:id="@+id/nav_search" android:icon="@drawable/ic_baseline_search_24px" android:title="search" /> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/navigation_graph" app:startDestination="@id/nav_top"> <fragment android:id="@+id/nav_top" android:name="kobashin.com.navigation_sample.TopFragment" android:label="TopFragment" tools:layout="@layout/fragment_top" > <action android:id="@+id/action_topFragment_to_searchFragment" app:destination="@id/nav_search" /> <action android:id="@+id/action_topFragment_to_mypageFragment" app:destination="@id/mypageFragment" /> </fragment> ͜͜Λἧ͑Δ menu/item_id navigation/fragment_id Λἧ͑Δ menu/menu.xml navigation/navigation_graph.xml
  9. class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    // লུ val navController = findNavController(R.id.root_nav_host_fragment) setupActionBarWithNavController( navController, AppBarConfiguration( setOf( R.id.nav_top, R.id.nav_search, R.id.nav_fav, R.id.nav_my ) ) ) bottom_navigation.setupWithNavController(navController) navigation/fragment_id Λ౉͢ BottomNavigationͷ ॳظԽΛ๨Εͳ͍ ActionBarͷॳظԽ࣌ʹ ભҠઌͷidsΛ౉͢ src/MainActivity.kt BottomNavigationͱҰॹʹ࢖͏ʹ͸ʁ
  10. BottomNavigationͷλϒຖʹBackStackΛอ͍࣋ͨ͠ • BottomNavigationView.
 setOnNavigationItemSelectedListener
 ͰભҠઌͷNavHostFragmentΛࢦఆ͢Δ • Back੍ޚͰ֤λϒͷStack͕ແ͘ͳͬͨ
 ઌΛTopʹ͢ΔͨΊɺaddToBackStack()
 ͓ͯ͘͠ setOnNavigationItemSelectedListener

    { item -> val newlySelectedItemTag = graphIdToTagMap[item.itemId] fragmentManager.beginTransaction() .attach(selectedFragment) .setPrimaryNavigationFragment(selectedFragment) .apply { // Detach all other Fragments graphIdToTagMap.forEach { _, fragmentTagIter -> if (fragmentTagIter != newlySelectedItemTag) { detach( fragmentManager.findFragmentByTag(firstFragmentTag)!! ) } } } .addToBackStack(firstFragmentTag) .commit() } src/NavigationExt.kt λϒຖʹอ࣋͢Δ NavHostFragmentͷ੾Γ ସ͑෦෼
  11. Fragmentͷ໊લղܾͷλΠϛϯάΛ୳Δ Activityͷىಈ LayoutͷಡΈࠐΈ NavHostFragment ͷॳظԽ NavHostController
 ͷॳظԽ Graphͷੜ੒ app:startDestination Λىಈ

    https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/navigation/navigation-fragment/src/main/java/androidx/ navigation/fragment/NavHostFragment.java#204
  12. ໊લղܾͷλΠϛϯάΛ୳Δ • Build࣌Ͱ͸ͳ͘ɺ࣮ߦ࣌ʹ໊લղܾΛߦ͍ͬͯΔ
 ͭ·ΓɺBuild࣌఺Ͱ੺͘ͳ͍ͬͯͯ΋େৎ෉ʂ
 ֆ͕ग़ͳ͍ͷ͕ͪΐͬͱऐ͍͚͠ΕͲ <?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_search" app:startDestination="@id/searchFragment"> <fragment android:id="@+id/searchFragment" android:name=“jp.co.yahoo.android.xxx.xxx.SearchTopFragment" android:label="SearchFragment"> <action android:id="@+id/action_contents_search_to_search_result" app:destination="@id/searchResultFragment"/> </fragment> ࣮ߦ࣌ʹղܾͰ͖Δ FragmentΛࢦఆ͢Δ navigation/navigation_graph.xml
  13. Dialog಺Ͱ΋Navigation͕͍ͨ͠ class SearchModalFragment : BottomSheetDialogFragment() { override fun onViewCreated(view: View,

    savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val fragment = NavHostFragment.create(R.navigation.modal_navi_graph) childFragmentManager.beginTransaction() .replace(R.id.container_nav_host, fragment) .commit() } • Activityʹஔ͘Α͏ʹɺ <fragment />
 Λॻ͘ͱ࠶ੜ੒࣌ʹΤϥʔʹͳΔ • ಈతʹੜ੒͢Ε͹े෼࢖͑Δ ίϯετϥΫλ͕ੜ͑ͯΔͷ ͰͦΕΛ࢖͏ src/SearchModalFragment.kt