【问题标题】:How to resize UIImageView after loading image from URL w/ Kingfisher从带翠鸟的 URL 加载图像后如何调整 UIImageView 的大小
【发布时间】:2019-06-15 01:06:08
【问题描述】:

我想调整所有下载的图像的大小,以保持它们的纵横比,但它们都与渲染它们的 UITableViewCell 一样宽。

我的 UIImageView 使用 contentMode 配置为 AspectFit,并且我的单元格上有以下锚点:

目前的尝试我快到了:

class AnimatedImageTableViewCell: UITableViewCell {
    @IBOutlet weak var gifView: AnimatedImageView!
    @IBOutlet weak var imageHeightAnchor: NSLayoutConstraint!

    var refreshCell: (() -> Void)?

    func render(imageUrl: String) {
        guard let url = URL(string: imageUrl) else { return }

        gifView.kf.setImage(with: url) { result in
            switch result {
            case .success(let value):
                let ratio = value.image.size.width / value.image.size.height
                let newHeight = self.gifView.frame.width / ratio
                self.imageHeightAnchor.constant = newHeight
                self.refreshCell?()
            case .failure(let error):
                print(error) // The error happens
            }
        }
    }
}

还有:

class HomeViewController: UITableViewController {

    let images = [
        "https://cdn-images-1.medium.com/max/1600/1*OJxJTJLSyqJ0nMeuswuCSQ.gif",
        "https://static1.squarespace.com/static/552a5cc4e4b059a56a050501/565f6b57e4b0d9b44ab87107/566024f5e4b0354e5b79dd24/1449141991793/NYCGifathon12.gif",
        "https://media2.giphy.com/avatars/100soft/WahNEDdlGjRZ.gif"
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.tableFooterView = UIView()
        tableView.estimatedRowHeight = 200
        tableView.rowHeight = UITableView.automaticDimension
        tableView.allowsSelection = false

        let nib = UINib(nibName: "AnimatedImageTableViewCell", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "cellId")

    }

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


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let imagePath = images[indexPath.item]

        let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! AnimatedImageTableViewCell

        cell.refreshCell = {
            tableView.reloadRows(at: [indexPath], with: .automatic)
        }

        cell.render(imageUrl: imagePath)

        return cell
    }
}

但是在某些情况下,单元格太高了。图像呈现全宽,具有正确的纵横比,图像上方和下方的空间太大。

我在控制台中也收到如下错误:

(
    "<NSLayoutConstraint:0x600000329770 Kingfisher.AnimatedImageView:0x7fd339e19330.height == 268.5   (active)>",
    "<NSLayoutConstraint:0x60000032a8f0 Kingfisher.AnimatedImageView:0x7fd339e19330.top == UITableViewCellContentView:0x7fd339e1a280.topMargin + 8   (active)>",
    "<NSLayoutConstraint:0x60000032a850 UITableViewCellContentView:0x7fd339e1a280.bottomMargin == Kingfisher.AnimatedImageView:0x7fd339e19330.bottom + 8   (active)>",
    "<NSLayoutConstraint:0x60000032a7b0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x600001908ee0'UIViewLayoutMarginsGuide']-(8)-|   (active, names: '|':UITableViewCellContentView:0x7fd339e1a280 )>",
    "<NSLayoutConstraint:0x600000323980 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fd339e1a280.height == 450.5   (active)>",
    "<NSLayoutConstraint:0x60000032a6c0 'UIView-topMargin-guide-constraint' V:|-(8)-[UILayoutGuide:0x600001908ee0'UIViewLayoutMarginsGuide']   (active, names: '|':UITableViewCellContentView:0x7fd339e1a280 )>"
)

【问题讨论】:

  • 您使用的是哪个 kingFisher 版本号?
  • 嘿,我用的是5.0版

标签: swift uitableview uiimageview kingfisher


【解决方案1】:

尝试使用提供的代码重新创建您的项目,一切都按预期工作,直到我注意到您的图像视图受限于单元格内容视图边距。然后它开始抛出那些布局错误并且单元格变得不合理地高。所以我的猜测是您需要确保您的图像视图约束与单元格边距无关。

还要确保您的视图控制器中没有 heightForRowAt 覆盖。

要完全摆脱自动布局错误,您可以将底部约束优先级设置为 999(blog post 解释为什么优先级有帮助)

【讨论】:

    【解决方案2】:

    您可以简单地在设置其image 属性后尝试调整图像视图的大小。例如:

    class ResizableImageView: UIImageView {
    
      override var image: UIImage? {
        didSet {
          guard let image = image else { return }
    
          let resizeConstraints = [
            self.heightAnchor.constraint(equalToConstant: image.size.height),
            self.widthAnchor.constraint(equalToConstant: image.size.width)
          ]
    
          if superview != nil {
            addConstraints(resizeConstraints)
          }
        }
      }
    }
    

    然后,添加忽略heightAnchorwidthAnchor 的常规约束,因为一旦添加图像就会添加它们(我建议此时不要使用界面生成器):

    let imageView = ResizableImageView(frame: .zero)
    imageView.translatesAutoresizingMaskIntoConstraints = false
    
    view.addSubview(imageView)
    
    // These are only illustrative constraints
    imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    
    imageView.image = image
    

    这是一个完整且功能齐全的示例:

    class ViewController: UIViewController {
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        downloadImage(
          fromURL: URL(string: "https://img.evbuc.com/https%3A%2F%2Fcdn.evbuc.com%2Fimages%2F33105753%2F184176199496%2F1%2Foriginal.jpg?h=200&w=450&rect=0%2C0%2C400%2C200&s=a92a5a03c153d312d682b2dfedd6a6ad")!,
          completionHandler: { [weak self] image in
            guard let self = self, let image = image else { return }
    
            let imageView = ResizableImageView(frame: .zero)
            imageView.translatesAutoresizingMaskIntoConstraints = false
    
            self.view.addSubview(imageView)
    
            imageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
            imageView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    
            imageView.image = image
          })
      }
    
      func downloadImage(fromURL url: URL, completionHandler: @escaping (UIImage?) -> Void) {
        let operationQueue = OperationQueue()
    
        operationQueue.addOperation {
          guard let data = try? Data(contentsOf: url) else {
            OperationQueue.main.addOperation {
              completionHandler(nil)
            }
    
            return
          }
    
          OperationQueue.main.addOperation {
            let image = UIImage(data: data)
            completionHandler(image)
          }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      相关资源
      最近更新 更多