2012-08-258/25担当の@masaichiです。qiitaも初投稿です。今回、sparrowやtwitterのクライアントで良く使われている、セルをスワイプするとスライドして下からメニューが出てくる機能を実装してみる、というお話です。メールやtwitterを使っていて多いのは、多分、その項目に対して返信したり、favをつけたりする事だと思いますが、セルをさっとスワイプすることでメニューが出てきて機能を選ぶ事ができるので大変便利です。最近ではこの機能を組み込んでいるアプリも多く、定番のインターフェスになってきた感があります。ちなみに出来上がったものはこちらです。(ライブラリとしてはまだテスト段階です)本文中はその中から抜粋してソースを載せていますが、細かい処理など省いていますので、githubのソースも合わせて参照してください。今回はスワイプするとビューがスライドするカスタムセル(RevealTableViewCell)と、それを利用するTableViewControllerを作りました。カスタムセルまずはRevealTableViewCellを作ります。前面に表示するビュー(frontContentView)と、スライドすると出てくるビュー(backContentView)をcontentViewに重ねて配置します。self.contentView.bounds;}@end前面に配置したビューをスワイプ操作に応じてずらしてあげることで、下に配置したビューが見えるという構造です。配置したところでずらせるようにしてみましょうドラッグして動かしてみるドラッグ操作はtouchesBegan〜touchesEndedを上書きして実装しました。UISwipeGestureRecognizerを使って実装しても良かったのですが、ドラッグできるようにしたいなーと思って上記の方法を取ることにしました。実装はこんな感じです。setScrollEnabled:enabled];}@endtouchesBeganで最初にタッチされた位置を保存しておいて、touchesMovedでの位置と開始位置の差分を取って、frontContentViewをその差分だけずらしてあげています。横になぞる操作は縦にも動いてしまいがちで、縦スクロールが発生してしまうので、touchesMovedのタイミングでTableViewのスクロールを無効にしています。スライドのアニメーション次は指を離したタイミングでシュパッとスライドさせてしまうようにします。スライドをさせる処理はUIViewのアニメーションを使えば簡単に出来ますね。スピード感を出すために、時間は最大で0.1秒で動作もEaseInOutではなくLinearで指定しています。指を離した位置に応じてアニメーションをさせる時間を小さくしています。最初の方であれば通常通り0.1秒間アニメーションするようになります。...}指を離したタイミング、つまりtouchesEndedで上記の関数を呼んであげます。その際、指を動かしている方向に向かってスライドが走ると自然ですね。今回の場合、左に向かってスワイプしているときはshowを右に向かってスワイプしているときはhideを呼んであげるようにします。実際に使ってみると、指を離した瞬間というのは位置がブレていて、意図した挙動になりませんでした。そこで、touchesMovedで移動方向をいくつか記録しておいて判断するように実装しています。}}スワイプしている方向を判断するロジック、これでうまく動いていますが、もう少しスマートな方法があるかもしれないです。(あったら教えてください)さてこれでスワイプして上のビューをどかせるようになりました。あとはdelegateなりなんなりで、ViewControllerにスワイプされたよーなど通知してあげて、連携を取れば良さそうです。UITableViewControllerから使うViewController側の実装ですが、今回は以下のような挙動を実現します。他のセルが触られたら、開いているセルは閉じるスクロールされたら開いているセルを閉じる上記2点を実現するために、ViewControllerで現在開いているセルを保持してあげれば良さそうです。セルからViewControllerへ状態をコールバックしてあげて、ViewControllerはそれを受け取り応じた処理をするようにしましょう。hideBackContentViewAnimated:YES];}ViewController側からの微調整ここまででも動くには動きますが、メニューを開いたのにdidSelectRowがコールバックされたりと誤爆が多いです。その他、スワイプするつもりがスクロールしてしまいtouchesBeganが呼ばれず処理が走らない等の問題があります。そのため、ViewController側で誤爆防止や自然な挙動のために微調整をします。スワイプの反応が悪いUITableViewのdelaysContentTouchesをNOにしてあげると即座にtouchesBeganが呼ばれるようになり、反応が良くなります。NO;}didSelectRowの誤爆UITableViewDelegateに(NSIndexPath*)tableView:willSelectRowAtIndexPath:というメソッドがあり、これでnilを返すとdidSelectRowをキャンセルできます。多少泥臭いですが、いまのセルの状態を見て、アニメーションしている場合にはnilを返して抑制してあげるようにします。indexPath;}ここらへんのところはセルのカスタマイズだけでなんとか解決したかったのですが、ちょっと厳しそうでViewControllerで対応をしました。何か良い方法をご存知の方がいたら教えてください!実際には、もう少し細かい判定や制御を入れてありますが、長くなってしまうので割愛しました。まとめスワイプしてメニューを表示するセルの実装ができました。細かく挙動を制御できるので実装してみて損はなかったかなと思います。