(快速)如何在单元格滑动操作中设置清晰的背景?

时间:2018-08-20 19:51:42

标签: ios swift tableview

我在UITableViewCell中有一个TrailingSwipeAction,其背景颜色必须清晰。

这是我设置操作的代码:

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let myAction = UIContextualAction.init(style: .normal, title: nil) {
        // My action code
    }
    myAction.backgroundColor = .clear
    myAction.image = UIImage.init(named: "my-icon")
    return UISwipeActionsConfiguration.init(actions: [myAction])
}

但是当我期望没有颜色时,我将获得灰色背景的动作:

enter image description here

解决方案: https://stackoverflow.com/a/52018193/9451152

7 个答案:

答案 0 :(得分:3)

您必须访问UIActionStandardButtonUISwipeActionPullView内的UIView。然后更改其背景颜色。

pull view hierarchy

您可以看到应用程序的视图层次结构在某个单元格上滑动,然后进入Xcode中的Debug菜单,然后进入View Debugging,然后选择Capture View Hierarchy

首先,让我们添加一个有用的extension,它将所有子视图及其子视图放入一个数组中:

extension UIView {
    var allSubViews : [UIView] {
        var array = [self.subviews].flatMap {$0}
        array.forEach { array.append(contentsOf: $0.allSubViews) }
        return array
    }
}

然后在viewWillLayoutSubviews()中输入:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    let btn = tableView
              .allSubViews //get all the subviews
              .first(where: {String(describing:type(of: $0)) ==  "UISwipeActionStandardButton"}) // get the first one that is a UISwipeActionStandardButton

    //This UISwipeActionStandardButton has two subviews, I'm getting the one that is not a UILabel, in your case, since you've set the image,  you should get the one that is not an imageView
    if let view = btn?.subviews.first(where: { !($0 is UILabel)})
    {
        view.backgroundColor = .clear //Change the background color of the gray uiview
    }
}

我正在使用viewWillLayoutSubviews(),因为它被调用来通知视图控制器其视图即将布局其子视图。请查看here了解更多详细信息。

此解决方案针对一个轻扫操作按钮进行了优化。如果您有多个按钮,代码将如下所示:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    let buttons = tableView
        .allSubViews //get all the subviews
        .filter {String(describing:type(of: $0)) ==  "UISwipeActionStandardButton"}

    buttons.forEach { btn in
        if let view = btn.subviews.first(where: { !($0 is UIImageView)}) //If you're sure that other than the uiview there is a UIImageView in the subviews of the UISwipeActionStandardButton
        {
            view.backgroundColor = .clear //Change the background color of the gray uiview
        }
    }
}

答案 1 :(得分:3)

显然,如果您将背景颜色设置为白色且 alpha 为零,它将保持清晰但没有灰色默认颜色。

试试这个:

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
{
    let deleteAction = UIContextualAction(style: .destructive, title: nil) { [weak self] (action, view, completion) in
        // weak self to prevent memory leak if needed
        guard let self = self else { return }
        
        // do your nasty stuff here 
        
        completion(true)
    }
    
    deleteAction.backgroundColor = UIColor(white: 1, alpha: 0)
    deleteAction.image = UIImage(systemName: "trash")
    
    return UISwipeActionsConfiguration(actions: [deleteAction])
}

enter image description here

答案 2 :(得分:1)

解决方案

感谢 Carpsen90

enter image description here

您必须将该UIImageView的backgroundColor设置为.clear,但在viewWillLayoutSubviews时不存在。滑动后即可创建。

可能的解决方案是使用计时器:

var timerCellSwipeButtons: Timer?

滑动完成后启动:

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let editAction = UIContextualAction.init(style: .normal, title: nil) { [weak self] (action, view, completion) in
        // editAction code
    }
    let deleteAction = UIContextualAction.init(style: .normal, title: nil) { [weak self] (action, view, completion) in
        // deleteAction code
    }
    // Set the button's images
    editAction.image = UIImage.init(named: "editIcon")
    deleteAction.image = UIImage.init(named: "deleteIcon")
    // You also must set the background color of the actions to .clear
    editAction.backgroundColor = .clear
    deleteAction.backgroundColor = .clear
    // Launch the timer, that will run a function every 10 milliseconds
    self.timerCellSwipeButtons = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(timerCellSwipeButtonsFunction), userInfo: nil, repeats: true)
    // Return the actions
    return UISwipeActionsConfiguration.init(actions: [deleteAction, editAction])
}

现在每10毫秒一次(您可以根据需要增加频率),此函数检查tableView子视图以查找所有UISwipeActionStandardButton并将其设置为.UI的backgroundColor清除。

@objc func timerCellSwipeButtonsFunction() {
    // Gets all the buttons, maybe we have more than one in a row
    let buttons = tableView.allSubViews.filter { (view) -> Bool in
        String(describing: type(of: view)) == "UISwipeActionStandardButton"
    }
    // Loops through all the buttons
    for button in buttons {
        if let view = button.subviews.first(where: { !($0 is UIImageView)})
        {
            // We are interested in the UIView that isn't a UIImageView
            view.backgroundColor = .clear
        }
    }
    // When finish, timer is invalidated because we don't need it anymore.
    // A new one will be launched with every swipe
    self.timerCellSwipeButtons?.invalidate()
}

要获取UIView的所有子视图,我使用了 Carpsen90 给出的功能:

extension UIView {
    var allSubViews : [UIView] {
        var array = [self.subviews].flatMap {$0}
        array.forEach { array.append(contentsOf: $0.allSubViews) }
        return array
    }
}

出于安全原因,您还应该在viewWillDisappear方法中使计时器无效:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.timerCellSwipeButtons?.invalidate()
}

这是结果:

enter image description here

但是正如您所看到的,当您在单元格的同一侧进行多个动作并且完全滑动时,效果会不太好:

enter image description here

为避免图标重叠,我在每一侧只做一个动作:

// Remember to launch the timer in both swipe functions, like in the example above

// Function to add actions to the leading side of the cell
tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
// Function to add actions to the trailing side of the cell
tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?

enter image description here

答案 3 :(得分:1)

您可以将操作的背景色的Alpha值设置为0 这是示例

let modifyAction = UIContextualAction(style: .normal, title:  "", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
        print("Update action ...")
        success(true)
    })
    modifyAction.backgroundColor = UIColor.init(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 0.0)

答案 4 :(得分:1)

100%在IOS swift中进行更改以滑动按钮图像颜色和背景颜色。

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

        let action =  UIContextualAction(style: .normal, title: "", handler: { (action,view,completionHandler ) in
            self.selectedIndex  = indexPath.row
            self.deleteNotification()
            completionHandler(true)

        })
        let cgImageX =  UIImage(named: "delete-1")?.cgImage
        action.image = OriginalImageRender(cgImage: cgImageX!)
        action.backgroundColor = UIColor.init(hex: "F7F7F7")
        let confrigation = UISwipeActionsConfiguration(actions: [action])

        return confrigation
    }
    return nil
}

还为原始图像彩色显示添加该类,否则仅显示白色图像

   class OriginalImageRender: UIImage {
        override func withRenderingMode(_ renderingMode: UIImage.RenderingMode) -> UIImage {
             return self
     } }

enter image description here

答案 5 :(得分:0)

我在项目中所做的是

func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {

        let subViews = tableView.subviews.filter { (view) -> Bool in
            if NSStringFromClass(view.classForCoder) == "UISwipeActionPullView" {
                return true
            }
            return false
        }
        if subViews.count > 0 {
            let bgView = subViews[0]
            bgView.backgroundColor = bgColor
        }
    }

我的项目目标是iOS 9.0及更高版本

答案 6 :(得分:0)

按照@Maulik Patel 的解决方案,我刚刚在 action.image 中添加了一个色调选项:

let imageDelete = UIImage(systemName: "trash")?.cgImage
        deleteAction.image = OriginalImageRender(cgImage: imageDelete!).withTintColor(UIColor(named: ("colorButton"))!)
        deleteAction.backgroundColor = UIColor.init(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 0.0)
        
        
        let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
        
        return configuration