12

How to add custom image to delete button when swiping cell from right on UITableview as shown in the below image?

enter image description here

 func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

    let remove = UITableViewRowAction(style: .Default, title: "\nRemove") { action, indexPath in }
    remove.backgroundColor = UIColor(patternImage: UIImage(named: "remove")!) }

From the above code, Image is showing but, it is showing as a group of images stacked together. I mean, I am unable to set the "ContentMode" to ".ScaleToAspectFit" for the "UIImage"

What is the best way for this approach?

sample code could be appreciable.

Rohit Khandelwal
  • 1,778
  • 15
  • 23
kumar
  • 481
  • 3
  • 7
  • 18

4 Answers4

6

Inspired with Denny's answer. Here is objective-c version of his code.

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

    UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"           " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Do you really want to delete this comment?" message:@"" delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];

        [alertView setTag:101];
        [alertView show];
    }];

    UITableViewCell *commentCell = (UITableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

    CGFloat height = commentCell.frame.size.height;

    UIImage *backgroundImage = [self deleteImageForHeight:height];

    deleteAction.backgroundColor = [UIColor colorWithPatternImage:backgroundImage];

    return @[deleteAction];
}

And below is the image drawing method:

- (UIImage*)deleteImageForHeight:(CGFloat)height{

    CGRect frame = CGRectMake(0, 0, 62, height);

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(62, height), NO, [UIScreen mainScreen].scale);

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
    CGContextFillRect(context, frame);

    UIImage *image = [UIImage imageNamed:@"icon-delete"];

    [image drawInRect:CGRectMake(frame.size.width/2.0, frame.size.height/2.0 - 10, 18, 20)];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

And the result is: Table view cell delete image

mattsson
  • 1,329
  • 1
  • 14
  • 30
Muzammil
  • 1,529
  • 1
  • 15
  • 24
  • 1
    Brilliant solution! I just want to mention, that `title:@" "` is important only for iOS < 11.0 – void Oct 02 '18 at 09:42
  • @VladE.Borovtsov I write this for iOS8 and not sure about latest version. Thank you for the updates. – Muzammil Oct 02 '18 at 16:59
  • @Muzamill, it works fine even on iOS 12. On iOS 11 and iOS 12 the action buttons appears squared with `title=nil` or `title=@""`. But on lower version, to keep button squared and looking similar i had to insert title with 8 spaces. – void Oct 03 '18 at 01:35
  • @VladE.Borovtsov Great Thanks!! – Muzammil Oct 03 '18 at 07:01
5

Essentially, you are drawing in a context, then retrieve the new image from the context.

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 80, height: 100))
label.text = "ADD"
label.textAlignment = .Center
label.textColor = UIColor.whiteColor()

let img: UIImage = UIImage(named: "delete")

UIGraphicsBeginImageContextWithOptions(imgSize, false, UIScreen.mainScreen().scale)
let context = UIGraphicsGetCurrentContext()

// Set background color
CGContextSetFillColorWithColor(context, UIColor.raangeRed().CGColor)
CGContextFillRect(context, CGRect(x: 0, y: 0, width: 80, height: 80))

// Draw image
img.drawInRect(CGRectMake(30, 15, 20, 20))

// Draw View
label.layer.renderInContext(context!)

// Retrieve new UIImage
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

let deleteRowAction = UITableViewRowAction(style: .Normal, title: "           ") { (rowAction, indexPath) in
     // Do stuff   
    }
deleteRowAction.backgroundColor = UIColor(patternImage: newImage)

You can also create a custom view (with an UIImageView and UILabel) and render it inside the context.

Danny Yassine
  • 661
  • 7
  • 9
  • Wow, great example! Thanks for showing how to use CGContext to draw label and apply background colour! Just what i needed – daisura99 Dec 10 '16 at 03:33
  • Though the label seems slightly 'blurred' and does not give a nice visual. It would definitely work better if the image contains the text as well. – daisura99 Dec 10 '16 at 05:08
  • Exactly, depending also with your designer, if both of you can agree if the buttons will be dynamic or not – Danny Yassine Dec 12 '16 at 17:55
4

try this

let backImage = UIImageView(image: UIImage(named: "remove"))
backImage.contentMode = .scaleAspectFit
remove.backgroundColor = UIColor(patternImage:backImage.image!)

Choice-2

var img: UIImage = UIImage(named: "remove")
var imgSize: CGSize = tableView.frame.size
UIGraphicsBeginImageContext(imgSize)
img.drawInRect(CGRectMake(20, 0, 20, 20))
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
remove.backgroundColor = UIColor(patternImage: newImage)
Nike Kov
  • 12,630
  • 8
  • 75
  • 122
Anbu.Karthik
  • 82,064
  • 23
  • 174
  • 143
  • Thanks Anbu. I've already tried first approach, but no use. Now, while trying second approach it is showing error `Value of type "UITableViewRowAction" has no member "frame"`. I understood that we need to give the action's height and width. – kumar Apr 07 '16 at 10:08
  • we cannot use `tableView` height, as it is much bigger than row right? – kumar Apr 07 '16 at 10:44
  • @kumar - ok choice no 2 is works correct, if yes we go for next step – Anbu.Karthik Apr 07 '16 at 10:45
  • Choice 2 works, but with custom `CGRectMake(20,0,20,20)` – kumar Apr 07 '16 at 11:06
  • @kumar -- happy to hear ,your problem is resolved or not – Anbu.Karthik Apr 07 '16 at 11:07
  • One more thing, I cannot set the background custom color and cannot set multiple actions with image. – kumar Apr 07 '16 at 11:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108508/discussion-between-kumar-and-anbu-karthik). – kumar Apr 07 '16 at 11:09
  • @ThreeCoins there is only image but no title text and no background color. how to achieve this all (image + text + background color)? swift 3 – ArgaPK Nov 24 '17 at 12:34
0

Swift 5 Xcode 11.3 Only Copy and Paste Code.....

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let deleteAction = UIContextualAction(style: .normal, title: "Delete") { (action, view, completion) in
        completion(true)
        print("Delete")
    }
    
    let muteAction = UIContextualAction(style: .normal, title: "Save") { (action, view, completion) in
        completion(true)
        print("Save")
    }
    
    deleteAction.image = UIImage(named: "dustbin")
    deleteAction.backgroundColor = UIColor.white
    
    muteAction.image = UIImage(named: "file")
    muteAction.backgroundColor = UIColor.white
    return UISwipeActionsConfiguration(actions: [deleteAction, muteAction])
}

enter image description here

M Hamayun zeb
  • 448
  • 4
  • 10