点击按钮时仅将子视图添加到一个 UICollectionViewCell

Adding subviews to only one UICollectionViewCell on button tap

每个 UICollectionViewCell 都有自己的按钮连接到以下操作:

@IBAction func dropDown(sender:UIButton){

    var pt = sender.bounds.origin
    var ptCoords : CGPoint = sender.convertPoint(pt, toView:sender.superview);
    var ptCoords2 : CGPoint = sender.convertPoint( ptCoords, toView: collectionView!);
    var cellIndex: NSIndexPath = self.collectionView!.indexPathForItemAtPoint(ptCoords2)!
    //var i : NSInteger = cellIndex.row;
    //var i2 : NSInteger  = cellIndex.section;
    var selectedCell = collectionView?.cellForItemAtIndexPath(cellIndex) as CollectionViewCell!
    selectedCell.button.backgroundColor = UIColor.blackColor()

    for (var i = 0; i < 3; i++){
        var textView : UITextView! = UITextView(frame: CGRectMake(self.view.frame.size.width - self.view.frame.size.width/1.3, CGFloat(50 + (30*(i+1))), CGRectGetWidth(self.view.frame), CGFloat(25)))
            textView.backgroundColor = UIColor.whiteColor()
            selectedCell.contentView.addSubview(textView)
    }
}

我想要做的是仅向被点击的单元格添加 3 个子视图。子视图已成功添加,但只要我滚动,进入视图并对应于先前设置的 indexPath 的单元格就会加载 3 个子视图。我认为这是由于 dequeueReusableCellWithReuseIdentifier 方法造成的,但我想不出解决方法。我考虑过删除 scrollViewDidScroll 上的子视图,但理想情况下,我希望在再次点击按钮之前,将视图保留在它们的父单元格上。

编辑: 好的,我放弃了整个 convertPoint 方法,现在根据按钮标签获取单元格索引:

    var selectedCellIndex : NSIndexPath = NSIndexPath(forRow: cell.button.tag, inSection: 0)
    var selectedCell = collectionView?.cellForItemAtIndexPath(selectedCellIndex) as CollectionViewCell!

无论如何,当我尝试仅将子视图添加到所选索引处的单元格时,子视图会重复。

编辑: 我创建了一个包含键值的字典来跟踪每个单元格的状态,如下所示:

var cellStates = [NSIndexPath: Bool]()
for(var i = 0; i < cellImages.count; i++){
    cellStates[NSIndexPath(forRow: i, inSection: 0)] = false
}

cellStates[selectedCellIndex] = truedropDown 函数中设置。然后在 cellForItemAtIndexPath 函数中,我进行以下检查:

if(selectedIndex == indexPath && cellStates[indexPath] == true){

    for (var i = 0; i < 3; i++){
         var textView : UITextView! = UITextView(frame: CGRectMake(cell.frame.size.width - cell.frame.size.width/1.3, CGFloat(50 + (30 * (i+1))), CGRectGetWidth(cell.frame), CGFloat(25)))
         textView.backgroundColor = UIColor.whiteColor()
         cell.contentView.addSubview(textView)
         println("display subviews")
         println(indexPath)
    }
 } else {
     println("do not display subviews")
     println(indexPath)
 }

return cell

其中 selectedIndex,通过 dropDown 函数设置的活动单元格的 NSIndexPath 与正在创建的单元格的 indexPathcellState 被检查为 true.

还是不行 - 子视图仍然显示在回收的单元格上。我应该提到 "display subviews" 和 "do not display subviews" 在滚动时被正确记录,因此条件语句被成功评估。

我的(...破解...)解决方案! 可能打破了一堆最佳编码实践,但我为所有创建的子视图分配了标签,在 cellForItemAtIndexPath 方法的开头删除它们,如果 cellState 条件 returns 则再次创建它们true.

两件事之一: - 不允许合并细胞。 - 在您的模式中保持足够的信息,以便能够根据模型而不是它们在屏幕上的位置来绘制单元格。也就是说,在您的模型中存储一个位来确定是否显示每个 "logical" 单元格的三个视图。然后,当要求将一个单元格出列时,检查它的模型和 add/remove 动态背景。

没问题。基本上,您需要将程序状态存储在 UI 组件之外,通常称为 "model"。不确定您的应用程序是什么,所以我将编写一个示例。假设您想要显示一个网格,其中每个单元格最初都是绿色的,当用户点击它时它们会切换为红色。您需要将状态(即,一个单元格是否被点击)存储在某个二维数组中,该数组将包含所有单元格的布尔值,而不仅仅是当前显示的单元格(假设您有足够的使网格滚动的单元格)。当用户点击一个单元格时,您会在相应的数组元素中设置标志。然后,当 iOS 回调你提供一个单元格(在 dequeue 方法中)时,你检查数组中的状态,将适当的颜色应用于单元格的 UIView,然后 return 它。这样,iOS 可以重用单元格视图对象以提高效率,同时您可以动态地将模型状态应用于相应的单元格。让我知道是否清楚。