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

Ser*_*gio 7 tableview ios swift

我在 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])
}
Run Code Online (Sandbox Code Playgroud)

但是当没有颜色时,我得到了动作的灰色背景:

在此处输入图片说明

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

Shu*_*oel 14

您可以将动作的背景颜色的 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)
Run Code Online (Sandbox Code Playgroud)

  • 这是真的。不适用于 UIColor.clear 但它适用于 UIColor.init(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 0.0) 以及 UIColor.init(white: 1, alpha : 0)。谢谢,我接受您的回答有效!:) (2认同)

iel*_*ani 6

您必须访问UIActionStandardButton. UISwipeActionPullView然后更改其背景颜色。

拉取视图层次结构

您可以在单元格上滑动来查看应用程序的视图层次结构,然后转到DebugXcode 中的菜单,View Debugging然后选择Capture View Hierarchy

首先,让我们添加这个有用的扩展,以获取数组中的所有子视图及其子视图:

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

然后在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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

该解决方案针对单次滑动操作按钮进行了优化。如果您有多个按钮,则代码将如下所示:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*gio 6

解决方案

感谢Carpsen90

在此输入图像描述

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

一个可能的解决方案是有一个计时器:

var timerCellSwipeButtons: Timer?
Run Code Online (Sandbox Code Playgroud)

滑动完成后启动:

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])
}
Run Code Online (Sandbox Code Playgroud)

现在,每隔 10 毫秒(如果需要,您可以增加频率),此函数会检查 tableView 子视图,查找所有 UISwipeActionStandardButton 并设置为 .clear 其 UIView 的背景颜色:

@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()
}
Run Code Online (Sandbox Code Playgroud)

为了获取 UIView 的所有子视图,我使用了Carpsen90给出的函数:

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

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

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.timerCellSwipeButtons?.invalidate()
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

在此输入图像描述

但正如您所看到的,当您在单元格的同一侧有多个操作并且完全滑动时,看起来不太好:

在此输入图像描述

为了避免图标重叠,我在每一侧只放置一个操作:

// 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?
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


小智 5

显然,如果您将背景颜色设置为 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])
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述