ios - 使用 UIStackView 时 UIImageView 被挤压到 UITableViewCell 内

标签 ios swift uitableview uistackview

UIStackView 中使用 UIImageView 时,我看到一些奇怪的行为,我怀疑有一些明显的东西被我忽略了 - 尽管我已经尝试了很多事已至此。

我想做的事情非常简单:从网络下载图像,在UIStackView内设置UIImageViewUIStackView 还包含一个 UILabel (而我的实际项目包含相当多的 UILabels,因此 UIStackView 的原因>)。下图有彩色背景来展示哪里出了问题,而且我还包含了完整的 Playground 代码,以便轻松复制/粘贴。

正在下载的图像大于屏幕的宽度/高度,并且我设置了 contentMode = .scaleAspectFitUITableView 使用
tableView.rowHeight = UITableViewAutomaticDimension.estimatedRowHeight。我已经设置了约束,并且还尝试在 UIImageView 上设置拥抱优先级,但无济于事。我事先不知道确切的单元高度,并且单元高度都会有所不同。

实际发生的情况是,尽管 UIImageView 上存在前导/尾随约束、UIStackView 上的约束、.rowHeight,但图像的大小调整得非常小单元格上的 ,以及 UIImageView 上的 .scaleAspectFit。您甚至可以看到一小条(红色)标签,因此我知道 UIStackView 已固定到 UITableViewCellcontentView

颜色键

  • 橙色:UITableViewCell 背景
  • 红色:UILabel 背景
  • 绿色:UIImageView 背景

enter image description here

import UIKit
import PlaygroundSupport



class CustomView: UIView, UITableViewDataSource {

    var tableView = UITableView()
    var tableData = [String]()

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = UIColor.gray

        tableView.dataSource = self
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 300
        tableView.tableFooterView = UIView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(tableView)
        tableView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        tableView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        tableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        tableData = [String](repeating: "https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/video/wibbitz/wbz-breakfast-most-important-meal.jpg", count: 2)
        tableView.register(CustomCell.self, forCellReuseIdentifier: "cell")
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tableData.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
        let imageURL = tableData[indexPath.row]
        if let url = URL.init(string: imageURL) {
            cell.cellImageView?.downloadImage(with: url,
                                              completion: {
                                                // ...
            })
        }
        return cell
    }
}

class CustomCell: UITableViewCell {

    var cellImageView: UIImageView?

    required init?(coder aDecoder: NSCoder) {
        fatalError() // since we're not using
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupCell()
    }

    func setupCell() {

        backgroundColor = UIColor.orange
        clipsToBounds = true

        let tempLabel = UILabel()
        tempLabel.translatesAutoresizingMaskIntoConstraints = false
        tempLabel.backgroundColor = UIColor.red
        tempLabel.text = "this is some text"
        tempLabel.numberOfLines = 0
        tempLabel.font = UIFont.systemFont(ofSize: 20, weight: .bold)

        cellImageView = UIImageView()
        cellImageView?.clipsToBounds = true
        cellImageView?.contentMode = .scaleAspectFit
        cellImageView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        cellImageView?.backgroundColor = UIColor.green
        cellImageView?.translatesAutoresizingMaskIntoConstraints = false

        let stackView = UIStackView(arrangedSubviews: [tempLabel, cellImageView!])
        contentView.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.distribution = .fillProportionally
        stackView.alignment = .leading
        stackView.spacing = 10
        stackView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
        cellImageView?.leadingAnchor.constraint(equalTo: stackView.leadingAnchor).isActive = true
        cellImageView?.trailingAnchor.constraint(equalTo: stackView.trailingAnchor).isActive = true

    }

}

extension UIImageView {

    func downloadImage(with url: URL, completion: @escaping () -> Void) {

        let task = URLSession.shared.dataTask(with: url) { [weak weakSelf = self] data, response, error in

            guard error == nil else {
                print("UIImageView: error downloading image: \(String(describing: error))")
                return
            }

            guard let data = data, let downloadedImage = UIImage.init(data: data) else {
                print("UIImageView: issue with data from downloaded image.")
                return
            }

            DispatchQueue.main.async {
                weakSelf?.image = downloadedImage
                completion()
            }
        }
        task.resume()
    }
}

let containerView = CustomView(frame: CGRect(x: 0, y: 0, width: 400, height: 600))
containerView.backgroundColor = UIColor.blue

PlaygroundPage.current.liveView = containerView
PlaygroundPage.current.needsIndefiniteExecution = true

最佳答案

您似乎认为堆栈 View 内的 ImageView 会以某种方式从内到外调整单元格的高度。不会的。如果您想使用自动单元格高度,请不要使用堆栈 View (或添加约束以显式调整堆栈 View 的大小,但我怀疑这会给您带来所需的结果)。

代码中堆栈 View 的用途是什么?堆栈 View 所做的只是在困难的情况下为您设置限制。但这并不是一个困难的情况。标签和 ImageView 一起可以轻松地手动配置。

关于ios - 使用 UIStackView 时 UIImageView 被挤压到 UITableViewCell 内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49881283/

相关文章:

objective-c - 读取属性时CoreData泄漏

swift - 这是什么错误: couldn't get mapped to 10 iovecs due to fragmentation

ios - Swift - 以编程方式更改 UICollectionViewCell 大小

ios - UITableView contentSize 和 origin

ios - 为什么我们必须同时符合 UIViewController 和 UITableViewDataSource?

ios - 秒表单圈计时器

iphone - 在iOS的Facebook中像在Facebook中一样在UINavigationController中向后滑动

ios - 在 iPad 中加载 PDF

ios - 在 Swift 中收到新数据时返回新的 Cell

swift - 获取 DDMathParser token 和组 token