Resizing UITableViewCell after loading image - ios

I am using dynamic height for tableview cells and Haneke for downloading and caching image using the following code:
override func viewDidLoad() {
super.viewDidLoad()
myTableView.rowHeight = UITableViewAutomaticDimension
myTableView.estimatedRowHeight = 500
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:ImageCellTableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ImageCellTableViewCell;
cell.myImageView.hnk_setImage(from: URL(string: imageUrl), placeholder: nil)
return cell
}
Here I need to resize the cell height when setting image after downloading.
How can I resize the tableview cell after downloading the image.

Just call
tableView.beginUpdates()
tableView.endUpdates()
after image is downloaded and height constraint is set. Hope this helps!
EDIT:
Another option, to give the right height to the cell, would be receiving the image size from the server. This way you could feed table with just right calculated cell height.

just add the proper constraint to your image, for example , top and left constraint with, aspect ratio constraint.(you can do it even in your storyboard interface)

Set table view's row height like:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:ImageCellTableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ImageCellTableViewCell;
cell.myImageView.hnk_setImage(from: URL(string: imageUrl), placeholder: nil)
tableView.rowHeight = cell.myImageView.frame.origin.y + cell.myImageView.frame.size.height + (constant what every you want to give like: - 20/30 as per your need)
return cell
}

Related

reloadData for UITableView changes constraints

I have a UITableView set up with cells: (no conflicting constraints)
Storyboard and Constraints
Looks like:
Pre-refresh
However, whenever I refresh using
self.tableView.reloadData()
the constraints seem to change which changes the cell into:
Post-refresh
Any suggestions as to why this happens?
Code for cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CaptureCell
let capture = tabBar?.captureArray[indexPath.row]
cell.capsuleImage.image = capture?.image
return cell
}
The cell identifier is "cell" and I have CaptureCell which is a subclass of UITableViewCell.

Dynamic Table Image View in Swift

I have a very similar question as posted here (Dynamic UIImageView Size Within UITableView) where I'm trying to dynamically retrieve an image from Firebase and make the resulting tableview adjust to the height of the image given a fixed width across the screen based on the aspect ratio. All the articles I read says to make the cell calculation based on cellforRowAt, but my actual image is within the TableViewCell. Can someone please help?
Tableview controller:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FeedTableViewCell", for: indexPath) as! FeedTableViewCell
cell.configureCell(post: postArray[indexPath.row])
return cell
}
TableViewCell:
func configureCell(post: Post){
self.postImage.sd_setImage(with: URL(string: post.postImageURL),
placeholderImage: UIImage(named: "default"))
}
you have cell.setNeedsLayout() inside the completion handler of setting image method, like this:
cell. postImage.kf.setImage(with: URL) { _, _, _, _ in
cell.layoutIfNeeded()
}
First of all, you need to use Autolayout to calculate the proper cell height by creating a proper set of constraints that would determine the cell height based on content. I am going to assume you did that.
Then you have to tell the tableView you want it to use Autolayout to calculate height:
// my best estimation of the height
tableView.estimatedRowHeight = 144
// but the real height is calculated by autolayout
tableView.rowHeight = UITableViewAutomaticDimension
Now this would work if the autolayout could calculate the height correctly in cellForRowAt. But since the image is downloaded asynchronously, the image is set later, when the cell may be already presented. This requires you to provide a way in which a cell can tell the tableView that it has downloaded its content and its layout needs to be recalculated. To do so, use this method in the viewController with the tableView:
func recalculateTableViewLayout() {
self.tableView.beginUpdates()
self.tableView.setNeedsLayout()
self.tableView.endUpdates()
}
You will need to pass the reference to the viewController with the tableView to each cell (I recommend to use delegate pattern for that, here for brevity I will simply sketch it using it directly):
class FeedTableViewCell: UITableViewCell {
weak var feedViewController: FeedViewController?
// etc.
And in the cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FeedTableViewCell", for: indexPath) as! FeedTableViewCell
cell.feedViewController = self
cell.configureCell(post: postArray[indexPath.row])
return cell
}
Then use completion handler of sd_setImage to tell the tableView to recalculate its layout when the image gets downloaded:
func configureCell(post: Post){
self.postImage.sd_setImage(with: URL(string: post.postImageURL), placeholderImage: UIImage(named: "default")) { (image, error, cache, url) in
self.feedViewController?.recalculateTableViewLayout()
}
}

Issue with auto layout - vertical spacing

In Xcode 8 with Swift 3 I'm using custom cell with auto layout. Information into cell inserted from JSON, so my code looks like:
//the method returning each cell of the list
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "Feedcell", for: indexPath) as! FruitTableViewCell
//getting the hero for the specified position
let hero: List_Feed
hero = heroes[indexPath.row]
cell.labelAnswer.text = hero.answer
cell.labelQuestion.lineBreakMode = .byWordWrapping
cell.labelQuestion.text = hero.question
cell.labelQuestion.sizeToFit()
cell.labelAnswer.sizeToFit()
return cell
}
Problem is that I'm getting equal labelQuestion heigh for each cell, but text size and line size are different. How to solve this? :c
As Cell is reusing the Label You have to empty label before use for next cell
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "Feedcell", for: indexPath) as! FruitTableViewCell
//EMPTY LABELS
cell.labelAnswer.text = ""
cell.labelQuestion.text = ""
self.layoutIfNeeded()
//getting the hero for the specified position
let hero: List_Feed
hero = heroes[indexPath.row]
cell.labelAnswer.text = hero.answer
cell.labelQuestion.lineBreakMode = .byWordWrapping
cell.labelQuestion.text = hero.question
cell.labelQuestion.sizeToFit()
cell.labelAnswer.sizeToFit()
return cell
}
Hope it is helpful to you
1- set vertical content hugging priority off today label to 1000
2- hook the bottom of the label [ that is under today label ] to the top of the imageView Below it
3- hook bottom of the most-down label to bottom of contentView
Edit :
Add this 2 lines before return cell in cellForRowAt
cell.layoutSubviews()
cell.layoutIfNeeded()

Standard TableView Cell - label text overlaps with uiimage

This is happening but I don't know why. It is a standard tableviewcell with a label and an image on it
Here is the code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = patientsTableView.dequeueReusableCell(withIdentifier: "patientTableViewCell", for: indexPath)
let text = "Bob Marley"
cell.textLabel?.text = text
return cell
}
When I do not put an image view in the object inspector but like below, it solves the problem. I am not sure why though
cell.imageView?.image = UIImage(named: "patients")

Dynamic image height in tableview not working for initial few cell

I am trying to make dynamic image height in tableview. i used SDWebImage to download image from URL. but it's not working on few initial cell
Here below methods that i wrote
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let shareDetailCell = tableView.dequeueReusableCell(withIdentifier: THShareDetailTableViewCell.className, for: indexPath) as! THShareDetailTableViewCell
shareDetailCell.selectionStyle = UITableViewCellSelectionStyle.none
shareDetailCell.likeButton.tag = indexPath.row
//to set image dynamic height
shareDetailCell.selectionStyle.socialPostImage.sd_setImage(with: URL(string: socialInteraction[indexpath.row].largeImageUrl), placeholderImage: nil, options: .retryFailed) { (image, error, imageCacheType, imageUrl) in
if image != nil {
let imgHeight = (image?.size.height)!
shareDetailCell.heightConstraintSocialImage.constant = (imgHeight * (self.socialPostImage.frame.size.width/imgHeight))
}else {
print("image not found")
}
}
return shareDetailCell
}
From your code work I found two things ,
Never return UITableViewAutomaticDimension from estimatedHeightForRowAt because estimated height is never be Automatic otherwise x-code does not understand what height it should need to return. Sometimes it works but not considered as a good practice.
You fetching the Images in the cellForRowAt method that means upto you fetch the image the height of cell is already set. So your cell images that height only.UITableViewAutomaticDimension works when system knows the height of that cell at the heightForRowAt method not after that.
Suggestion for your problem.
Once you fetch the data and then reload your tableView so that cell height is adjusted according to the image height. You can do this in paging also.

Resources