在不使用重新加载方法的情况下调整 UICollectionView 单元格的大小

问题描述 投票:0回答:3

如何在没有

UICollectionView
方法的情况下调整
reload
的单元格大小? 只是想在某些事件上调用以下方法。我不想重新加载
UICollectionView
或其任何部分或行。

   func collectionView(collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                           sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 
ios uicollectionview uicollectionviewlayout
3个回答
55
投票

我通过以下代码行得到了问题的解决方案。

collectionView?.collectionViewLayout.invalidateLayout()

注意要以动画方式调整大小,请使用

UIView.animate
:

let duration: TimeInterval = 0.3
UIView.animate(withDuration: duration, animations: {
    collectionView.collectionViewLayout.invalidateLayout() 
})

1
投票

我可以确认 Payal Maniyar 的解决方案也适用于 UICollectionCompositional 布局。 在我的情况下,我有一个 CollectionViewCell 只嵌入了一个 UITextView。组合布局正确计算出单元格中文本视图的初始大小。 (旁注:您可以通过禁用 UITextView 内的滚动来实现此目的,因为它已经位于另一个可滚动视图内)。问题是当用户直接在文本视图中键入时,我想更改单元格的高度而不重新加载它。我想避免重新加载单元有两个原因。 a) 重新加载的单元格在用户键入时闪烁,b) 文本视图失去焦点;从而迫使用户再次单击文本视图以继续键入。所以我的解决方案如下:

  1. 我有一个单元格,里面只有 UITextView,其中该单元格也是 UITextView 的委托,如下所示:

    class MyCollectionCell: UICollectionViewCell {
      @IBOutlet private weak var myTextView: UITextView!
      //this local variable used to determine if the intrinsic content size has changed or not
      private var textViewHeight: CGFloat = .zero
      ...
      ...
      override func awakeFromNib() {
       super.awakeFromNib()
       myTextView.delegate = self
      }
      ...
      ...
    }
    
  2. 使此单元格符合 UITextViewDelegate

    extension MyCollectionCell: UITextViewDelegate { 
    
    func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
      //this assumes that collection view already correctly laid out the cell
      //to the correct height for the contents of the UITextView
      //textViewHeight simply needs to catch up to it before user starts typing
      let fittingSize = textView.sizeThatFits(CGSize(width: myTextView.frame.width, height: CGFloat.greatestFiniteMagnitude))
      textViewHeight = fittingSize.height
    
      return true
    }
    
    func textViewDidChange(_ textView: UITextView) {
      //flag to determine whether textview's size is changing
      var shouldResize = false
      //calculate fitting size after the content has changed
      let fittingSize = textView.sizeThatFits(CGSize(width: myTextView.frame.width, height: CGFloat.greatestFiniteMagnitude))
    
      //if the current height is not equal to 
      if textViewHeight != fittingSize.height {
        shouldResize = true
        //save the new height 
        textViewHeight = fittingSize.height
      }
    
      //notify the cell's delegate (most likely a UIViewController) 
      //that UITextView's intrinsic content size has changed
      //perhaps with a protocol such as this:
      delegate?.textViewDidChange(newText: textView.text, alsoRequiresResize: shouldResize)
    }
    
  3. 然后,当委托收到通知时,可能会保存更新的文本并更新布局,如下所示:

    myCollectionView.collectionViewLayout.invalidateLayout()
    

此解决方案最好的部分是您不必调用 collectionView(_:layout:sizeForItemAt:) 来调整单元格大小,因为您一开始就没有使用笨重的 FlowLayout。

干杯!


0
投票

我正在播放里面的视频

UICollectionViewCell
。我发现
UIView.animate
无法正确使用淡入淡出动画更新高度。下面的代码完美运行。

collectionView.performBatchUpdates({
    collectionView.collectionViewLayout.invalidateLayout()
})
© www.soinside.com 2019 - 2024. All rights reserved.