如何在Swift中动态更改包含UICollectionView单元格的UITableView单元格的高度? [英] How to dynamically change the height of a UITableView Cell containing a UICollectionView cell in Swift?

查看:188
本文介绍了如何在Swift中动态更改包含UICollectionView单元格的UITableView单元格的高度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我已经在UITableView部分之一的UITableViewCell中嵌入了UICollectionViewCell.我知道如何在UITableView的另一部分中动态更改单元格的高度,因为我在另一个UITableViewCell中具有UITextView,该UITextView根据UITextView中的文本量来动态更改单元格的高度. /p>

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

目前,在生成第5张图片时,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:根据以下情况扩展UITableViewCell的高度的大小 里面的UICollectionView
  2. UITableViewCell内部的UICollectionView的自动高度
  3. UITableViewCell内的UICollectionView —动态高度?

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

imagesCell.images_ARRAY = images_ARRAY
imagesCell.awakeFromNib()

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

但是,这没有任何效果.谁能指出我需要什么代码并放在何处的正确方向?

谢谢!

解决方案

我在我的代码中使用了这些类型的单元格,不是明智地执行出色的性能(因为会影响滚动的平滑性),但是会让您实现所需的设计.

  1. 在tableViewCell内部使用CollectionView并具有Vertical ScrollDirection和固定宽度(我的意思是本质上不是动态的).填充水平方向后,会将溢出的单元格置于垂直方向.
  2. 从collectionViewHeight的xib(如果正在使用)中获取NSLayoutConstraint.我们将在以后的部分中使用它.
  3. 在heightForRowAtIndexPath方法的tableView中设置 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的height函数并刷新该tableViewCell的高度,并处理该tableViewCell的集中条件(当tableViewCell处于焦点时),我之所以这样说是因为,如果它不在焦点上(或者说缓存,虽然它们之间有区别),那么在滚动时将调用cellForRowAtIndexPath方法(当此单元格将成为焦点时),那么tableViewCell高度将已经被获取照顾.

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

Currently, I have embedded a UICollectionViewCell in a UITableViewCell within one of the sections of my UITableView. I know how to dynamically change the cell's height in another section of my UITableView because I have a UITextView in another UITableViewCell that dynamically changes the height of the cell based on how much text is in the UITextView.

The problem I have is in regards to the UITableViewCell containing the UICollectionViewCell. My UICollectionViewCell has one row of 4 images that the user can add via the camera or photo library using a UIImagePickerController.

Currently as I have it, when the 5th picture is generated, the UITableViewCell's height remains static, but the user can scroll horizontally in the UICollectionViewCell like so:

My end goal is this:

And my storyboard:

Pretty self-explanatory but if there is only 4 images, the UITableViewCell remains the same as in screenshoot 1, but the cell's height will dynamically change if the UICollectionViewCell's height changes.

I have set the UICollectionView's scroll direction to be vertical only. Before explaining further, here's my partial code:

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)
    }
}

Originally, my indexPath.section == 4, which contains the UICollectionViewCell returned a height of 95, but I commented that out and replaced it with returning UITableViewAutomaticDimension. I would assume that adjusted the height of the cell to fit the 5th image, but the cell remained a static height even though the UICollectionViewCell' height changed, allowing me to scroll vertically within that static UITableViewCell height.

I know these are some questions I found very similar to my situation, but they didnt help me resolve my particular issue:

  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?

With some of the answers and suggestions, I've added the following:

imagesCell.images_ARRAY = images_ARRAY
imagesCell.awakeFromNib()

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

However, this did not have any effects. Can anyone point me in the right direction on what code I need and placed where?

Thanks!

解决方案

I am using these type of cells in my code, Not performing excellent performance wise(as affecting scrolling smoothness) but will let you achieve required design.

  1. Use CollectionView inside tableViewCell with Vertical ScrollDirection and fixed width(I mean not dynamic in nature). This will put overflowing cells in vertical direction after filling horizontal direction.
  2. Take out NSLayoutConstraint from xib(if you are using that) of collectionViewHeight. We will use it in later part.
  3. set UITableViewAutomaticDimension in tableView in heightForRowAtIndexPath method.
  4. And finally set cell's collectionViewHeight while returning cell in cellForRowAtIndexPath method using constraint that we took out in step 2.

Here I am attaching some code that may will help:

UITableView Part:

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

And you will need to reload that particular tableViewCell and reload collectionView inside this tableViewCell so that height function of tableView will be called and height of that tableViewCell will be refreshed, and to handle focused condition of that tableViewCell(when tableViewCell is in focus), I am saying this because if it's not in focus(or say cache, there is difference between them though) then cellForRowAtIndexPath method will be called on scrolling(when this cell is going to come in focus) then tableViewCell height will already be taken care of.

Hope this will help to achieve required functionality.

这篇关于如何在Swift中动态更改包含UICollectionView单元格的UITableView单元格的高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆