Jack
Jack

Reputation: 14329

How to add image in UITableViewRowAction?

I'm trying to add image in UITableView Swipe style. I tried with Emoji text & its working fine

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
  let editAction = UITableViewRowAction(style: .normal, title: "🖋") { (rowAction, indexPath) in
      print("edit clicked")
  }

  return [editAction]
}

But I need image instead of Emoji, meanwhile I tried

editAction.backgroundColor = UIColor.init(patternImage: UIImage(named: "edit")!)

But it's getting duplicate image, I used images in many format like 20*20, 25*25, 50*50 but still duplicating.

How can I add image?

Upvotes: 15

Views: 17001

Answers (6)

Jack
Jack

Reputation: 14329

Finally in iOS 11, SWIFT 4 We can add add image in UITableView's swipe action with help of UISwipeActionsConfiguration

@available(iOS 11.0, *)
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

            let action =  UIContextualAction(style: .normal, title: "Files", handler: { (action,view,completionHandler ) in
                //do stuff
                completionHandler(true)
            })
        action.image = UIImage(named: "apple.png")
        action.backgroundColor = .red
        let configuration = UISwipeActionsConfiguration(actions: [action])

        return configuration
    }

WWDC video at 28.34

Apple Doc

Note: I have used 50*50 points apple.png image with 50 tableview row height

Upvotes: 28

Ryan Forte
Ryan Forte

Reputation: 589

I came across this same problem and discovered a really good pod for this called SwipeCellKit that makes it really easy to implement an image into your swipe cell action without the swipe action causing multiple images to show. it also allows for more customization such as different swipe directions.

Steps:

  1. add pod
  2. import SwipeCellKit
  3. make cell conform to SwipeTableViewCell
  4. in cellForRow function set the cells delegate to self
  5. follow the implementation below or via the link

link to pod -> https://github.com/SwipeCellKit/SwipeCellKit

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
    guard orientation == .right else { return nil }

    let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
        // handle action by updating model with deletion
    }

    // customize the action appearance
    deleteAction.image = UIImage(named: "delete")

    return [deleteAction]
}

func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
    var options = SwipeOptions()
    options.expansionStyle = .destructive
    return options
}

Upvotes: 3

Isuru Jayathissa
Isuru Jayathissa

Reputation: 488

I had the same problem with my project, so I did a workaround for this. I think, this is helpful for you.

When I swipe table cell to the left only for image width, it is working fine.

enter image description here

But when I swipe table cell more than image width, table cell display like this:

enter image description here

This happen because to add image I use 'backgroundColor' property.

copyButton.backgroundColor = UIColor(patternImage: UIImage(named: "bfaCopyIcon.png")!)

So to fix this, I increase image width to the same as table width.

old image >>>>>>>>>>>> new image

enter image description here >>>> enter image description here

this is the new look:

enter image description here

This is my sample code:

func tableView(_ tableView: UITableView, editActionsForRowAt: IndexPath) -> [UITableViewRowAction]? {
    let copyButton = UITableViewRowAction(style: .normal, title: "") { action, index in

         print("copy button tapped")

    }
    copyButton.backgroundColor = UIColor(patternImage: UIImage(named: "bfaCopyIcon.png")!)


    let accessButton = UITableViewRowAction(style: .normal, title: "") { action, index in

       print("Access button tapped")

    }
    accessButton.backgroundColor = UIColor(patternImage: UIImage(named: "bfaAccess.png")!)


    return [accessButton, copyButton]
}

Upvotes: 6

Jack
Jack

Reputation: 14329

I found one way of doing this in SWIFT 3 -

enter image description here

 func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        //let cell = tableView.cellForRow(at: indexPath)
        //print(cell?.frame.size.height ?? 0.0)//hence we need this height of image in points. make sure your contentview of image is smaller
        let deleteAction = UITableViewRowAction(style: .normal, title:"       ") { (rowAction, indexPath) in
            print("delete clicked")
        }
        deleteAction.backgroundColor = UIColor(patternImage:UIImage(named: "delete")!)
        return [deleteAction]
    }

We need to make sure our image dimension is matching with cell row height Here is my image which i usedenter image description here

Upvotes: 1

Harry Singh
Harry Singh

Reputation: 826

Here is how I do it in objective-c and should work in swift when translated.

- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *deleteString = @"Delete";
    CGFloat tableViewCellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath];
    UIImage *image = [UIImage imageNamed:@"delete_icon"];

    CGFloat fittingMultiplier = 0.4f;
    CGFloat iOS8PlusFontSize = 18.0f;
    CGFloat underImageFontSize = 13.0f;
    CGFloat marginHorizontaliOS8Plus = 15.0f;
    CGFloat marginVerticalBetweenTextAndImage = 3.0f;

    float titleMultiplier = fittingMultiplier;

    NSString *titleSpaceString= [@"" stringByPaddingToLength:[deleteString length]*titleMultiplier withString:@"\u3000" startingAtIndex:0];

    UITableViewRowAction *rowAction= [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:titleSpaceString handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
        //Do Stuff
    }];

    CGSize frameGuess=CGSizeMake((marginHorizontaliOS8Plus*2)+[titleSpaceString boundingRectWithSize:CGSizeMake(MAXFLOAT, tableViewCellHeight) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName: [UIFont systemFontOfSize:iOS8PlusFontSize] } context:nil].size.width, tableViewCellHeight);

    CGSize tripleFrame=CGSizeMake(frameGuess.width*3.0f, frameGuess.height*3.0f);

    UIGraphicsBeginImageContextWithOptions(tripleFrame, YES, [[UIScreen mainScreen] scale]);
    CGContextRef context=UIGraphicsGetCurrentContext();

    [[UIColor blueColor] set];
    CGContextFillRect(context, CGRectMake(0, 0, tripleFrame.width, tripleFrame.height));

    CGSize drawnTextSize=[deleteString boundingRectWithSize:CGSizeMake(MAXFLOAT, tableViewCellHeight) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName: [UIFont systemFontOfSize:underImageFontSize] } context:nil].size;

    [image drawAtPoint:CGPointMake((frameGuess.width/2.0f)-([image size].width/2.0f), (frameGuess.height/2.0f)-[image size].height-(marginVerticalBetweenTextAndImage/2.0f)+2.0f)];

    [deleteString drawInRect:CGRectMake(((frameGuess.width/2.0f)-(drawnTextSize.width/2.0f))*([[UIApplication sharedApplication] userInterfaceLayoutDirection]==UIUserInterfaceLayoutDirectionRightToLeft ? -1 : 1), (frameGuess.height/2.0f)+(marginVerticalBetweenTextAndImage/2.0f)+2.0f, frameGuess.width, frameGuess.height) withAttributes:@{ NSFontAttributeName: [UIFont systemFontOfSize:underImageFontSize], NSForegroundColorAttributeName: [UIColor whiteColor] }];

    [rowAction setBackgroundColor:[UIColor colorWithPatternImage:UIGraphicsGetImageFromCurrentImageContext()]];
    UIGraphicsEndImageContext();

    return @[rowAction];
}

Upvotes: 0

karthik
karthik

Reputation: 159

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

    let write = UITableViewRowAction(style: .default, title: "\u{1F58A}") { action, index in
        print("edit button tapped")
    }

    return [write]
}

try this used unicode instead icon. this will work

Upvotes: -2

Related Questions