以编程方式将 UILabel 添加到 CollectionViewCells

Posted

技术标签:

【中文标题】以编程方式将 UILabel 添加到 CollectionViewCells【英文标题】:Add UILabel to CollectionViewCells programmatically 【发布时间】:2017-09-03 12:05:24 【问题描述】:

我的应用程序需要多个CollectionViews,因此我决定以编程方式创建它们。我在每个单元格中添加了一个UILabel,但是 UILabel 仅添加到随机的 cells 中,而其他的不显示任何标签。

如果我上下滚动 textLabels 在某些单元格中随机消失并重新出现在其他单元格中。 这是问题的直观描述

(注意标签在我向下滚动时消失)

我需要所有单元格来显示 textLabels。

这是我正在使用的代码:

视图控制器

  override func viewDidLoad() 
    super.viewDidLoad()


   let frame =                  CGRect(x: 0 , y: 50 , width: 375 , height: 300)
   let layout =                 UICollectionViewFlowLayout()
   let collectionView =         UICollectionView(frame: frame , collectionViewLayout: layout)
    collectionView.delegate =   self
    collectionView.dataSource = self
    collectionView.register(CustomCell.self, forCellWithReuseIdentifier: NSStringFromClass(CustomCell.self))
    view.addSubview(collectionView)




func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return 250    

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

    let cell =             collectionView.dequeueReusableCell( withReuseIdentifier: NSStringFromClass(CustomCell.self), for: indexPath) as! CustomCell
    cell.nameLabel.text =  "XYZ"
    return cell


II 自定义单元格

class CustomCell: UICollectionViewCell 

 var nameLabel:  UILabel!

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

    nameLabel =                 UILabel(frame:   self.frame)
    nameLabel.textAlignment =  .left
    nameLabel.textColor =      .black
    contentView.addSubview(nameLabel)
    contentView.backgroundColor = .red
  

required init(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


  

是什么导致了这种异常行为?我是否错误地设置了我的collectionView

【问题讨论】:

func CollectionView(_ CollectionView: UICollectionView, heightForRowAt indexPath: IndexPath) -> CGFloat .这是什么?这是您返回 UICollectionViewCell developer.apple.com/documentation/uikit/… 的大小的方式 很抱歉这是一个错字。我更新了代码。 以编程方式创建 UILabel 需要您设置 IB 为您执行的所有属性,因此,请查看:***.com/questions/17813121/… 还有,您是否尝试过将 UILabel 放在前面?第二个问题,看起来你出队问题,尝试在 awakeFromNib 方法中设置标签。 @6994 您应该使用约束以编程方式设置标签,并避免使用框架。 @TusharSharma 你是绝对正确的。应避免框架。我通过用边界替换它解决了这个问题。 【参考方案1】:

您在nameLabel = UILabel(frame: self.frame) 这一行中做错了,实际上您给出的位置与集合视图单元格的位置(x 和 y 坐标)相同,这是错误的。你需要给 nameLabel 的位置 x=0 和 y=0,然后它就可以正常工作了。定义nameLabel的frame如下:

var nameLabel:  UILabel = UILabel(frame: CGRect.zero)

override init(frame : CGRect) 
    super.init(frame : frame)
    nameLabel.frame.size = CGSize(width: self.frame.width, height: self.frame.height)

输出如下:

【讨论】:

感谢您的解决方案。这是一个非常粗心的错误。【参考方案2】:

这看起来像是出队问题,因为它发生在单元出队期间。

您应该在 awakeFromNib 方法中初始化 UILabel - 这样每次单元格出列时,您将创建所需的标签。

此外,由于您正在以编程方式创建 UILabel,因此您应该看看这个answer,基本上,当您以编程方式创建 UILabel 时,您应该设置更多值。

我还建议在创建标签时使用bringSubViewToFront。

【讨论】:

感谢您的回答。我不知道 awakeFromNib 会有什么用,因为我没有使用 InterfaceBuilder 。我也尝试在cellForItemAtIndexPath 方法中使用bringSubviewToFront,但这也没有用。 只需覆盖 awakeFromNib 并将您的代码重构为 awakeFromNib - 它对故事板和 nib 都有好处。如果您仍然坚持,您始终可以在单元格内创建一个设置方法(将您的 UILabel 代码重构到其中)并在 cellForRow 内的出列后调用它,但这是一个不好的做法 我以编程方式做所有事情,因此既没有故事板也没有 nib。 @6994,所以在你的单元格中创建一个方法,将其命名为 setupCell() 并将 UILabel 创建封装在其中。在每个单元格出列后调用此方法【参考方案3】:

问题是每个单元格都有不同的frame.origin 值,因此设置UILabel(frame : self.frame ) 是不正确的。

示例:

   let label = UILabel(frame: self.frame)
   print(self.frame)                     // (130.0, 420.0, 50.0, 50.0)

 // the origin of the label is now CGPoint(130.0, 420.0) with respect to the 
 //cell it would be totally out of bounds somewhere down below.               

每个UILabelorigin 必须是CGPoint(x :0,y :0),以便它显示在其各自单元格的正上方。

因此,简单的解决方案是用边界替换框架。

   let label = UILabel(frame: self.bounds)

【讨论】:

以上是关于以编程方式将 UILabel 添加到 CollectionViewCells的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将 UILabel 添加到工具栏

以编程方式将点击手势添加到 UILabel

以编程方式将 UILabel 添加到集合单元,快速

以编程方式将 UILabel 添加到自定义 tableViewCell

以编程方式将 UILabel 和 UIImageViews 添加到 UIScrollView

在 Swift 4 中以编程方式将 UIImageView、UILabel 添加到 UIStackView