Изображение UITableViewRowAction для заголовка

Я сделал пользовательский UITableViewRowAction. Теперь я хотел бы добавить изображение вместо текста. Я знаю, что это возможно, но не знаю, как это сделать. Кто-то из вас знает, как это сделать в Свифт и хотел бы мне помочь? Спасибо за ваши ответы!

Ответ 1

iOS 11.0

Apple представила гибкий способ объявить ряд действий с большими преимуществами.

extension ViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let askAction = UIContextualAction(style: .normal, title: nil) { action, view, complete in
      print("Ask!")
      complete(true)
    }

    // here set your image and background color
    askAction.image = IMAGE
    askAction.backgroundColor = .darkGray

    let blockAction = UIContextualAction(style: .destructive, title: "Block") { action, view, complete in
      print("Block")
      complete(true)
    }

    return UISwipeActionsConfiguration(actions: [blockAction, askAction])
  }

  func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.textLabel?.text = "row: \(indexPath.row)"
  }
}

Пример:

enter image description here

iOS 8.0

Вам нужно установить UIImage для backgroundColor действия строки, конкретно:

Swift:

UIColor(patternImage: UIImage(named: "IMAGE_NAME"))

Objective-C:

[UIColor colorWithPatternImage:[UIImage imageNamed:@"IMAGE_NAME"]];

Ответ 2

Swift 4 (iOS 11+):

iOS 11 теперь поддерживает изображения (только) для отображения в кнопках действий. Вам просто нужно инициализировать объект UISwipeActionsConfiguration в объекте делегата табличного представления:

extension MyTableViewController:UITableViewDelegate {

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

        let deleteAction = UIContextualAction(style: .normal, title:  nil, handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in

                debugPrint("Delete tapped")

                success(true)
            })

        deleteAction.image = UIImage(named: "icon_delete.png")
        deleteAction.backgroundColor = UIColor.red

        return UISwipeActionsConfiguration(actions: [deleteAction])
    }

}

Ответ 3

Я сделал эту простую категорию UITableViewRowAction, чтобы установить значок для моих действий. Вы можете установить изображение, цвет фона, высоту ячейки (для управления динамическими ячейками) и размер значка в процентах.

extension UITableViewRowAction {

  func setIcon(iconImage: UIImage, backColor: UIColor, cellHeight: CGFloat, iconSizePercentage: CGFloat)
  {
    let iconHeight = cellHeight * iconSizePercentage
    let margin = (cellHeight - iconHeight) / 2 as CGFloat

    UIGraphicsBeginImageContextWithOptions(CGSize(width: cellHeight, height: cellHeight), false, 0)
    let context = UIGraphicsGetCurrentContext()

    backColor.setFill()
    context!.fill(CGRect(x:0, y:0, width:cellHeight, height:cellHeight))

    iconImage.draw(in: CGRect(x: margin, y: margin, width: iconHeight, height: iconHeight))

    let actionImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.backgroundColor = UIColor.init(patternImage: actionImage!)
  }
}

Ответ 4

class TableViewRowAction: UITableViewRowAction 
{
    var image: UIImage?

    func _setButton(button: UIButton) 
    {
        if let image = image, let titleLabel = button.titleLabel
        {
            let labelString = NSString(string: titleLabel.text!)
            let titleSize = labelString.sizeWithAttributes([NSFontAttributeName: titleLabel.font])

            button.tintColor = UIColor.whiteColor()
            button.setImage(image.imageWithRenderingMode(.AlwaysTemplate), forState: .Normal)
            button.imageEdgeInsets.right = -titleSize.width
        }
    }
}


func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? 
{
    let delete = TableViewRowAction(style: UITableViewRowActionStyle.Default, title: "         ") { action, indexPath in }
    delete.image = UIImage(named: "trashImg")

    let sharing = TableViewRowAction(style: UITableViewRowActionStyle.Default, title: "         ") { action, indexPath in }
    sharing.backgroundColor = UIColor.lightGrayColor()
    sharing.image = UIImage(named: "sharingImg")

    return [delete, sharing]
}

Ответ 5

Я просто реализую лучшую версию fooobar.com/questions/93291/... 1. В большинстве случаев высота ячейки и ширина настраиваемой части смахивания различаются, вы должны рассчитать это в вашей функции 2. Изображение может иметь разный размер чем квадрат, так что вы должны рассчитывать пропорции не только по высоте. Итак, код с моими исправлениями

func setIcon(iconImage: UIImage, backColor: UIColor, cellHeight: CGFloat, customSwipPartWidth: CGFloat, iconSizePercentage: CGFloat) {
        let iconWidth = customSwipPartWidth * iconSizePercentage
        let iconHeight = iconImage.size.height / iconImage.size.width * iconWidth
        let marginY = (cellHeight - iconHeight) / 2 as CGFloat
        let marginX = (customSwipPartWidth - iconWidth) / 2 as CGFloat


        UIGraphicsBeginImageContextWithOptions(CGSize(width: customSwipPartWidth, height: cellHeight), false, 0)
        let context = UIGraphicsGetCurrentContext()

        backColor.setFill()
        context!.fill(CGRect(x:0, y:0, width:customSwipPartWidth, height:cellHeight))

        iconImage.draw(in: CGRect(x: marginX, y: marginY, width: iconWidth, height: iconHeight))

        let actionImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        self.backgroundColor = UIColor.init(patternImage: actionImage!)
    } 

Ответ 6

delActions.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"delete.png"]];

Ответ 7

Проблема с базовым подходом к шаблону заключается в том, что ваше изображение должно быть того же размера, что и кнопка действия, или, по крайней мере, иметь более плоский фон внизу, чтобы предотвратить повторение изображения (хотя это будет быть привязанным сверху, что не очень приятно).

Мне приходилось иметь дело с ячейками динамической высоты, поэтому я реализовал следующее:

- (UIColor *)backgroundImageForActionAtIndexPath:(NSIndexPath *)indexPath withImage:(UIImage *)image tintColor:(UIColor *)tintColor backgroundColor:(UIColor *)backgrounfColor expectedWith:(CGFloat)width {
//
CGRect cellFrame = [self.tableView rectForRowAtIndexPath:indexPath];
CGSize expectedSize = CGSizeMake(width, cellFrame.size.height);

UIGraphicsBeginImageContextWithOptions(expectedSize, NO, 0.0);

CGContextRef ctx = UIGraphicsGetCurrentContext ();
if (ctx) {
    // set the background
    CGContextSetFillColorWithColor(ctx, backgrounfColor.CGColor);
    CGRect fillRect = CGRectZero;
    fillRect.size = expectedSize;
    CGContextFillRect(ctx, fillRect);
    // put the image
    CGContextSetFillColorWithColor(ctx, tintColor.CGColor);
    CGRect rect = CGRectMake((expectedSize.width - image.size.width) / 2., (expectedSize.height - image.size.height) / 2., image.size.width, image.size.height);
    [image drawInRect:rect];
}

UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return [UIColor colorWithPatternImage:newImage];

}

Вам все равно нужно установить ожидаемую ширину так, чтобы она соответствовала пустой метке, помеченной в заголовке действия. например: @"" → 64.f

Как вы видите при таком подходе вы можете установить цвет фона кнопки и оттенка в коде, а не в самом художественном произведении.

Ответ 8

Мой вариант пытается использовать поведение UImageView contentMode, и когда этого было недостаточно, я нашел хорошее применение для пары методов Core Geometry Rect, поскольку они удерживают целевой кадр в центре кадра ячейки. Используя проверку зрения, кажется, что смахивание удаляло половину моей нормальной ширины ячейки, так что там, где появляются магические числа.

Swift 3.0

extension UITableViewRowAction {

    func setIcon(iconImage: UIImage, backColor: UIColor, cellHeight: CGFloat, cellWidth:CGFloat) ///, iconSizePercentage: CGFloat)
    {
        let cellFrame = CGRect(origin: .zero, size: CGSize(width: cellWidth*0.5, height: cellHeight))
        let imageFrame = CGRect(x:0, y:0,width:iconImage.size.width, height: iconImage.size.height)
        let insetFrame = cellFrame.insetBy(dx: ((cellFrame.size.width - imageFrame.size.width) / 2), dy: ((cellFrame.size.height - imageFrame.size.height) / 2))
        let targetFrame = insetFrame.offsetBy(dx: -(insetFrame.width / 2.0), dy: 0.0)
        let imageView = UIImageView(frame: imageFrame)
        imageView.image = iconImage
        imageView.contentMode = .left
        guard let resizedImage = imageView.image else { return }
        UIGraphicsBeginImageContextWithOptions(CGSize(width: cellWidth, height: cellHeight), false, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return }
        backColor.setFill()
        context.fill(CGRect(x:0, y:0, width:cellWidth, height:cellHeight))
        resizedImage.draw(in: CGRect(x:(targetFrame.origin.x / 2), y: targetFrame.origin.y, width:targetFrame.width, height:targetFrame.height))
        guard let actionImage = UIGraphicsGetImageFromCurrentImageContext() else { return }
        UIGraphicsEndImageContext()
        self.backgroundColor = UIColor.init(patternImage: actionImage)
    }
}

Использование: из метода editActions... делегата tableview.

let cellHeight = (self.tableView(tableView, cellForRowAt: indexPath)).frame.size.height
let cellWidth = (self.tableView(tableView, cellForRowAt: indexPath)).frame.size.width
let favorite = UITableViewRowAction(style: .normal, title: nil) { action, index in
                //perform action
                debugPrint("Test")

            }
favorite.setIcon(iconImage: #imageLiteral(resourceName: "favorite"), backColor: .green, cellHeight: cellHeight, cellWidth:cellWidth)