【问题标题】:How to dynamically change the height of a UITableView Cell containing a UICollectionView cell in Swift?如何在 Swift 中动态更改包含 UICollectionView 单元格的 UITableView 单元格的高度?
【发布时间】:2017-07-18 20:46:40
【问题描述】:

目前,我已在 UITableViewCellUITableView 的一个部分中嵌入了 UICollectionViewCell。我知道如何在UITableView 的另一部分动态更改单元格的高度,因为我在另一个UITableViewCell 中有一个UITextView,它根据UITextView 中的文本量动态更改单元格的高度。

我遇到的问题是关于包含UICollectionViewCellUITableViewCell。我的UICollectionViewCell 有一行 4 张图片,用户可以使用 UIImagePickerController 通过相机或照片库添加这些图片。

目前据我所知,当生成第五张图片时,UITableViewCell 的高度保持不变,但用户可以像这样在UICollectionViewCell 中水平滚动:

我的最终目标是这样的

还有我的故事板:

非常不言自明,但如果只有 4 张图片,UITableViewCell 与屏幕截图 1 中的相同,但如果 UICollectionViewCell 的高度发生变化,单元格的高度将动态变化。

我已将UICollectionView 的滚动方向设置为仅垂直。在进一步解释之前,这是我的部分代码:

class TestViewController: UITableViewController, UITextFieldDelegate, UITextViewDelegate, UIImagePickerControllerDelegate
{
    override func viewDidLoad()
    {
        super.viewDidLoad()

        ....

        tableView.estimatedRowHeight = 40.0
        tableView.rowHeight = UITableViewAutomaticDimension

    }

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

    {
        var cell: UITableViewCell = UITableViewCell()

        if indexPath.section == 1
        {
            cell = tableView.dequeueReusableCell(withIdentifier: "TextViewCell", for: indexPath)

            let textView: UITextView = UITextView()

            textView.isScrollEnabled = false

            textView.delegate = self
            cell.contentView.addSubview(textView)
        }
        else if indexPath.section == 4
        {
            if let imagesCell = tableView.dequeueReusableCell(withIdentifier: "ImagesCell", for: indexPath) as? CustomCollectionViewCell
            {
                if images_ARRAY.isEmpty == false
                {
                    imagesCell.images_ARRAY = images_ARRAY
                    imagesCell.awakeFromNib()
                }

                return imagesCell
            }

        }

        return cell
    }

    ....

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        if indexPath.section == 1
        {
            return UITableViewAutomaticDimension
        }
        else if indexPath.section == 4
        {
            //return 95.0
            return UITableViewAutomaticDimension
        }

        return 43.0
    }

    ....

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
    {
        if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage
        {
            if let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 4) ) as? CustomCollectionViewCell
            {
                cell.images_ARRAY.append(selectedImage)
                cell.imagesCollectionView.reloadData()
            }
        }
        picker.dismiss(animated: true, completion: nil)
    }

    ....

    func textViewDidChange(_ textView: UITextView)
    {
        ...
        // Change cell height dynamically
        tableView.beginUpdates()
        tableView.endUpdates()
    }
}

class CustomCollectionViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
{
    @IBOutlet var imagesCollectionView: UICollectionView!

    var images_ARRAY = [UIImage]()

    var images = [INSPhotoViewable]()

    override func awakeFromNib()
    {
        super.awakeFromNib()

        for image in images_ARRAY
        {
            images.append(INSPhoto(image: image, thumbnailImage: image) )
        }

        imagesCollectionView.dataSource = self
        imagesCollectionView.delegate = self
    }

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

    {
        return images_ARRAY.count
    }

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

    {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! ExampleCollectionViewCell

        cell.populateWithPhoto(images[(indexPath as NSIndexPath).row]

        return cell
    }

    ....

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
    {
        return UIEdgeInsetsMake(0.0, 25.0, 0.0, 25.0)
    }
}

最初,包含UICollectionViewCellindexPath.section == 4 返回高度95,但我将其注释掉并将其替换为返回UITableViewAutomaticDimension。我假设调整了单元格的高度以适合第 5 张图像,但即使 UICollectionViewCell' 高度发生变化,单元格仍保持静态高度,允许我在该静态 UITableViewCell 高度内垂直滚动。

我知道这些是我发现的一些与我的情况非常相似的问题,但它们并没有帮助我解决我的特定问题:

  1. Swift: Expand UITableViewCell height depending on the size of the UICollectionView inside it
  2. Auto Height of UICollectionView inside UITableViewCell
  3. UICollectionView inside a UITableViewCell — dynamic height?

根据一些答案和建议,我添加了以下内容:

imagesCell.images_ARRAY = images_ARRAY
imagesCell.awakeFromNib()

// Added code
imagesCell.frame = tableView.bounds
tableView.setNeedsLayout()
tableView.layoutIfNeeded()

但是,这没有任何影响。谁能指出我需要哪些代码并放置在哪里的正确方向?

谢谢!

【问题讨论】:

    标签: ios swift uitableview uicollectionviewcell


    【解决方案1】:

    我在我的代码中使用了这些类型的单元格,性能并不出色(因为会影响滚动平滑度),但可以让您实现所需的设计。

    1. 在tableViewCell 中使用CollectionView,垂直滚动方向和固定宽度(我的意思是本质上不是动态的)。这将在填充水平方向后将溢出的单元格放在垂直方向。
    2. 从 collectionViewHeight 的 xib(如果你正在使用它)中取出 NSLayoutConstraint。我们将在后面使用它。
    3. 在 tableView 中的 heightForRowAtIndexPath 方法中设置 UITableViewAutomaticDimension
    4. 最后使用我们在步骤 2 中取出的约束在 cellForRowAtIndexPath 方法中返回单元格时设置单元格的 collectionViewHeight。

    我在这里附上一些可能会有所帮助的代码:

    UITableView 部分:

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: xyzTableViewCell.self), for: indexPath) as! xyzTableViewCell
        cell.collectionViewHeight.constant = (numberOfCells/5) * cell.cellHeight
        return cell
    }
    

    UITableViewCell 部分:

    @IBOutlet fileprivate weak var collectionView: UICollectionView!
    @IBOutlet weak var collectionViewHeight: NSLayoutConstraint
    

    并且您将需要重新加载该特定 tableViewCell 并在此 tableViewCell 中重新加载 collectionView 以便调用 tableView 的高度函数并刷新该 tableViewCell 的高度,并处理该 tableViewCell 的聚焦条件(当 tableViewCell 处于焦点时),我这样说是因为如果它不在焦点中(或者说缓存,它们之间存在差异),那么在滚动时将调用 cellForRowAtIndexPath 方法(当这个单元格将成为焦点时)然后 tableViewCell 高度将已经被占用照顾。

    希望这将有助于实现所需的功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      相关资源
      最近更新 更多