ObjecTips

Swift & Objective-C で iOS とか macOS とか

UITableViewCell を左スワイプしてボタンを表示するUI

UITableViewCell を左スワイプした時に表示されるボタンは iOS 7 までは削除ボタンのみに固定されていた。
削除ボタンのタイトルはデリゲートメソッド

- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;

でカスタマイズ可能。

iOS 8 以降では UITableViewRowAction クラスを使ってボタンのスタイル、数、テキストがカスタマイズできるようになった。

f:id:Koze:20150609003050p:plain

以下が上記画面の実装コード

まずポイントは以下のデリゲートメソッドを実装しておく必要がある事。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;

このメソッド自体は呼ばれないが、これを実装していないとセルが左スワイプに反応してくれない。*1

そして重要なのが iOS 8 で登場した以下のデリゲートメソッド

- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath;

ここで UITableViewRowAction の配列を返す事で左スワイプ時に表示するボタンのスタイルとアクションを定義する事ができる。
削除アクションの場合 deleteRowsAtIndexPaths:withRowAnimation: アクションを呼ぶ事で該当のセルが削除されるアニメーションを発生させる事ができる。
その他のアクションの場合 UITableViewRowAction のハンドラが呼ばれてもセルにはアクションボタンと削除ボタンが表示されたままで元の状態に戻らないので [tableView setEditing:NO animated:YES]; を呼んでセルを通常の状態に戻してやるのがポイント。

ボタンの数に上限は無く、画面に収まる範囲でいくつでもボタンを置ける。

f:id:Koze:20150609004727p:plain

ボタンの背景色は UITableViewRowActionbackgroundColor プロパティでカスタマイズできる。

f:id:Koze:20150609005149p:plain

UIColorcolorWithPatternImage: メソッドで画像から色を作ればグラデーション表示もできた。

f:id:Koze:20150609010520p:plain

現状タイトルだけしか設定できず、アイコン画像を設定できないのがちょっと残念。


ちなみに UITableViewRowAction を使用した際のViewの階層構造は以下のようになる。

f:id:Koze:20150616222636p:plain

カスタマイズしたアクションボタンに色が付いているのはもちろん、ボタンが乗っている UITableViewCellDeleteConfirmationView 自体に赤色が設定されているのに驚き。iOS 8ではデフォルトの削除ボタンを使用した時でもこの View の上に赤色の削除ボタンが subview として乗っかるView構成なので、デフォルトでもカスタムでもこの ConfirmationView 自体は表には表示されない。この View が赤色なのはiOS 7時代の名残なのかも?

そして確認したかったのはカスタムのアクションボタン、これは _UITableViewCellAcitonButton というクラスで表示されている事が分かる。
ここにアクセスする API が用意されればView階層を辿って Private クラスを触ったりしなくてもフォントを変えたりアイコンを設定したり簡単にアクションボタンをカスタマイズできる。
このボタンをカスタマイズする API が欲しい人は是非 Apple にレポートを。

*1:iOS 9以降ではこのメソッドを実装しなくても動くようになった。