Slide 1

Slide 1 text

意外と簡単?Navigation rail導入のお話 2021/11/16 Mobile勉強会 Wantedly × チームラボ tomoya0x00 1

Slide 2

Slide 2 text

About me tomoya0x00 Twitter, GitHub Android U-NEXT Co., Ltd. 2

Slide 3

Slide 3 text

話す事と、話さない事 話す事 Bottom navigation導入済みアプリに、Navigation railを導入した話し ただし、実装しただけで未リリース 話さない事 Material Design 3 Material Design 2前提の話しをします Jetpack Compose 従来のAndroid View上での話しをします 3

Slide 4

Slide 4 text

目次 Navigation Rail is 何? 具体的なBottom navigationとの使い分け条件 簡単に導入できる前提条件 実際の導入の流れ なぜ、選択済みアイテムが引き継がれているのか? U-NEXTアプリに追加で手を加えたところ まとめと感想 4

Slide 5

Slide 5 text

Navigation Rail is 何? 5

Slide 6

Slide 6 text

6

Slide 7

Slide 7 text

Usage The rail is a side navigation component that displays three to seven app destinations and, optionally, a Floating Action Button. Each destination is represented by an icon and a text label. The rail can function on its own at larger screen sizes, such as desktop and tablet. When users transition between screen sizes and devices, the rail can also complement other navigation components, such as bottom navigation. https://material.io/components/navigation-rail#usage 7

Slide 8

Slide 8 text

When to use Navigation rails should be used for: Top-level destinations that need to be accessible anywhere in an app Three to seven main destinations in a product Tablet or desktop layouts Navigation rails shouldn’t be used for: Small screen sizes Single tasks, such as viewing a single email Secondary navigation destinations https://material.io/components/navigation-rail#usage 8

Slide 9

Slide 9 text

具体的なBottom navigationとの使い分け条件 9

Slide 10

Slide 10 text

Create responsive navigation views https://developer.android.com/guide/topics/large-screens/navigation-for-responsive- uis#create_responsive_navigation_views 10

Slide 11

Slide 11 text

Window size classes https://developer.android.com/guide/topics/large-screens/support-different-screen- sizes#window_size_classes 11

Slide 12

Slide 12 text

簡単に導入できる前提条件 12

Slide 13

Slide 13 text

簡単に導入できる前提条件 (1/2) Material Components for Android の BottomNavigationView を導入済み BottomNavigationViewを表示しているActivityでは、configuration changeを自前でハ ンドリング していない AndroidMafinext.xml で、該当Activityに android:configChanges という 記 載が無い 13

Slide 14

Slide 14 text

簡単に導入できる前提条件 (2/2) BottomNavigationView固有のメソッドを使っていない NavigationBarView で提供されているメソッドだけを使っているならOK NGなメソッド isItemHorizontalTranslationEnabled setItemHorizontalTranslationEnabled setOnNavigationItemReselectedListener 代わりに setOnItemReselectedListener を使う setOnNavigationItemSelectedListener 代わりに setOnItemSelectedListener を使う 14

Slide 15

Slide 15 text

実際の導入の流れ 15

Slide 16

Slide 16 text

実際の導入の流れ 1. 使用するMaterial Components for Androidのバージョンを1.4.0以上にする 2. 横幅600dp以上でレイアウトファイルを切り替えてNavigationRailViewを表示する 3. Activity側ではNavigationBarViewとしてキャストして使用する 16

Slide 17

Slide 17 text

1. 使用するMaterial Components for Androidのバージョンを1.4.0以 上にする NavigationRailView は 1.4.0 から使用できるため app moduleのbuild.gradleなどを更新 implementation "com.google.android.material:material:1.4.0" 17

Slide 18

Slide 18 text

2. 横幅600dp以上でレイアウトファイルを切り替えて NavigationRailViewを表示する Create responsive navigation views を参考に、レイアウトファイルを分ける BottomNavigationViewを表示しているActivity(以降:MainActivity)のレイアウトフ ァイルを res/layout-w600dp/ にコピーして、 BottomNavigationView を NavigationRailView に書き換える app:layout_constraint* も表示位置に合わせて変更する 18

Slide 19

Slide 19 text

コピー元:res/layout/main_activity.xml 19

Slide 20

Slide 20 text

コピー先:res/layout-w600dp/main_activity.xml 20

Slide 21

Slide 21 text

レイアウトファイルの差分と補足 (1/2) com.google.android.material.bottomnavigation.BottomNavigationView -> com.google.android.material.navigationrail.NavigationRailView app:layout_constraintEnd_toEndOf="parent" -> app:layout_constraintTop_toTopOf="parent" android:layout_width と android:layout_height の値を入れ替え 記載を省略していますが、 content view(s) の app:layout_constraint* も変更 必要です 21

Slide 22

Slide 22 text

レイアウトファイルの差分と補足 (2/2) android:id や app:menu はそのまま(同じ値を指定)にしておきます 自分は事前に共通っぽい(Bottom navigation固有では無い)名前にリネームしまし た android:id を同じにしておくと実装が楽ですが、後述の危険性もあるのでご留意 ください 22

Slide 23

Slide 23 text

3. Activity側ではNavigationBarViewとしてキャストして使用する before binding.navView.setOnItemSelectedListener { ... } after // binding 上はView になってしまうので、キャストしている val navView = binding.navView as NavigationBarView navView.setOnItemSelectedListener { ... } 23

Slide 24

Slide 24 text

これだけです 24

Slide 25

Slide 25 text

※ これらのスクショは開発中のもので、ロゴの追加やテキストスタイル調整をおこなっています 25

Slide 26

Slide 26 text

※ これらのスクショは開発中のもので、ロゴの追加やテキストスタイル調整をおこなっています 26

Slide 27

Slide 27 text

意外と簡単ですよね? 27

Slide 28

Slide 28 text

ただ、疑問が一つ… 28

Slide 29

Slide 29 text

なぜ、選択済みアイテムが引き継がれているのか? 29

Slide 30

Slide 30 text

なぜ、選択済みアイテムが引き継がれているのか? なぜ、画面回転しても選択済みアイテムの状態が復元されているのか? BottomNavigationView と NavigationRailView は個別に onSaveInstanceState/onRestoreInstanceState を実装 していない 共通の親である NavigationBarView で状態の保存と復元をおこなっている NavigationBarView#onSaveInstanceState NavigationBarView#onRestoreInstanceState なので、レイアウトファイル上で同じView IDだと自動で保存と復元ができる ただし、将来的に個別に保存と復元処理が実装されると、壊れる危険性あり 30

Slide 31

Slide 31 text

U-NEXTアプリに追加で手を加えたところ 31

Slide 32

Slide 32 text

U-NEXTアプリに追加で手を加えたところ Windowの高さが低い場合、 Compact rail without text labels を参考に表示を微調整 ロゴ無し ラベル文字無し NavigationRailView の横幅を小さくして、各アイテムの高さを削減 コメント によると、 NavigationRailView の横幅 = 各アイテムの最小限の高さ val metrics = WindowMetricsCalculator.getOrCreate() .computeCurrentWindowMetrics(this) val heightDp = metrics.bounds.height() / resources.displayMetrics.density if (heightDp < 400) { navRail.removeHeaderView() navRail.labelVisibilityMode = NavigationRailView.LABEL_VISIBILITY_UNLABELED navRail.layoutParams.width = (56 * resources.displayMetrics.density).toInt() } 32

Slide 33

Slide 33 text

※ これらのスクショは開発中のもので、ロゴの追加やテキストスタイル調整をおこなっています 33

Slide 34

Slide 34 text

※ これらのスクショは開発中のもので、ロゴの追加やテキストスタイル調整をおこなっています 34

Slide 35

Slide 35 text

まとめと感想 35

Slide 36

Slide 36 text

まとめと感想 Bottom navigation導入済みであれば、Navigation railの導入は意外と簡単 View IDを共通にすると実装が楽だけど、今後壊れる可能性はあるので注意 個人的にスマホ横画面でのNavigation railは縦方向の表示領域が広がって嬉しい ただし、スマホ横画面でNavigation railに切り替わるアプリを見たことが無い 例えば、 google/iosched では、 横幅720dp以上 で切り替えている ただ、時系列に 600dp以上で切り替えましょう が最新ガイドライン? 自分の場合、タブレットやスマホ横画面では両手で端末の両サイドを保持する ナビゲーションのUIが端末の横側に表示されるのは、操作しやすい気がする 36