Custom edit view in UITableViewCell while swipe left. Objective-C or Swift
Solution 1
Just copy paste the code below!
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewRowAction *editAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"Clona" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//insert your editAction here
}];
editAction.backgroundColor = [UIColor blueColor];
UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//insert your deleteAction here
}];
deleteAction.backgroundColor = [UIColor redColor];
return @[deleteAction,editAction];
}
Solution 2
Swift 3
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let editAction = UITableViewRowAction(style: .normal, title: "Edit") { (rowAction, indexPath) in
//TODO: edit the row at indexPath here
}
editAction.backgroundColor = .blue
let deleteAction = UITableViewRowAction(style: .normal, title: "Delete") { (rowAction, indexPath) in
//TODO: Delete the row at indexPath here
}
deleteAction.backgroundColor = .red
return [editAction,deleteAction]
}
Swift 2.1
func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let editAction = UITableViewRowAction(style: .Normal, title: "Edit") { (rowAction:UITableViewRowAction, indexPath:NSIndexPath) -> Void in
//TODO: edit the row at indexPath here
}
editAction.backgroundColor = UIColor.blueColor()
let deleteAction = UITableViewRowAction(style: .Normal, title: "Delete") { (rowAction:UITableViewRowAction, indexPath:NSIndexPath) -> Void in
//TODO: Delete the row at indexPath here
}
deleteAction.backgroundColor = UIColor.redColor()
return [editAction,deleteAction]
}
Note: for iOS 8 onwards
Solution 3
You can use UITableViewRowAction
's backgroundColor
to set custom image or view. The trick is using UIColor(patternImage:)
.
Basically the width of UITableViewRowAction
area is decided by its title, so you can find a exact length of title(or whitespace) and set the exact size of image with patternImage
.
To implement this, I made a UIView
's extension method.
func image() -> UIImage {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
guard let context = UIGraphicsGetCurrentContext() else {
return UIImage()
}
layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
and to make a string with whitespace and exact length,
fileprivate func whitespaceString(font: UIFont = UIFont.systemFont(ofSize: 15), width: CGFloat) -> String {
let kPadding: CGFloat = 20
let mutable = NSMutableString(string: "")
let attribute = [NSFontAttributeName: font]
while mutable.size(attributes: attribute).width < width - (2 * kPadding) {
mutable.append(" ")
}
return mutable as String
}
and now, you can create UITableViewRowAction
.
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let whitespace = whitespaceString(width: kCellActionWidth)
let deleteAction = UITableViewRowAction(style: .`default`, title: whitespace) { (action, indexPath) in
// do whatever you want
}
// create a color from patter image and set the color as a background color of action
let kActionImageSize: CGFloat = 34
let view = UIView(frame: CGRect(x: 0, y: 0, width: kCellActionWidth, height: kCellHeight))
view.backgroundColor = UIColor.white
let imageView = UIImageView(frame: CGRect(x: (kCellActionWidth - kActionImageSize) / 2,
y: (kCellHeight - kActionImageSize) / 2,
width: 34,
height: 34))
imageView.image = UIImage(named: "x")
view.addSubview(imageView)
let image = view.image()
deleteAction.backgroundColor = UIColor(patternImage: image)
return [deleteAction]
}
The result will look like this.
Another way to do this is to import custom font which has the image you want to use as a font and use UIButton.appearance
. However this will affect other buttons unless you manually set other button's font.
From iOS 11, it will show this message [TableView] Setting a pattern color as backgroundColor of UITableViewRowAction is no longer supported.
. Currently it is still working, but it wouldn't work in the future update.
==========================================
For iOS 11+, you can use:
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .normal, title: "Delete") { (action, view, completion) in
// Perform your action here
completion(true)
}
let muteAction = UIContextualAction(style: .normal, title: "Mute") { (action, view, completion) in
// Perform your action here
completion(true)
}
deleteAction.image = UIImage(named: "icon.png")
deleteAction.backgroundColor = UIColor.red
return UISwipeActionsConfiguration(actions: [deleteAction, muteAction])
}
Solution 4
You Can try this,
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let backView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
backView.backgroundColor = #colorLiteral(red: 0.933103919, green: 0.08461549133, blue: 0.0839477703, alpha: 1)
let myImage = UIImageView(frame: CGRect(x: 30, y: backView.frame.size.height/2-14, width: 16, height: 16))
myImage.image = #imageLiteral(resourceName: "rubbish-bin")
backView.addSubview(myImage)
let label = UILabel(frame: CGRect(x: 0, y: myImage.frame.origin.y+14, width: 80, height: 25))
label.text = "Remove"
label.textAlignment = .center
label.textColor = UIColor.white
label.font = UIFont(name: label.font.fontName, size: 14)
backView.addSubview(label)
let imgSize: CGSize = tableView.frame.size
UIGraphicsBeginImageContextWithOptions(imgSize, false, UIScreen.main.scale)
let context = UIGraphicsGetCurrentContext()
backView.layer.render(in: context!)
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let delete = UITableViewRowAction(style: .destructive, title: " ") { (action, indexPath) in
print("Delete")
}
delete.backgroundColor = UIColor(patternImage: newImage)
return [delete, share]
}
Solution 5
Refer this link : https://github.com/TeehanLax/UITableViewCell-Swipe-for-Options
And customize your uitableviewcell with multiple button.
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) + kCatchWidth, CGRectGetHeight(self.bounds));
scrollView.delegate = self;
scrollView.showsHorizontalScrollIndicator = NO;
[self.contentView addSubview:scrollView];
self.scrollView = scrollView;
UIView *scrollViewButtonView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds) - kCatchWidth, 0, kCatchWidth, CGRectGetHeight(self.bounds))];
self.scrollViewButtonView = scrollViewButtonView;
[self.scrollView addSubview:scrollViewButtonView];
// Set up our two buttons
UIButton *moreButton = [UIButton buttonWithType:UIButtonTypeCustom];
moreButton.backgroundColor = [UIColor colorWithRed:0.78f green:0.78f blue:0.8f alpha:1.0f];
moreButton.frame = CGRectMake(0, 0, kCatchWidth / 3.0f, CGRectGetHeight(self.bounds));
[moreButton setTitle:@"More" forState:UIControlStateNormal];
[moreButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[moreButton addTarget:self action:@selector(userPressedMoreButton:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollViewButtonView addSubview:moreButton];
UIButton *shareButton = [UIButton buttonWithType:UIButtonTypeCustom];
shareButton.backgroundColor = [UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f];
shareButton.frame = CGRectMake(kCatchWidth / 3.0f, 0, kCatchWidth / 3.0f, CGRectGetHeight(self.bounds));
[shareButton setTitle:@"Share" forState:UIControlStateNormal];
[shareButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[shareButton addTarget:self action:@selector(userPressedMoreButton:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollViewButtonView addSubview:shareButton];
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
deleteButton.backgroundColor = [UIColor colorWithRed:1.0f green:0.231f blue:0.188f alpha:1.0f];
deleteButton.frame = CGRectMake(kCatchWidth / 3.0f+kCatchWidth / 3.0f, 0, kCatchWidth / 3.0f, CGRectGetHeight(self.bounds));
[deleteButton setTitle:@"Delete" forState:UIControlStateNormal];
[deleteButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[deleteButton addTarget:self action:@selector(userPressedDeleteButton:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollViewButtonView addSubview:deleteButton];
UIView *scrollViewContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
scrollViewContentView.backgroundColor = [UIColor whiteColor];
[self.scrollView addSubview:scrollViewContentView];
self.scrollViewContentView = scrollViewContentView;
UILabel *scrollViewLabel = [[UILabel alloc] initWithFrame:CGRectInset(self.scrollViewContentView.bounds, 10, 0)];
self.scrollViewLabel = scrollViewLabel;
[self.scrollViewContentView addSubview:scrollViewLabel];
-
I have implemented this code with my app got such result. You can add number of button in swipe cell.
Here is implemented screen shots
After swipe the cell 3 buttons appears "More","Share","Delete".
Related videos on Youtube
ugoarangino
18, blogger, software developer, german and italian
Updated on October 23, 2021Comments
-
ugoarangino over 2 years
How to make a custom edit view in iOS7 UITableView with Objective C like the Evernote or the Apple Reminders app while swipe left. I have tried to set an custom editingAccessoryView, but this didn't work.
Evernote edit view:
Reminders edit view:
My current code is
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { NSLog(@"delete"); } }
I have tried to solve the problem with: (UITableViewController.h)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //make cell UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; [view setBackgroundColor:[UIColor greenColor]]; //add Buttons to view cell.editingAccessoryView = view; return cell; }
And the same with: (UITableViewCell)
- (void)willTransitionToState:(UITableViewCellStateMask)state; - (void)setEditing:(BOOL)editing animated:(BOOL)animated; - (UIView*)editingAccessoryView;
-
Suhas Arvind Patil over 4 yearscan we make the height fix for the side swipe buttons? eg: my cell is 150 and i want button to be show only 50.0f is it possible?
-
-
u2Fan almost 9 yearsTo get these to show up in my case, I also needed to implement the table view's dataSource method - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; Even an empty implementation of this method was sufficient to get the buttons to show up.
-
MattyG over 8 yearsI've converted this to Swift and posted it as a new answer below. stackoverflow.com/a/33748345/470879
-
Kartik 123 over 8 years@sohil which image? you are having an imageview in your cell? So you are getting a handler in that method which i have written which will be called when you tap on any of the buttons
-
Jerland2 about 7 yearsCould you clarrify the func image() -> UIImage {} I have errors ebcause there is no varaible bounds.size in its first line. likewise in the 5th line hthere is no layer variable... Since the function does not take in any variables. Thank you
-
Ryan about 7 yearsThat is an 'UIView''s extension. So bounds will be the instance's bounds.
-
Jerland2 about 7 yearsTHIS IS AWESOME, exactly what I was looking for. Very creative implementation, love it! Thank you
-
mythicalcoder about 7 yearsbut the swipe is NOT having any effect !! in swift3 Any other methods needed ?
-
mythicalcoder about 7 yearsswift 3 - Swipe doesn't seem to work !! No options are shown !!
-
MattyG about 7 years@Maven, have you implemented canEditRowAtIndexPath to return true?
-
TheCodingArt about 7 yearsFYI, you shouldn't be using init directly:
deleteAction.backgroundColor = UIColor.init(patternImage: image)
should bedeleteAction.backgroundColor = UIColor(patternImage: image)
. Awesome answer though -
mattsson about 7 yearsThis doesn't attempt to answer the question. The submitter specifically asked how to set icons for the swipe actions instead of text.
-
MattyG about 7 years@mattsson, the question is vague in that regard, and doesn't mention icons at all. It mentions Evernote and Apple Reminders as examples. The Apple Reminders app uses a standard implementation like this answer.
-
mattsson about 7 years@MattyG You're completely right, I don't know what I was thinking.
-
reojased about 7 yearsI've noticed you also need to at least write
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { }
oreditActionsForRowAtIndexPath
won't be called -
krlbsk almost 7 yearsGreat answer. Thanks a lot!
-
nyxee almost 7 years
tableView(_, commit:, forRowAt:) { }
as mentioned above -
Jan almost 7 yearshow to add images instead of text?
-
Travis M. over 6 yearsThis solution was exactly what I was looking for but unfortunately, it will only work for very small images because the "whitespace" padding no longer increases the size past the minimum width. I tried a non-breaking space \u{00a0} but it still is always the minimum size. I wonder if there's another unicode character that's blank that actually takes up space?
-
Legonaftik over 6 yearsIsn't there a memory leak when you create a closure which references to
self
? -
Harshith Rai over 5 yearswould be nice if you added some explanation in the answer itself buddy.
-
Majid Bashir almost 5 yearswhat about from iOS 9 and above ?
-
Vinay Kharb almost 5 years@MajidBashir My apps do not support the older iOS versions. Sorry, unable to help.
-
James Wolfe almost 5 yearsIt would, but I believe the code speaks for itself in this case (considering comments are included and function names are pretty self explainitory)
-
A.s.ALI almost 5 yearsIt is now working for section headers, do you why?
-
Suhas Arvind Patil over 4 yearscan we make the height fix for the side swipe buttons? eg: my cell is 150 and i want button to be show only 50.0f is it possible?
-
Maulik shah over 3 yearsdo you have example
-
mojuba over 3 yearsAlso setting the background color is not necessary. For destructive actions use the .destructive style, for others it can be .normal, in this case some system defaults will be used. In fact the destructive one is not exactly pure .red, it's something else.
-
ekashking almost 3 yearsHow to trigger
delete
automatically once I swipe to the right??? -
Nikodem almost 3 yearsYou should use - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath. For UIContextualAction action please look at: stackoverflow.com/questions/5560602/…
-
ekashking almost 3 yearsThat's what your example is already. And your reference has nothing related to my question: How to trigger
delete
action at the end of the swipe process (without clicking on a button) -
Nikodem almost 3 yearsI understand. Please look here: developer.apple.com/documentation/uikit/…
-
ekashking almost 3 yearsI'll rephrase. How to trigger
delete
or any action like WhatsAppswipe to reply to message
by swiping just 1/3 of the screen and trigger action? -
Nikodem almost 3 yearsSorry, but I can’t understand what do you mean. Please ask the question with attachment which will show your issue and paste here the link.