Android QのGesturalNavigationとDrawerLayoutの競合に対するボクなりの最適解
Android Qでは Gestural Navigation
が基本となり、アプリ側で対応が必要となりました。
Gestural Navigationについて詳しくはこちらのスライドで触れています。
何に注意が必要なのか?
上のスライドでも触れていますが、Gestural Navigationは
画面の両サイドからスワイプすると戻る挙動
をします。
ということは、これまでDrawerLayoutを画面左右からのスワイプで表示していたのが競合します。
何も対応しないと
Drawerを表示したいのに、アプリが終了してしまう
という動きになってしまい、ユーザー体験は良くないものとなってしまいます。
どう対処したらいい?
方法は2つあります。
- DrawerLayoutをAndroidXの物を使う
- 自分で対応する(私が出した最適解)
DrawerLayoutをAndroidXの物を使う
implementation 'androidx.drawerlayout:drawerlayout:1.1.0-alpha01'
このAndroidXのDrawerLayoutを使うと
- Drawerが閉じてる時:Drawerが開く
- Drawerが開いている時:アプリが終了する
という挙動になります。
果たしてこれは本当にユーザーが求めている挙動なのか・・・?
Gestural Navigationは始まったばかりの機能なので「ユーザーが求める挙動」の定義は難しいですが
なんだか違和感があります。
ということで、最適解を考えてみました。
自分で対応する(私が出した最適解)
Android版のTwitter公式アプリがやっているDrawerの出し方が、体験としては非常に良いのではないかと感じています。
- 画面のどこでも左から右にスワイプ:Drawerが開く
- 画面両サイドからスワイプ:Gestural Navigationでアプリが終了する
私はAndroid Q Beta3を入れて日々Gestural Navigationを使っていますが、
画面両サイドからスワイプすると「戻る」挙動
を感覚的に求めていました。なので、Twitter公式アプリの挙動が最適解なのではないかと感じました。
具体的な実装
サンプルコードは https://github.com/furusin/GesturalNavigationSample に上げています。
画面上でのスワイプ(フリック)の検知は
Androidでフリックイベントを取得する
の記事を参考にしました。
AndroidXのDrawerLayoutを使わず、GestureDetector.SimpleOnGestureListener
の onFling()
で画面上でのスワイプ(フリック)を検知するようにしています。
class MainActivity : AppCompatActivity() {
companion object {
// X軸最低スワイプ距離
private const val SWIPE_MIN_DISTANCE = 50
// X軸最低スワイプスピード
private const val SWIPE_THRESHOLD_VELOCITY = 200
}
lateinit var gestureDetector: GestureDetector
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 左から右へのスワイプでDrawerLayoutを開く
gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
override fun onFling(
event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float
): Boolean {
// 左から右へのフリックの判定
if (event2.x - event1.x > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
findViewById<DrawerLayout>(R.id.drawerLayout).openDrawer(Gravity.LEFT)
}
return false
}
})
}
// ListViewの場合はonTouchEventではなく
// dispatchTouchEventを使う
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
// GestureDetectorにイベントを流す
gestureDetector.onTouchEvent(ev)
return super.dispatchTouchEvent(ev)
}
}
まとめ
いかがだったでしょうか。
まだ本記事執筆時点(2019/05/28)ではAndroid QはBeta3ですし、Gestural Navigationの挙動自体が変わる可能性はあります。
ですので「こんな考え方(回避のしかた)もあるんだな」程度で捉えていただければと思います。
また、「横向きスクロールのViewがあった場合どうするの」といった問題もあり、そこは考慮できてません。
もう少し考える必要はあるかなぁと思います。
Author And Source
この問題について(Android QのGesturalNavigationとDrawerLayoutの競合に対するボクなりの最適解), 我々は、より多くの情報をここで見つけました https://qiita.com/furusin_oriver/items/e2d20325fefded070cb6著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .