在可重复使用的表格视图单元格中自动触摸按钮

Posted

技术标签:

【中文标题】在可重复使用的表格视图单元格中自动触摸按钮【英文标题】:Button is automatically touched in reusable table view cell 【发布时间】:2019-04-01 05:45:49 【问题描述】:

我的表格视图的自定义单元格中有一个按钮。每当我滚动表格视图时,该按钮都会自动处于按下状态(我已经从 isTouchInside 进行了检查)。我使用了可重复使用的电池。我该如何解决这个问题?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "bookTimeCellView", for: indexPath) as! BookTimeCellView
        print("Button state : \(cell.bookButton.isTouchInside)")
        cell.timeLabel.text = timeArray[indexPath.row]
        return cell

这是我的自定义单元格的图像 Custom View Cell Image

每当我点击 booknow 按钮并滚动时,单元格中的其他按钮也处于按下状态。

这是我用于按钮的自定义类 UIButtonX

import UIKit

@IBDesignable
class UIButtonX: UIButton 

    enum FromDirection:Int 
        case Top = 0
        case Right = 1
        case Bottom = 2
        case Left = 3
    

    var shadowView: UIView!
    var direction: FromDirection = .Left
    var alphaBefore: CGFloat = 1

    @IBInspectable var animate: Bool = false
    @IBInspectable var animateDelay: Double = 0.2
    @IBInspectable var animateFrom: Int 
        get 
            return direction.rawValue
        
        set (directionIndex) 
            direction = FromDirection(rawValue: directionIndex) ?? .Left
        
    

    @IBInspectable var popIn: Bool = false
    @IBInspectable var popInDelay: Double = 0.4

    override func draw(_ rect: CGRect) 
        self.clipsToBounds = true

        if animate 
            let originalFrame = frame

            if direction == .Bottom 
                frame = CGRect(x: frame.origin.x, y: frame.origin.y + 200, width: frame.width, height: frame.height)
            

            UIView.animate(withDuration: 0.3, delay: animateDelay, usingSpringWithDamping: 0.5, initialSpringVelocity: 0, options: .allowUserInteraction, animations: 
                self.frame = originalFrame
            , completion: nil)
        

        if popIn 
            transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
            UIView.animate(withDuration: 0.8, delay: popInDelay, usingSpringWithDamping: 0.5, initialSpringVelocity: 0, options: .allowUserInteraction, animations: 
                self.transform = CGAffineTransform.identity
            , completion: nil)
        

        if shadowView == nil && shadowOpacity > 0 
            shadowView = UIView(frame: self.frame)
            shadowView.backgroundColor = UIColor.clear
            shadowView.layer.shadowColor = shadowColor.cgColor
            shadowView.layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: self.cornerRadius).cgPath
            shadowView.layer.shadowOffset = shadowOffset
            shadowView.layer.shadowOpacity = Float(shadowOpacity)
            shadowView.layer.shadowRadius = shadowRadius
            shadowView.layer.masksToBounds = true
            shadowView.clipsToBounds = false

            self.superview?.addSubview(shadowView)
            self.superview?.bringSubviewToFront(self)
        
    

    override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool 
        alphaBefore = alpha

        UIView.animate(withDuration: 0.2, delay: 0, options: .allowUserInteraction, animations: 
            self.alpha = 0.4
        )

        return true
    

    override func endTracking(_ touch: UITouch?, with event: UIEvent?) 
        UIView.animate(withDuration: 0.35, delay: 0, options: .allowUserInteraction, animations: 
            self.alpha = self.alphaBefore
        )
    

    // MARK: - Borders

    @IBInspectable var cornerRadius: CGFloat = 0 
        didSet 
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        
    

    @IBInspectable var borderWidth: CGFloat = 0.0 
        didSet 
            layer.borderWidth = borderWidth
        
    

    @IBInspectable var borderColor: UIColor = UIColor.clear 
        didSet 
            layer.borderColor = borderColor.cgColor
        
    

    // MARK: - Shadow

    @IBInspectable public var shadowOpacity: CGFloat = 0
    @IBInspectable public var shadowColor: UIColor = UIColor.clear
    @IBInspectable public var shadowRadius: CGFloat = 0
    @IBInspectable public var shadowOffset: CGSize = CGSize(width: 0, height: 0)


   //    MARK: - Gradient
    @IBInspectable var firstColor: UIColor = UIColor.white 
        didSet 
            updateView()
        
    

    @IBInspectable var secondColor: UIColor = UIColor.white 
        didSet 
            updateView()
        
    

    @IBInspectable var horizontalGradient: Bool = false 
        didSet 
            updateView()
        
    

    override public class var layerClass: AnyClass 
        get 
            return CAGradientLayer.self
        
    

    func updateView() 
        let layer = self.layer as! CAGradientLayer
        layer.colors = [ firstColor.cgColor, secondColor.cgColor ]

        if (horizontalGradient) 
            layer.startPoint = CGPoint(x: 0.0, y: 0.5)
            layer.endPoint = CGPoint(x: 1.0, y: 0.5)
         else 
            layer.startPoint = CGPoint(x: 0, y: 0)
            layer.endPoint = CGPoint(x: 0, y: 1)
        
    


【问题讨论】:

添加您到目前为止所做的代码。这样我们就可以帮助您:) @AmirKhan 我添加了我的单元格的图像和一些代码。请帮帮我;) 检查您的Cell's Xib,是否为该按钮设置了任何默认状态。 @AmirKhan 处于默认状态。 你的意思是说每当你滚动Table按钮的target方法被调用?是吗? 【参考方案1】:

您可以覆盖 prepareForReuseUITableViewCell,这是您在重用之前还原任何 UI 控件的地方,如下所示:

class BookTimeCellView: UITableViewCell 

    @IBOutlet var button = CustomButton()

    override func prepareForReuse() 
        super.prepareForReuse()

        // normally following are the button states you would reset
        self.button.isSelected = false
        self.button.isHighlighted = false

        // This seems some CustomButton property
        self.bookButton.isTouchInside = false
    


【讨论】:

未处于选中状态。它处于按下状态,我用 isTouchInside 进行了检查。 请发布您如何检查它的代码,或者只是替换行self.button.isSelected = false使其未选中 我已经用这条线检查了状态。 print("Button state : \(cell.bookButton.isTouchInside)") 。此行打印为 true。如果我检查了其他类似 isHighlighted、isSelected 等,那么它会打印错误。我已经检查了 self.button.isSelected = false 并没有工作 我认为如果 isTouchInside 属性同时被获取和设置,这将起作用。但不幸的是,这个属性只是获取,所以我们无法设置值 我没有设置isTouchInside 的值。每当我滚动表格视图时,我都检查了按钮处于哪个状态。起初,所有按钮都处于默认状态,每当我在一个单元格中按下一个按钮并滚动时,它就会开始将另一个按钮状态更改为按下状态。我检查了按钮状态,只有当我检查 isTouchInside 时它才返回 true

以上是关于在可重复使用的表格视图单元格中自动触摸按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何使用自动布局来调整表格视图单元格中的视图大小?

当触摸单元格中的自定义按钮时,我们如何知道表格中触摸了哪个单元格?

如何使用自动布局来调整表格视图单元格中的视图?

在表格视图单元格中使用按钮出列单元格

自定义表格单元格中的堆栈视图

表格视图中的按钮没有响应其单元格编号