TL;DR
- 今年のiPhoneのハードウェア面のウリは3D Touch
- Peek & Popはとても簡単に実装できる
- Peekで見せるViewはPopで表示されるViewと同じである必要はないので、専用のViewControllerを用意するとUXの向上が期待できる、はず
どうも、こんにちは。iOS大好き monoqlo(ものくろ) です。
2015年を振り返ってみると、ここ数年噂されていたApple Watchが発売されたり、iOSベースのtvOSを搭載した第4世代Apple TVが登場したり、Swiftも予定通りオープンソース化されました。
Appleが仕込んできた新しいプロダクトやツールが次々とお披露目された印象深い年となりましたね。
さて、そんな中、毎年アップグレードされるiPhoneですが、今年の目玉のひとつは3D Touchです。
引用元:iPhone 6s - デザイン - Apple(日本) http://www.apple.com/jp/iphone-6s/design/ (2015年12月15日)
発表時、「便利な気もするけれど、必要なんだろうか」というような、なんとも腑に落ちない感じの感想を頂いた方々がいたような気もしますが、今月LINEが3D Touchに対応して、未読のままメッセージが読める!と話題になった*1ことで見方が変わった人も多くいるのではないでしょうか(?)
賛否両論ありますが、とにかく実装してみたくなるのが開発者のサガってやつですね!
この記事は animateLAB Advent Calendar 2015 21日目の記事です。
3D Touch対応するなら、まずはここから
3D Touch対応にあたり、オススメなのが、Home Screen Quick ActionsとPeek & Popです。
Home Screen Quick Actionsを実装すると、ホーム画面でアプリアイコンを強く押すことでメニューが表示されます。このメニューがアプリ内の特定の画面を直接表示するショートカットになっています。
例えば、投稿画面や検索画面へのショートカットがよく実装されている印象を受けます。
引用元:iPhone 6s - 3D Touch - Apple(日本) http://www.apple.com/jp/iphone-6s/design/ (2015年12月15日)
一方、Peek & Popはアプリ内のお話になります。AppleのアプリではメールやSafariが代表的でしょうか。画面遷移せずに届いたメールの内容やリンク先のWebページをチラ見できます。
引用元:iPhone 6s - 3D Touch - Apple(日本) http://www.apple.com/jp/iphone-6s/design/ (2015年12月15日)
Peek & Pop を実装してみよう
今回は、触って楽しい見て楽しいPeek & Popを実装してみましょう。
とはいえ、Appleからシンプルなサンプルプログラムが提供されています*2し、すでに他所のブログ等で実装方法を拝見されている方が多いと思います。
そこで、この記事では実装方法については要所を押さえるにとどめて、UXの観点からPeek & Popの効果的な使い方について考察してみたいと思います。
アニマートでのPeek & Pop
実際に、Peek & Popを実装した弊社のアニメグッズ専門フリマiOSアプリ「アニマート」を例に解説していきます。
アニマートでは、起動後に表示されるホーム画面の各タブ内コンテンツでPeek & Popを体験できます。Peek中のクイックアクションについては、一部実装しているものの現在は公開していないので、純粋にチラ見機能ということになります。
実装は意外とかんたん!
例えば、スレッド(掲示板)のPeek & Popのために必要なコードはこれだけです*3。
class BoardThreadResultsViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() if self.traitCollection.forceTouchCapability == .Available { self.registerForPreviewingWithDelegate(self, sourceView: self.tableView) } } // 諸々省略 } extension BoardThreadResultsViewController: UIViewControllerPreviewingDelegate { func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { guard let indexPath = self.tableView.indexPathForRowAtPoint(location), cell = self.tableView.cellForRowAtIndexPath(indexPath) else { return nil } previewingContext.sourceRect = cell.frame return ThreadDetailViewController(thread: self.threads[indexPath.row]) } func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { self.navigationController?.pushViewController(viewControllerToCommit, animated: true) } }
実装について少し解説します。
Peek & Pop機能を使うには、対応させたい UIViewController
の viewDidLoad
で registerForPreviewingWithDelegate:sourceView:
を実行し、 UIViewControllerPreviewingDelegate
に適合する任意のインスタンスとPeekに対応するViewを登録します。
併せて、 UIViewControllerPreviewingDelegate
プロトコルの以下のメソッドを実装しておきます。
previewingContext:viewControllerForLocation:
previewingContext:commitViewController:
previewingContext:viewControllerForLocation:
previewingContext:viewControllerForLocation:
は、 registerForPreviewingWithDelegate:sourceView:
で登録したViewがタッチイベントを拾った際に実行されます。
引数の location: CGPoint
でタッチ位置が取得できるため、今回のケースでは UITableView
上で相当する NSIndexPath
を取得し、そこから UITableViewCell
のインスタンスを取得しています。
次に、もうひとつの引数である previewingContext: UIViewControllerPreviewing
の sourceRect: CGRect
プロパティに、Peekを発生させる位置とサイズをセットします。
これにより、Peekが発生する箇所以外にブラー効果がかかり、Peek時にふわっと浮いているかのように表示されます。
後は、実際にPeekで表示したい UIViewController
を生成して返すようにすれば完了です。
なお、このメソッドで nil
を返すとPeekされないため、意図的に表示したくない場合や不都合が生じた場合には nil
を返すようにします。
previewingContext:commitViewController:
previewingContext:commitViewController:
は、Peek時に更に押しこまれ、Popして画面遷移する必要が生じた際に実行されます。
引数の viewControllerToCommit: UIViewController
が現在Peek中のインスタンスです。今回のケースではこれをそのまま表示するだけで良いので、 Pushして画面遷移させています。
ちなみにデバッグは・・・
これもすでに結構いろんなところで言及されていますし、Appleのリリースノートにも記載がありますが、現在3D TouchはiOS Simulatorでは使えません。
そのため、デバッグするにはiPhone 6s/6s Plusが必要になります… 早くSimulatorでも対応して欲しいですね。。
ユーザーがもっと喜ぶPeek & Popとは
さて、これで普通に遷移後の画面をPeekさせる方法は分かりました。 このままでも充分に便利ですが、UXという観点から見た時、それは果たして充分でしょうか。もう一歩踏み込んで考えてみたいと思います。
有名アプリのUXを考慮したPeek例
今や芸能人も多数愛用するInstagram*4は、iPhone 6s/6s Plusのリリースに合わせて3D Touch対応アップデートを公開しました。
当時なるほどなーと関心したのですが、各ユーザーの画面をPeekさせると単純にその画面が表示されるのではなく、専用のレイアウトでユーザーがチラ見したい要素だけをしっかり見せているんです。
ユーザーが「チラ見したいのはなんなのか」
アニマートではフリマの商品個別画面があるのですが、この画面は上部にでかでかと商品の画像が表示されています。
そのため、この画面をそのままPeekするとチラ見の価値がずいぶん下がってしまいます。
ここでユーザー目線に立ってみます。
商品がたくさん並ぶタイムラインでは、商品写真、商品名、値段がわかります。
商品個別画面ではこれらに加えて、商品説明や商品状態、配送料の負担者、発送日の目安、他にも売り手の情報やコメントなどが閲覧できます。
まず、タイムラインで見えている商品写真は必要ありません。大きく分けるとこの3つが必要だと考えました。
- 商品状態
- 金額(配送料は別なのかどうか)
- 配送スケジュール
商品の詳細を知れる説明欄も重要な要素ですが、少なくともチラ見ということを考慮すると、上記に上げた3点よりは優先度が低いと思います。
また、商品の紹介文が長いケースも多いので、Peek画面に収まらないことも意識しなければなりません。
そもそも気になる場合にはPopして詳しく見る、というのがAppleが想定している使い方なので、やはり商品説明の優先度は少し低めに設定したいところです。
以上を踏まえて、アニマートのフリマ商品のPeekでは、次の様な画面を表示することにしました。
具体的な実装について
previewingContext:viewControllerForLocation:
で返却するPeek用のViewControllerを工夫します。
元々 ItemDetailViewController
が存在していたのですが、それとは別に ItemDetailPreviewingViewController
を作成し、これをPeekさせるようにしました。
このようにすると previewingContext:commitViewController:
の引数である viewControllerToCommit: UIViewController
には ItemDetailPreviewingViewController
のインスタンスがセットされているため、これは使いません。
本来表示したい ItemDetailViewController
のインスタンスを生成してPushで遷移させるようにしています。
Peek専用のViewControlelrを用意する際の注意点
Peek専用のViewControlelrを用意することで、UXの向上が期待できます。ですが、注意するべき点があります。
遷移先のViewControllerをそのままPeekさせた場合には、 viewDidLoad
が実行されて画面がレンダリングされるので、Pop時にはそのまま表示されます。
ですが、ViewControllerを分けることで、通信が2回必要になる可能性があります。(例えば、画面を表示するために通信が必要な場合)
ユーザーの使用シーンから通信環境を考慮すると、Previewで表示する要素に関してはうまく引き継ぎ、Pop後も表示されているのが理想だと思います。*5
まとめ
ここ最近のApp Storeを見ていると、多くのアプリが次々に3D Touchに対応したアップデートを公開しています。
来年発売される次期iPhoneでももちろん3D Touchが使えるはずなので、できるだけ早いタイミングで実装して感触を掴んでおくに越したことはありません。
その際、本記事で言及したようなPeekを実装すると、ユーザーは少しハッピーになるかもしれないよ、ということを頭の片隅に置いておいてもらえれば幸いです。
*1:iPhone 6sなら既読を付けずにLINEが読める!3D TouchのPeek&Pop対応でトークをプレビュー表示可能に(動画追加) - Engadget Japanese
*2:ViewControllerPreviews: Using the UIViewController previewing APIs - iOS Developer Library
*3:Peek & Popと直接関係のない部分は省略しています
*5:ちなみにInstragramは写真を改めて読み込みなおしているようでした