ユーザーがテーブルビューでセルをスワイプしたときに「詳細」ボタンを作成する方法(ios 7のメールアプリのように)
私はこことCocoa Touchフォーラムの両方でこの情報を探していましたが、私は答えを見つけることができないようで、私自身が解決策をくれるより賢い人を望んでいます。
ユーザーがTable View Cellをスワイプして複数の編集ボタンを表示するようにしたい(彼のデフォルトは削除ボタンです)。 iOS 7用のMailアプリでは、削除するためにスワイプすることができますが、表示される "MORE"ボタンがあります。
IOS 8がこのAPIを公開しているようです。このような機能のヒントはBeta 2にあります。
機能するようにするには、UITableViewのデリゲートに次の2つのメソッドを実装して目的の効果を得ます(例についてはGistを参照)。
- tableView:editActionsForRowAtIndexPath:
- tableView:commitEditingStyle:forRowAtIndexPath:
ドキュメントにはtableView:commitEditingStyle:forRowAtIndexPathは次のように記載されています。
「UITableViewRowActionを使用した編集アクションに対しては呼び出されません。代わりにアクションのハンドラが呼び出されます。」
しかし、スワイプはそれなしでは機能しません。メソッドスタブが空白の場合でも、今のところまだ必要です。これは明らかにbeta 2のバグです。
https://Twitter.com/marksands/status/481642991745265664https://Gist.github.com/ marksands/76558707f583dbb8f870
元の回答: https://stackoverflow.com/a/24540538/870028
これを使ったサンプルコード(Swift): http://dropbox.com/s/0fvxosft2mq2v5m/DeleteRowExampleSwift.Zip
サンプルコードのMasterViewController.Swiftには、このわかりやすいメソッドが含まれています。このメソッドを使用すると、OPスクリーンショットに示す動作が得られます。
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in
println("MORE•ACTION");
});
moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);
var deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
println("DELETE•ACTION");
});
return [deleteRowAction, moreRowAction];
}
私は、iOS 8メールアプリのようにさまざまな切り替えや拡張可能なボタンをサポートする、切り替え可能なボタンを実装するための新しいライブラリを作成しました。
https://github.com/MortimerGoro/MGSwipeTableCell
このライブラリは、UITableViewCellを作成するさまざまな方法と互換性があり、iOS 5、iOS 6、iOS 7、およびiOS 8でテスト済みです。
これがいくつかの遷移の例です。
国境移行:
クリップトランジション
3Dトランジション:
ジョニーの答えは正当化するのに正しいものです。私はそれを初心者(そしてSwiftの構文を学ぶことを拒む私たちの人々)をより明確にするためにこれを目的-cの下に加えているだけです。
必ずuitableviewdelegateを宣言し、次のメソッドを持ってください。
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
NSLog(@"Action to perform with Button 1");
}];
button.backgroundColor = [UIColor greenColor]; //arbitrary color
UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
NSLog(@"Action to perform with Button2!");
}];
button2.backgroundColor = [UIColor blueColor]; //arbitrary color
return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work:
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES; //tableview must be editable or nothing will work...
}
これは(かなりばかげて)プライベートAPIです。
次の2つのメソッドはプライベートで、UITableViewのデリゲートに送信されます。
-(NSString *)tableView:(UITableView *)tableView titleForSwipeAccessoryButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
-(void)tableView:(UITableView *)tableView swipeAccessoryButtonPushedForRowAtIndexPath:(NSIndexPath *)indexPath;
彼らはかなり自明です。
Johnnyの答えを改善するために、これは以下のようにパブリックAPIを使用して行うことができます。
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "More", handler:{action, indexpath in
print("MORE•ACTION");
});
moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);
let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Delete", handler:{action, indexpath in
print("DELETE•ACTION");
});
return [deleteRowAction, moreRowAction];
}
Appleがあなたに必要なものを提供するまで待つことができないことを望みますか。だからここに私の選択です。
カスタムセルを作成します。 2つのuiviewsがあります
1. upper
2. lower
下のビューで、必要なボタンを追加します。他のIBActionと同じようにそのアクションを処理します。あなたは、アニメーションの時間、スタイルなど何でも決めることができます。
上のビューにワイプジェスチャーを追加し、下のビューをスワイプジェスチャーで表示します。私は以前にこれをしました、そして、私が考える限りそれは最も簡単なオプションです。
お役に立てば幸いです。
これは標準のSDKでは不可能です。ただし、Mail.appの動作を多かれ少なかれ模倣するさまざまなサードパーティソリューションがあります。そのうちのいくつか(例: MCSwipeTableViewCell 、 DAContextMenuTableViewController 、 RMSwipeTableViewCell )ジェスチャ認識機能を使用してスワイプを検出します。それらの一部(例: SWTableViewCell )は2番目のUISScrollViewを配置します。標準のUITableViewCellScrollView
(UITableViewCell
のプライベートサブビュー)の下にあり、それらのいくつかはUITableViewCellScrollView
の動作を変更します。
タッチ操作が最も自然に感じられるので、私は最後のアプローチが最も好きです。具体的には、 MSCMoreOptionTableViewCell が良いです。あなたの選択はあなたの特定のニーズ(あなたが左から右へのパンを必要とするかどうか、あなたがiOS 6互換性を必要とするかどうかなど)によって変わるかもしれません。また、これらのアプローチのほとんどには負担が伴うことにも注意してください。AppleがUITableViewCell
サブビュー階層を変更すると、将来のiOSバージョンでは簡単に壊れる可能性があります。
Swift 3のバージョンコードをライブラリを使わずに:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.tableFooterView = UIView(frame: CGRect.zero) //Hiding blank cells.
tableView.separatorInset = UIEdgeInsets.zero
tableView.dataSource = self
tableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
return cell
}
//Enable cell editing methods.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let more = UITableViewRowAction(style: .normal, title: "More") { action, index in
//self.isEditing = false
print("more button tapped")
}
more.backgroundColor = UIColor.lightGray
let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in
//self.isEditing = false
print("favorite button tapped")
}
favorite.backgroundColor = UIColor.orange
let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in
//self.isEditing = false
print("share button tapped")
}
share.backgroundColor = UIColor.blue
return [share, favorite, more]
}
}
UITableViewCell
とサブクラスメソッドwillTransitionToState:(UITableViewCellStateMask)state
をサブクラス化する必要があります。これはユーザーがセルをスワイプするたびに呼び出されます。 state
フラグは、Deleteボタンが表示されているかどうかを知らせ、そこにMoreボタンを表示/隠します。
残念ながら、この方法では[削除]ボタンの幅もアニメーション時間も得られません。だから、あなたは自分のMoreボタンのフレームとアニメーションの時間をあなたのコードにオブザーバーしてハードコードする必要がある(私は個人的にAppleはこれについて何かする必要があると思う)。
Swiftプログラミング用
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
deleteModelAt(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
else if editingStyle == UITableViewCellEditingStyle.Insert {
println("insert editing action")
}
}
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
var archiveAction = UITableViewRowAction(style: .Default, title: "Archive",handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
// maybe show an action sheet with more options
self.tableView.setEditing(false, animated: false)
}
)
archiveAction.backgroundColor = UIColor.lightGrayColor()
var deleteAction = UITableViewRowAction(style: .Normal, title: "Delete",
handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
self.deleteModelAt(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic);
}
);
deleteAction.backgroundColor = UIColor.redColor()
return [deleteAction, archiveAction]
}
func deleteModelAt(index: Int) {
//... delete logic for model
}
これは助けになるでしょう。
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
NSLog(@"Action to perform with Button 1");
}];
button.backgroundColor = [UIColor greenColor]; //arbitrary color
UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
NSLog(@"Action to perform with Button2!");
}];
button2.backgroundColor = [UIColor blueColor]; //arbitrary color
return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work:
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES; //tableview must be editable or nothing will work...
}
IOS 11以降、これはUITableViewDelegate
で公開されています。ここにいくつかのサンプルコードがあります:
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive
title:@"DELETE"
handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
NSLog(@"index path of delete: %@", indexPath);
completionHandler(YES);
}];
UIContextualAction *rename = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
title:@"RENAME"
handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
NSLog(@"index path of rename: %@", indexPath);
completionHandler(YES);
}];
UISwipeActionsConfiguration *swipeActionConfig = [UISwipeActionsConfiguration configurationWithActions:@[rename, delete]];
swipeActionConfig.performsFirstActionWithFullSwipe = NO;
return swipeActionConfig;
}
また利用できる:
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath;
Swift 4&iOs 11+
@available(iOS 11.0, *)
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .destructive, title: "Delete") { _, _, handler in
handler(true)
// handle deletion here
}
let more = UIContextualAction(style: .normal, title: "More") { _, _, handler in
handler(true)
// handle more here
}
return UISwipeActionsConfiguration(actions: [delete, more])
}
実際のSwift 3回答
これはあなたが必要とする唯一の機能です。カスタムアクションにCanEdit関数やCommitEditingStyle関数は必要ありません。
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let action1 = UITableViewRowAction(style: .default, title: "Action1", handler: {
(action, indexPath) in
print("Action1")
})
action1.backgroundColor = UIColor.lightGray
let action2 = UITableViewRowAction(style: .default, title: "Action2", handler: {
(action, indexPath) in
print("Action2")
})
return [action1, action2]
}
私は自分のアプリに同じ機能を追加しようと思っていましたが、非常に多くの異なるチュートリアル( raywenderlich が最良のDIYソリューション)を経験した後非常に便利な独自のUITableViewRowAction
class。
Tableviewのboilerpointメソッドをこれに変更する必要があります。
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
// 1
var shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
// 2
let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .ActionSheet)
let twitterAction = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default, handler: nil)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
shareMenu.addAction(twitterAction)
shareMenu.addAction(cancelAction)
self.presentViewController(shareMenu, animated: true, completion: nil)
})
// 3
var rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Rate" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
// 4
let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .ActionSheet)
let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.Default, handler: nil)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
rateMenu.addAction(appRateAction)
rateMenu.addAction(cancelAction)
self.presentViewController(rateMenu, animated: true, completion: nil)
})
// 5
return [shareAction,rateAction]
}
This Site でこれについてもっと知ることができます。アップルの 独自のドキュメント は、背景色を変更するのに非常に便利です。
アクションボタンの背景色。
宣言OBJECTIVE-C @property(nonatomic、copy)UIColor * backgroundColor解説このプロパティを使用して、ボタンの背景色を指定します。このプロパティに値を指定しないと、UIKitはstyleプロパティの値に基づいてデフォルトの色を割り当てます。
提供時期iOS 8.0以降で利用できます。
ボタンのフォントを変更したい場合は、もう少し注意が必要です。 SOで 別の投稿 を見ました。コードとリンクを提供するために、ここで彼らが使用したコードがあります。ボタンの外観を変更する必要があります。あなたはtableviewcellへの特定の参照をしなければならないでしょう、さもなければあなたはあなたのアプリを通してボタンの外観を変えるでしょう(私はそれを望んでいませんでした、しかしあなたは、私は知りません:))
目標C:
+ (void)setupDeleteRowActionStyleForUserCell {
UIFont *font = [UIFont fontWithName:@"AvenirNext-Regular" size:19];
NSDictionary *attributes = @{NSFontAttributeName: font,
NSForegroundColorAttributeName: [UIColor whiteColor]};
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString: @"DELETE"
attributes: attributes];
/*
* We include UIView in the containment hierarchy because there is another button in UserCell that is a direct descendant of UserCell that we don't want this to affect.
*/
[[UIButton appearanceWhenContainedIn:[UIView class], [UserCell class], nil] setAttributedTitle: attributedTitle
forState: UIControlStateNormal];
}
迅速:
//create your attributes however you want to
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(UIFont.systemFontSize())] as Dictionary!
//Add more view controller types in the []
UIButton.appearanceWhenContainedInInstancesOfClasses([ViewController.self])
これは最も簡単で、最も合理化されたバージョンの私見です。それが役に立てば幸い。
更新:これはSwift 3.0バージョンです:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
var shareAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Share", handler: {(action, cellIndexpath) -> Void in
let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .actionSheet)
let twitterAction = UIAlertAction(title: "Twitter", style: .default, handler: nil)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
shareMenu.addAction(twitterAction)
shareMenu.addAction(cancelAction)
self.present(shareMenu,animated: true, completion: nil)
})
var rateAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Rate" , handler: {(action, cellIndexpath) -> Void in
// 4
let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)
let appRateAction = UIAlertAction(title: "Rate", style: .default, handler: nil)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
rateMenu.addAction(appRateAction)
rateMenu.addAction(cancelAction)
self.present(rateMenu, animated: true, completion: nil)
})
// 5
return [shareAction,rateAction]
}
複数のデータを表示するためにtableViewCellを使い、セル上で右から左へスワイプ()した後に2つのボタンが表示されます1つの引数を取り、もう1つはRejectFuncで、これも1つの引数を取ります。
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let Approve = UITableViewRowAction(style: .normal, title: "Approve") { action, index in
self.ApproveFunc(indexPath: indexPath)
}
Approve.backgroundColor = .green
let Reject = UITableViewRowAction(style: .normal, title: "Reject") { action, index in
self.rejectFunc(indexPath: indexPath)
}
Reject.backgroundColor = .red
return [Reject, Approve]
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func ApproveFunc(indexPath: IndexPath) {
print(indexPath.row)
}
func rejectFunc(indexPath: IndexPath) {
print(indexPath.row)
}
Swift 4
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, sourceView, completionHandler) in
print("index path of delete: \(indexPath)")
completionHandler(true)
}
let rename = UIContextualAction(style: .normal, title: "Edit") { (action, sourceView, completionHandler) in
print("index path of edit: \(indexPath)")
completionHandler(true)
}
let swipeActionConfig = UISwipeActionsConfiguration(actions: [rename, delete])
swipeActionConfig.performsFirstActionWithFullSwipe = false
return swipeActionConfig
}
これは、やや脆弱な方法で、プライベートAPIを使用したり、独自のシステムを構築したりすることはありません。あなたは、Appleがこれを破らないこと、そしておそらくこれらの数行のコードを置き換えることができるAPIをリリースすることを賭けている。
これには、標準のテーブルビュー編集デリゲートコールバックを実装する必要もあります。
static char kObserveContext = 0;
@implementation KZTableViewCell {
UIScrollView *_contentScrollView;
UIView *_confirmationView;
UIButton *_editButton;
UIButton *_deleteButton;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_contentScrollView = (id)self.contentView.superview;
[_contentScrollView.layer addObserver:self
forKeyPath:@"sublayers"
options:0
context:&kObserveContext];
_editButton = [UIButton new];
_editButton.backgroundColor = [UIColor lightGrayColor];
[_editButton setTitle:@"Edit" forState:UIControlStateNormal];
[_editButton addTarget:self
action:@selector(_editTap)
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(void)dealloc {
[_contentScrollView.layer removeObserver:self forKeyPath:@"sublayers" context:&kObserveContext];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(context != &kObserveContext) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if(object == _contentScrollView.layer) {
for(UIView * view in _contentScrollView.subviews) {
if([NSStringFromClass(view.class) hasSuffix:@"ConfirmationView"]) {
_confirmationView = view;
_deleteButton = [view.subviews objectAtIndex:0];
CGRect frame = _confirmationView.frame;
CGRect frame2 = frame;
frame.Origin.x -= frame.size.width;
frame.size.width *= 2;
_confirmationView.frame = frame;
frame2.Origin = CGPointZero;
_editButton.frame = frame2;
frame2.Origin.x += frame2.size.width;
_deleteButton.frame = frame2;
[_confirmationView addSubview:_editButton];
break;
}
}
return;
}
}
-(void)_editTap {
UITableView *tv = (id)self.superview;
while(tv && ![tv isKindOfClass:[UITableView class]]) {
tv = (id)tv.superview;
}
id<UITableViewDelegate> delegate = tv.delegate;
if([delegate respondsToSelector:@selector(tableView:editTappedForRowWithIndexPath:)]) {
NSIndexPath *ip = [tv indexPathForCell:self];
// define this in your own protocol
[delegate tableView:tv editTappedForRowWithIndexPath:ip];
}
}
@end
SwipeCellKit
と呼ばれる素晴らしいライブラリがあります。私の意見では、それはMGSwipeTableCell
よりも涼しいです。後者はMailアプリのセルの振る舞いを完全には再現しませんが、SwipeCellKit
は再現します。 見てください
これが1つの簡単な解決策です。 UITableViewCell内でカスタムUIViewを表示および非表示にすることができます。表示ロジックは、UITableViewCell、BaseTableViewCellから拡張されたクラス内に含まれています。
BaseTableViewCell.h
#import <UIKit/UIKit.h>
@interface BaseTableViewCell : UITableViewCell
@property(nonatomic,strong)UIView* customView;
-(void)showCustomView;
-(void)hideCustomView;
@end
BaseTableViewCell.M
#import "BaseTableViewCell.h"
@interface BaseTableViewCell()
{
BOOL _isCustomViewVisible;
}
@end
@implementation BaseTableViewCell
- (void)awakeFromNib {
// Initialization code
}
-(void)prepareForReuse
{
self.customView = nil;
_isCustomViewVisible = NO;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)showCustomView
{
if(nil != self.customView)
{
if(!_isCustomViewVisible)
{
_isCustomViewVisible = YES;
if(!self.customView.superview)
{
CGRect frame = self.customView.frame;
frame.Origin.x = self.contentView.frame.size.width;
self.customView.frame = frame;
[self.customView willMoveToSuperview:self.contentView];
[self.contentView addSubview:self.customView];
[self.customView didMoveToSuperview];
}
__weak BaseTableViewCell* blockSelf = self;
[UIView animateWithDuration:.5 animations:^(){
for(UIView* view in blockSelf.contentView.subviews)
{
CGRect frame = view.frame;
frame.Origin.x = frame.Origin.x - blockSelf.customView.frame.size.width;
view.frame = frame;
}
}];
}
}
}
-(void)hideCustomView
{
if(nil != self.customView)
{
if(_isCustomViewVisible)
{
__weak BaseTableViewCell* blockSelf = self;
_isCustomViewVisible = NO;
[UIView animateWithDuration:.5 animations:^(){
for(UIView* view in blockSelf.contentView.subviews)
{
CGRect frame = view.frame;
frame.Origin.x = frame.Origin.x + blockSelf.customView.frame.size.width;
view.frame = frame;
}
}];
}
}
}
@end
この機能を取得するには、BaseTableViewCellからテーブルビューセルを単純に拡張します。
次に、UITableViewDelegateを実装するInside UIViewControllerで、左右のスワイプを処理する2つのジェスチャ認識機能を作成します。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.tableView registerNib:[UINib nibWithNibName:CUSTOM_CELL_NIB_NAME bundle:nil] forCellReuseIdentifier:CUSTOM_CELL_ID];
UISwipeGestureRecognizer* leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipe:)];
leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.tableView addGestureRecognizer:leftSwipeRecognizer];
UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightSwipe:)];
rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.tableView addGestureRecognizer:rightSwipeRecognizer];
}
スワイプハンドラを2つ追加するより
- (void)handleLeftSwipe:(UISwipeGestureRecognizer*)recognizer
{
CGPoint point = [recognizer locationInView:self.tableView];
NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];
if([cell respondsToSelector:@selector(showCustomView)])
{
[cell performSelector:@selector(showCustomView)];
}
}
- (void)handleRightSwipe:(UISwipeGestureRecognizer*)recognizer
{
CGPoint point = [recognizer locationInView:self.tableView];
NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];
if([cell respondsToSelector:@selector(hideCustomView)])
{
[cell performSelector:@selector(hideCustomView)];
}
}
これで、UITableViewDelegateのcellForRowAtIndexPath内で、カスタムUIViewを作成し、それをデキューされたセルに添付することができます。
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableViewCell* cell = (CustomCellTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"CustomCellTableViewCell" forIndexPath:indexPath];
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"CellCustomView"
owner:nil
options:nil];
CellCustomView* customView = (CellCustomView*)[ nibViews objectAtIndex: 0];
cell.customView = customView;
return cell;
}
もちろん、このカスタムUIViewのロード方法は、この例に過ぎません。必要に応じて管理してください。