Edge-to-edgeの対応

#はじめに
Android Qから、「ジェスチャーナビゲーション」という新しい操作方法が追加されました。
従来の操作方法は、画面下部にある三つのボタンをタッチしてホーム画面に戻ったり、ひとつ前の画面に戻ったりしていました。
「ジェスチャーナビゲーション」はiOSのようにボタンではなくジェスチャーによって前の画面に戻ったりする操作方法です。

|3ボタンナビゲーション|ジェスチャーナビゲーション|
|:---:|:---:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/3ab585f4-d246-b42a-8949-266a063d7396.png" width="50%">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/7ea6fd81-02f3-1246-a6c8-5b3d7aadedf8.png" width="50%">|

このジェスチャーナビゲーションを利用することで、画面全体を使うことができ
より没入感のあるUXを提供することができるようになりました。

#Edge-to-edgeとは
一言で表すと、画面全体をアプリの領域として扱える。
<img src="https://1.bp.blogspot.com/-kP4-Xq5x3NI/XZaZjjTvsKI/AAAAAAAADwE/jVBjEPU4XmICQkxmXjUhC1Xhhnc8E6K-ACEwYBhgL/s1600/1_JvQG9PD7qvD3zhHq-gpc_w.gif" width="30%">
アプリはシステムバー(ステータスバー、ナビゲーション バー)の背後に配置されるようになります。

#前提
サンプルアプリのEdge-to-edge未対応は以下のようになります。

```xml
<ConstraintLayout>
 <ImageView />
 <Button />
</ConstraintLayout>
```

|3ボタンナビゲーション|ジェスチャーナビゲーション|
|:---:|:---:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/8675882a-6a7e-6a47-7d0b-383d2c189b40.png" width="50%">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/2b76cfa8-d7fb-3dcf-c412-4698b1e949d7.png" width="50%">|



#全画面表示
View.setSystemUiVisibility() を使用して次のフラグを設定するだけで、全画面にアプリを表示できます。
ステータスバーの背後のみや、ナビゲーションバーの背後のみということも可能です。

```kotlin
val decorView = window.decorView
decorView.systemUiVisibility = (
        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        )
```

|3ボタンナビゲーション|ジェスチャーナビゲーション|
|:---:|:---:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/6a590c3a-f800-0eaf-a3ca-f2e2fada8bfb.png" width="50%">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/650befad-b575-c795-32a9-39b38341074e.png" width="50%">|



しかし、サンプル画像で見られるようにアプリがシステムバーの背後に配置されるため、ボタンが隠れてしまいます。
そこで、システムバーの色を透明にするとことで、全画面にアプリが表示されていることを確認できます。

#透明なシステムバーの設定
システムバーの背景を透明にすることができます。

```xml
<style name="AppTheme" parent="...">
    <item name="android:navigationBarColor">@android:color/transparent</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>
```

|3ボタンナビゲーション|ジェスチャーナビゲーション|
|:---:|:---:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/57435c08-dd14-e81c-e587-ff57ba178c38.png" width="50%">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/7a544fa3-a8bf-03b4-93ca-bb442fb39f2f.png" width="50%">|

また、`Window.setNavigationBarColor()` と `Window.setStatusBarColor()` を使用すると、透明なシステム バーを動的に設定できます。

しかし、サンプル画像で見られるようにアプリがシステムバーの背後に配置されるため、ボタンを押すことができません。
そこで、`fitsSystemWindow`を利用し、要素が被らないように実装できます。

#fitsSystemWindowの対応
親レイアウトに設定することで、自動的にかさらないように調整してくれる。
fitsSystemWindowはデフォルトで深さ優先探索をし、見つかった最初のみ適応される

|3ボタンナビゲーション|ジェスチャーナビゲーション|
|:---:|:---:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/61f9c93a-b940-a582-5f98-ded635494e3f.png" width="50%">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/c9a4ba1a-8fda-21ab-ab90-53f5232df1eb.png" width="50%">|


しかし、ステータスバーの背景が透明なため、アイコンが見えずらくなってしまう。

#WindowsInsetsの対応
システムバーの幅、占める領域をWindowsInsetsを使うことでより柔軟にカスタマイズすることができる

```kotlin
view.setOnApplyWindowInsetsListener{v, insets ->
            v.updatePadding(
                top = 0,  //insets.systemWindowInsetTopでステータスバーの高さを取得可能
                bottom = insets.systemWindowInsetBottom
            )
            insets
        }
```

|3ボタンナビゲーション|ジェスチャーナビゲーション|
|:---:|:---:|
|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/833ffe2f-d16d-2ea8-2796-4da5561b0f8c.png" width="50%">|<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542499/da664ddd-9b0a-1f8f-6be0-ac8f898faded.png" width="50%">|

#まとめ
* 簡単に全画面に対応できるが、システムバーの色や重なりを考慮するのが大変そう
* 全画面にすることで没入感を得ることはできた

#参考
* https://developers-jp.googleblog.com/2019/10/gesture-navigation-going-edge-to-edge.html
* https://developer.android.com/training/gestures/gesturenav