(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]) } 

但是当我没有预期的颜色时,我正在获得灰色背景:

在此处输入图像描述

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

您必须访问UISwipeActionPullViewUIActionStandardButton内的UISwipeActionPullView 。 然后改变它的背景颜色。

拉视图层次结构

您可以看到应用程序在单元格上滑动的视图层次结构,然后在Xcode中Debug菜单,然后选择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 } } 

然后在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()因为它被调用以通知视图控制器它的视图即将布局其子视图。 在这里查看更多详细信息。

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

 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 } } } 

感谢Carpsen90

在此处输入图像描述

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

一个可行的解决方案是有一个Timer:

 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并设置为.clear他们的UIView的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() } 

这就是结果:

在此处输入图像描述

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

在此处输入图像描述

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

 // 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? 

在此处输入图像描述