繁体   English   中英

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

[英](Swift) How to set clear background in cell swipe action?

我在 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

您可以将动作的背景颜色的 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)

您必须访问UISwipeActionPullView内的UIActionStandardButton内的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 时不存在。 它是在您滑动后创建的。

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

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?

在此处输入图片说明

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

在此处输入图片说明

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

在此处输入图片说明

我在我的项目中所做的是

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

按照@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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM