Chirag Shah
Chirag Shah

Reputation: 3016

Make tableview cell height dynamically after download image from server

I have one cell in which i show images download from server now. Right now i show image with static height but now i want to make dynamic like facebook and instagram. For example if i upload image 320 * 100 then my cell need to become 300*100. and also suggest server side changes if required I am using afnetworking image loading classes.

Here is my cell design . enter image description here

EDIT: I tried given solution but now issue is that cell resize with jerk when second time it's come in cellforindexpath method. This will happen in first cell only.

Upvotes: 1

Views: 4848

Answers (2)

Manish Mahajan
Manish Mahajan

Reputation: 2082

I have solved this problem. If you have to make imageview height and width dynamic then ask server to send image width and Height in API response. Once you get both, according to image width and screen width calculate the image height. Take constraint of image height. And assign calculated height to image height constraint.

To calculate image height use below formula:-

imageHeight =  (screen_width * actual_image_height) / actual_image_width

Upvotes: 2

Ratul Sharker
Ratul Sharker

Reputation: 8011

I have done similar task, showing the images on the table and resize the tableview cell so that the image is shown along the fullscreen width

Height For Row At IndexPath

var cachedHeight = [IndexPath : CGFloat]()
    override func tableView(_ tableView: UITableView, heightForRowAtindexPath: IndexPath) -> CGFloat {

    let default_height : CGFloat = 332.0

    // lookup for cached height
    if let height = cachedHeight[indexPath]{
        return height
    }

    // no cached height found
    // so now try for image so that cached can be calculated and cached
    let cache : SDImageCache = SDImageCache.shared()
    let image : UIImage? = cache.imageFromDiskCache(forKey: self.viewModel?.getProductImage(of: indexPath.row, at: 0))

    if let image = image{
        let baseHeight : CGFloat = CGFloat(332 - 224)   // cell height - image view height
        let imageWidth = self.tableView.frame.size.width
        let imageHeight = image.size.height * imageWidth / image.size.width

        cachedHeight[indexPath] = imageHeight + baseHeight
        return cachedHeight[indexPath]!
    }

    //
    //  even if the image is not found, then
    //  return the default height
    //
    return default_height
}

Cell For Row At IndexPath

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

    let sdCache = SDImageCache.shared()
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyXYZCell", for: indexPath) as! AuctionListTableViewCell
    let imageURL = self.viewModel?.getProductImage(of: indexPath.row, at: 0)

    if let imageURL = imageURL {
        if (sdCache.imageFromCache(forKey: imageURL) != nil) {
            //
            //  image data already persist on disk,
            //  cell height update required
            //
            cell.auctionImageView.sd_setImage(with: URL.init(string: imageURL), completed: nil)
        }
        else
        {
            cell.auctionImageView.sd_setImage(with: URL.init(string: imageURL), completed: { (image, err, cacheType, url) in
                self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)
            })
        }
    }

    //other cell customization code

    return cell
}

I have used SDWebImage. You can use it, or find similar api in AFNetworking.

Keynotes:

  1. Here cachedHeight is used to cache the height of the cell indexed by the IndexPath, because reading the image from the disk is quiet I/O exhaustive task, which results lag in the table view scroll.
  2. In heightForRow i checked that, is the image is in cache, if in cache, then calculate the height, store it into the cachedHeight, otherwise return the default height. (My default height is calculated for my placeholder image)
  3. In the cellForRowAtIndexPath i have checked is the image is in cache. If the image is in cache, then no reload is required as the height is already calculated. Otherwise i attempt a network fetch, when the fetch completed i request to tableview to reload that cell.

Hope it helps, Happy coding.

Upvotes: 4

Related Questions