Reputation: 3016
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.
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
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
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:
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.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)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