首页 > 解决方案 > 无法点击 CollectionViewCell 中的按钮

问题描述

我在具有以下结构的 UICollectionViewCell 中嵌入了一个按钮,当我尝试点击按钮时,按钮 UI 不会更改,也不会调用关联的函数,这种行为在 iOS 12 (iPhone 8) 中而不是在 iOS 10 (iPhone 5)

UITableView > UITableViewCell > UICollectionView > UICollectionViewCell > UIButton

以下屏幕截图显示了带有 collectionViewCells 的 tableViewCell。 在此处输入图像描述

下面是代码:

TableView 类 AppointmentTVC: UITableViewController {

var appointmentTimesCollectionTVCell    = AppointmentTimesCollectionTVCell()

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            appointmentTimesCollectionTVCell.appointmentTimesToDisplay  = self.appointmentTimesToDisplay
            appointmentTimesCollectionTVCell.isUserInteractionEnabled   = true
            //appointmentTimesCollectionTVCell.selectionStyle             = .none
            return appointmentTimesCollectionTVCell
}

}

下面是包含 collectionViewCells 的 tableview 单元格

class AppointmentTimesCollectionTVCell: UITableViewCell {

    var notificationCenter = NotificationCenter.default

    let collectionView:UICollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())

    var layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout.init()

    let collectionViewCellId    =   "Cell"

    var cellDimensionsArray     =   [CGSize]()

    var appointmentTimes        =   [Date]()

    var indexOfSelectedItem : Int?



    var appointmentTimesToDisplay : [Date]{
        set(appointmentTimesToSet){   // This method is called whenever appointmentTimesToDisplay is set
            appointmentTimes = appointmentTimesToSet
            print("appointmentTimesBeingSet: \(appointmentTimes)")
            collectionView.reloadData() // This is used to reload images
        }
        get{
            return appointmentTimes
        }
    }


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)



        // Configure CollectionView
        collectionView.register(ButtonCVCell.self, forCellWithReuseIdentifier: collectionViewCellId)

        collectionView.isScrollEnabled  = true  // To scroll collectionview inside cell

        layout.scrollDirection          = .horizontal

        layout.minimumInteritemSpacing  = CGFloat(10.0)  // The minimum spacing to use between items in the same row.
        layout.minimumLineSpacing       = CGFloat(10.0)       // The minimum spacing to use between lines of items in the grid.


        collectionView.setCollectionViewLayout(layout, animated: true)
        collectionView.backgroundColor = Colors.white

        collectionView.delegate     = self as UICollectionViewDelegate
        collectionView.dataSource   = self as UICollectionViewDataSource

        collectionView.translatesAutoresizingMaskIntoConstraints = false


        contentView.addSubview(collectionView)

        let viewsDict = [
            "collectionView"    : collectionView
            ] as [String : Any]

        // collectionView Constraints
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-5-[collectionView]-5-|", options: [], metrics: nil, views: viewsDict))
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-5-[collectionView]-5-|", options: [], metrics: nil, views: viewsDict))

    }

}


extension AppointmentTimesCollectionTVCell: UICollectionViewDelegateFlowLayout {

    // FOR SETTING FIXED SIZES
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        // setting the standard widths of 80 and height 30.0 as default to ensure correct collection view cell size
        // These have been obtained by printing intrinsicContent size width in function cellforItem at
        if cellDimensionsArray.count == 0   { return CGSize(width:80.0, height: 30.0) }

        let _cellDimension = cellDimensionsArray[indexPath.item]

        return _cellDimension
    }


}



extension AppointmentTimesCollectionTVCell: UICollectionViewDataSource {
    // MARK: UICollectionViewDataSource

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return appointmentTimes.count
    }


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let item = indexPath.item

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: collectionViewCellId, for: indexPath) as? ButtonCVCell

        let appointmentTimeObject   =   appointmentTimes[item]
        let appointmentTimeString   = " " + DateFormatter().standardDateFormatter.string(from: appointmentTimeObject) + " "

        print("indexOfSelectedItem: \(indexOfSelectedItem), item: \(item)")

        // This is to ensure that only the selected item color stays and remainder are set to default
        if indexOfSelectedItem == item{
            cell?.button.backgroundColor    =   Colors.curieBlue
            cell?.button.layer.borderColor  =   Colors.curieBlue.cgColor
            cell?.button.setTitleColor(Colors.white, for: .normal)

        } else{
            cell?.button.layer.borderWidth      =   1
            cell?.button.layer.borderColor      =   Colors.lightGrey.cgColor
            cell?.button.backgroundColor       =   Colors.white
            cell?.button.setTitleColor(Colors.curieBlue, for: .normal)
        }

        cell?.button.tag                    =   item
        cell?.button.setTitle(appointmentTimeString , for: .normal)
        //cell?.button.addTarget(self, action: #selector(setSelectedTime(sender:)), for: .touchUpInside)
        cell?.button.addTarget(self, action: #selector(setSelectedTime(sender:)), for: .touchUpInside)
        print("buttonTagSetForTheButton: \(cell)")

        if let intrinsicContentSize    = cell?.button.intrinsicContentSize {
            //let intrinsicContentSize    = cell?.button.intrinsicContentSize
            let cellWidth   = intrinsicContentSize.width
            let cellHeight  = intrinsicContentSize.height
            let cellDimension = CGSize(width: cellWidth, height: cellHeight)

            if cellDimensionsArray.count <= appointmentTimes.count{ // Setting dimensions for new cells
                cellDimensionsArray.append(cellDimension)

            }else{  // Replacing dimensions for existing cells
                cellDimensionsArray[item] = cellDimension
            }
        }


        return cell ?? UICollectionViewCell()

        //return cell
    }


    func setSelectedTime(sender: UIButton){
        print("setSelectedTimeFuncCalled")
        let selectedTime            =   appointmentTimes[sender.tag]
        self.indexOfSelectedItem    =   sender.tag
        let timestamp               =   selectedTime.timeIntervalSince1970    // Get the Unix timestamp

        // Posting a local notification
        let selectedAppointmentTimeDict = ["selectedAppointmentTime" : Int(timestamp)]
        notificationCenter.post(name: Notification.Name(NotificationNames.appointmentTimeSelected), object: nil, userInfo: selectedAppointmentTimeDict)

        self.collectionView.reloadData()
    }


}

下面的代码用于生成带有按钮的集合视图单元格。

class ButtonCVCell: UICollectionViewCell {

    let button : UIButton = {
        let btn                 = UIButton(type: .system)
        btn.tintColor           = Colors.curieBlue
        btn.frame               = CGRect(x: 0, y: 0, width: 20, height: 20)
        btn.layer.cornerRadius  = 5
        btn.sizeToFit()

        return btn
    }()

    var cellWidthConstraint : NSLayoutConstraint!   


    var cellWidth : CGFloat{       
        set(width){

            self.cellWidthConstraint.constant = width
            self.cellWidthConstraint.isActive = true

            print("SettingCellsWidth: \(width)")
        }
        get{
            return self.cellWidthConstraint.constant
        }
    }



    override func awakeFromNib() {
        super.awakeFromNib()

    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        fatalError("init(coder:)")
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        self.contentView.translatesAutoresizingMaskIntoConstraints = false            

        self.cellWidthConstraint = NSLayoutConstraint(item: contentView, attribute: .width, relatedBy: .equal, toItem: nil, attribute:.notAnAttribute, multiplier: 0, constant: 0.0)

        button.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(button)


        let viewsDict = [
            "button"    :   button
            ] as [String : Any]

        // Button Constraints
        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[button(30)]|", options: [], metrics: nil, views: viewsDict))

        contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[button]", options: [], metrics: nil, views: viewsDict))

    }

}

标签: iosswiftuitableviewuicollectionviewuicollectionviewcell

解决方案


每个集合视图单元格都是按钮。使用collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)代替


推荐阅读