Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
540 views
in Technique[技术] by (71.8m points)

ios - Swift - Dynamic UITableViewCell size based on image aspect ratio

I'm trying to create dynamically sized UITableViewCells, changing the height based on the aspect ratio of an image downloaded from a server.

For example, if an image's height is double its width, I want the UITableViewCell's height to be double the screen width so that the image can take up the full width of the screen and maintain the aspect ratio.

What I've tried to do is add constraints to the cell and use UITableViewAutomaticDimension to calculate the height, but the problem I'm facing is that I cannot know the aspect ratio of the image until it is downloaded, and therefore the cells start off small and then once the tableView is refreshed manually the cell appears with the right size.

I don't feel like reloading each individual cell when it's image is downloaded is a great way to do things either.

Is this approach the best way to do it? I can't for the life of me think how else to do this, as I can't know the aspect ratio from within the cell itself when it's being initialized.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

For achieve this I use first a dictionary [Int:CGFloat] to keep the calculated heigths of cells then in the heightForRowAtIndexpath method use the values keeped in your dictionary, in your cellForRowAtIndexpath method you should download your image, calculate the aspect ratio, multiply your cell width or your image width by your aspect ratio and put the height calculated in correspondent IndexPath number in your dictionary

In code something like this, this is an example of code using alamofire to load the images

    var rowHeights:[Int:CGFloat] = [:] //declaration of Dictionary


    //My heightForRowAtIndexPath method
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if let height = self.rowHeights[indexPath.row]{
            return height
        }else{
            return defaultHeight
        }
    }

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

if let cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell") as? ImageCell
        {
        let urlImage = Foundation.URL(string: "http://imageurl")
        cell.articleImage.af_setImage(withURL: urlImage, placeholderImage: self.placeholderImage, filter: nil, imageTransition: .crossDissolve(0.3), completion: { (response) in

            if let image = response.result.value{
                DispatchQueue.main.async {

                    let aspectRatio = (image! as UIImage).size.height/(image! as UIImage).size.width
                    cell.articleImage.image = image
                    let imageHeight = self.view.frame.width*aspectRatio
                    tableView.beginUpdates()
                    self.rowHeights[indexPath.row] = imageHeight
                    tableView.endUpdates()

                }
            }
        })
        }

I hope this helps


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...