如何在Swift中动态更改包含UICollectionView单元格的UITableView单元格的高度?

时间:2017-07-18 20:46:40

标签: ios swift uitableview uicollectionviewcell

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

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

目前正如我所知,当生成第5张照片时,UITableViewCell的高度保持静止,但用户可以像UICollectionViewCell一样水平滚动:

enter image description here

我的最终目标是enter image description here

我的故事板:

enter image description here

相当不言自明但如果只有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)
    }
}

最初,我的indexPath.section == 4包含UICollectionViewCell,其返回的高度为 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?
  4. 通过一些答案和建议,我添加了以下内容:

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

    然而,这没有任何影响。任何人都可以指出我正确的方向我需要什么代码并放在哪里?

    谢谢!

1 个答案:

答案 0 :(得分:0)

我在我的代码中使用这些类型的单元格,没有表现出优异的性能(影响滚动平滑度),但会让你实现所需的设计。

  1. 在tableViewCell中使用CollectionView,使用Vertical ScrollDirection和固定宽度(我的意思是不是动态的)。填充水平方向后,这将使溢出的单元在垂直方向上。
  2. 从collectionViewHeight的xib(如果使用的话)中取出NSLayoutConstraint。我们将在后面部分使用它。
  3. 在heightForRowAtIndexPath方法的tableView中设置 UITableViewAutomaticDimension
  4. 最后设置cell的collectionViewHeight,同时使用我们在步骤2中取出的约束返回cellForRowAtIndexPath方法中的单元格。
  5. 这里我附上一些可能有用的代码:

    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 Part:

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

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

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