【问题标题】:How to set clear background in table view cell swipe action?如何在表格视图单元格滑动动作中设置清晰的背景?
【发布时间】:2019-01-26 23:46:53
【问题描述】:

我在 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])
}

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

【问题讨论】:

  • 清除颜色 - 表示完全透明。因此,您需要检查按钮下的视图的背景颜色(TableViewCell、TableView 等...)
  • 还是灰色的,还是谢谢你。
  • 你在viewdidload方法中设置tableView.backgroundColor = .clear了吗?
  • 是的,tableview 背景清晰,单元格后面的所有内容和单元格也要清除。它仍然显示为灰色
  • 和 cell.contentView.backgroundColor = .clear ?

标签: ios swift tableview


【解决方案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)

【讨论】:

  • 这是真的。不适用于 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】:

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

您可以在单元格上滑动查看应用的视图层次结构,然后转到 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
        }
    }
}

【讨论】:

  • 对不起,我找不到这样做的方法。谢谢。
  • @Sergio 您所指的帖子使用 Xamarin。我已经更新了我的答案。我希望有所帮助。
  • 还是不行,我们还是继续聊天吧。
  • @Sergio 你用什么代替了 UILabel?
【解决方案3】:

解决方案

感谢Carpsen90

你必须将那个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 并设置为 .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?

【讨论】:

    【解决方案4】:

    显然,如果您将背景颜色设置为白色且 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])
    }
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 我只有一个更大的黑色图标。 action.backgroundColor 只是改变了背景颜色...并不意外。
      • @TiloDelau 你想要哪种类型的输出请告诉我我可以帮你
      • 好吧,我想改变图标颜色。这是我的(修改后的)代码,但我只是得到了带有蓝色背景的更大尺寸的黑色图标(实际上想要一个清晰的背景)。我猜是因为它实际上不是图像?: let cgImageX = UIImage(systemName: "minus.square")?.cgImage delete.image = OriginalImageRender(cgImage: cgImageX!) delete.backgroundColor = UIColor.blue let confrigation = UISwipeActionsConfiguration(actions : [delete]) 归还保护
      • 请检查@TiloDelau if #available(iOS 13.0, *) { action.image = UIGraphicsImageRenderer(size: CGSize(width: 30, height: 30)).image { _ in UIImage(systemName: "minus.square")?.draw(in: CGRect(x: 0, y: 0, width: 30, height: 30)) } action.backgroundColor = UIColor.init(red: 0/255.0, green: 0/ 255.0,蓝色:0/255.0,alpha:0.0) 让 confrigation = UISwipeActionsConfiguration(actions: [action]) return confrigation } else { }
      • 可以调整大小,但是图标颜色还是黑色:if #available(iOS 13.0, *) { delete.image = UIGraphicsImageRenderer(size: CGSize(width: 20, height: 20))。图片 { _ in UIImage(systemName: "minus.square")?.draw(in: CGRect(x: 0, y: 0, width: 20, height: 20)) } delete.backgroundColor = UIColor.init(red: 0/255.0,绿色:0/255.0,蓝色:244/255.0,alpha:0) let confrigation = UISwipeActionsConfiguration(actions: [delete]) return confrigation } else { ...
      【解决方案6】:

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

      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
      

      【讨论】:

        【解决方案7】:

        我在项目中所做的是

        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及以上

        【讨论】:

          猜你喜欢
          • 2014-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-22
          • 2011-04-04
          • 2010-10-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多