普段、左手でiPhoneを操作している人は、iOS7になってから毎日こんな経験をしているのではないでしょうか。
ひどいUXですね
これでは、本来の縦スクロール操作が慎重になってしまい、ストレスが募るばかり。。それもこれも、UINavigationController
のinteractivePopGestureRecognizer
(UIScreenEdgePanGestureRecognizer
クラス)の感度が高すぎるのが原因です。
そこで改善策として、UIScreenEdgePanGestureRecognizer
クラスをメソッド差し替え(swizzle)して感度調整する涙ぐましい方法などがありますが、今回はそれよりももっと簡単で良い方法が見つかったので、その情報共有をします。
ヒントは、Facebookアプリでした。
interactivePopGestureRecognizer.delegateを自前で実装する(ただし、注意点あり)
標準のUINavigationControllerのジェスチャー+トランジションを使って感度調整を行っている(と思われる)アプリは、手元のインストール済みアプリの中では、Facebookだけでした。このアプリでは、
- コンテンツのスクロール中に、interactivePopGestureRecognizerを実行しない
という上手い処理が入っているようで、似たところでは、Twitter公式アプリもそのような挙動になっていました。つまり、
// viewWillAppearあたり
self.navigationController.interactivePopGestureRecognizer.delegate = self;
...
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
// (1)
if (self.tableView.dragging) return NO;
// (2)
return [self.navigationController.viewControllers count] > 1;
}
return YES;
}
と(1)のように書くのが、よりスマートな方法と言えます。
ただし、注意点として、interactivePopGestureRecognizer.delegate
を標準の_UINavigationInteractiveTransition
から勝手に奪っているので、 自己責任のもと、取り扱いにくれぐれも注意する 必要があります。(カスタムleftBarButtonItemをセット→popGestureを再度ONにした場合も同様)
One problem with this method is if you perform an edge pan on a root view it will lock up the UI
(意訳)navigationControllerのrootViewController内でinteractivePopGestureRecognizerを実行すると、UIがおかしくなるよ
この対策として、(2)も合わせて入れておくと良いでしょう。
まとめ
左利きにも優しいUIができた Appleが最初から頑張ればこんなことにはならなかった