viewDidLayoutSubviews for Custom UITableViewCell - swift

I want to animate a subview of a custom TableViewCell. To perform this animation, the cell needs the width of this subview, which is laid out by an auto-layout-constraint.
However, when I use the animation-function in the cellForRowAtIndex function (mycell.animate()), the width is 0, because the subviews are not laid out yet and the animation will not work.
In a regular view, I would use viewDidLayoutSubviews(), because then the view is laid out, I can get the width and perform the animation. However, what's the equivalent function for a custom UITableViewCell?
I tried the willDisplay delegate function of the TableView, but when I print out the width of the cells subview, it still says 0...

The correct place is inside layoutSubviews:
class MyCell : UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
// do your thing
}
}

It will work if you animate your view inside draw function in tableViewCell
override func draw(_ rect: CGRect) {
super.draw(rect)
//Your code here
}

Related

UITableViewCell width not expanding on rotation to landscape

I'm having trouble resizing the content of a UITableViewCell when the device rotates to landscape (and therefore view width increases).
For context, this is part of a universal split view app and is only occurring on iPhone 8 in the simulator (which doesn't support split view). Later devices which do support the split view have no issue.
In my UITableViewController, translatesAutoresizingMaskIntoConstraints = false, and 'Follow Readable Width' is unchecked in IB. I have also added:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
self.tableView.reloadData()
}
The tableView also has a custom UITableViewCell to which I've added:
override func layoutSubviews() {
uniqueIDLeading.constant = (self.contentView.frame.width * 0.4)
layoutIfNeeded()
}
No errors or warnings in the console. Any other ideas?
Eventually fixed with the following in custom UITableViewCell class.
override func layoutSubviews() {
super.layoutSubviews()
autoresizingMask = .flexibleWidth
layoutIfNeeded()
}
I have the similar issue today, but I am not using a custom cell. I solved it with the following code.
Swift:
self.tableView.autoresizingMask = .flexibleWidth
Objective-C:
self.tableView.autoresizingMask=UIViewAutoresizingFlexibleWidth;

swift CollectionView inside TableView Cell

Why am I scroll first cell then third cell also scrolling?
Screen Record
It is because of cell reuse, so basically the cell that you scroll goes off screen and will be reused when another cell down is needed.
In your UITableViewCell subclass you can implement prepareForReuse method, this is called when cell is ready to be reused and you can set contentOffset to 0 there, something like:
override func prepareForReuse() {
super.prepareForReuse()
scrollView.contentOffset = CGPoint(x: 0, y: 0)
}

Swift, Auto Resize Custom Table View Cells

In my app, I have a table view with an image, label and text view in each cell. I would like to be able to auto-resize the cells depending on the amount of content in the text view. (The text view is the lower most text.)
So far, I have added the correct constraints; leading, trailing, top and bottom to the text view and have disabled scrolling and editing.
In my tableViewController.swift file, I have written this code:
override func viewWillAppear(_ animated: Bool) {
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
However, this is not working as when I add more text to the text view, it just cuts off.
Maybe this has something to do with the card like look, I have got a UIView in each cell acting as a card.
I honestly don't know what I am doing wrong
A picture is below of what my app looks like and if anyone could help that would be greatly appreciated
Check if your constraints are like this(based on your image) :
imageView : set to Top and Leading of your container, with fix height and width values.
label : you can set it to top and horizontal space of your image, with fix height and width as well.
textView : leading to image, top space to label, trailing and bottom to container.
And keep using
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
in your viewWillAppear()
Update for swift 4.2
Use:
UITableView.automaticDimension
Instead of:
UITableViewAutomaticDimension
Make sure that the content mode is set to Scale To Fill of your UITextView
Make sure that there are no height constraints for the UITextView and the card UIView
Try to add the estimated height into viewDidLoad:
override func viewDidLoad() {
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
Maybe the AutoHeight is not working because of the UIView above the UITextView. Try to call the sizeToFit and layoutIfNeeded methods for the UIView in the cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier", for: indexPath) as! CustomTableViewCell
cell.vwCard.sizeToFit()
cell.vwCard.layoutIfNeeded()
return cell
}
You can also try the sizeToFit and layoutIfNeeded as well for the UITextView.
Hope this works........
Set bottom of your textView with bottom of that white UIView and make sure that white UIView has left,right,top and bottom constraints :)
Same type of example is explained here programmatically....

UICollectionView inside a tableviewcell: scrollToIndex not working

I have created a simple UICollectionView inside of a tableviews, UITableviewCell. The collection view is set to scroll horizontally. I am trying to scroll to a certain element within the collection view using scrollToIndex at:, I have placed the scroll request in the tableviewcell's layoutSubviews method. When the collection view is displayed, no scrolling takes place.
Here is the tableviewcell's layoutSubviews code:
override func layoutSubviews() {
super.layoutSubviews()
let indexPath = IndexPath(item: 1, section: 0)
self.collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.left , animated: false)
}
It's quite simple, so really not sure why this is not working?
Many thanks for any help!

Where to get frame size of custom UIView in its subclass

When does the correct frame size of the UIView is calculated when I add my custom UIView by using storyboard?
I can't get correct frame size in UIView's init(frame: CGRect) or init(coder aDecoder: NSCoder) or awakeFromNib(). I get the correct size in override func layoutSubviews() but this time the view is not added to the view controller's view.
Edit:
I want to do this in the UIView subclass because I add a CAGradientLayer layer (which has same size with my view) to my custom UIView. There must be a better way than setting up the view in UIViewControllers viewDidLayoutSubviews method.
There are two vertical constraints (trailing and leading space to superview) that adjust the width of my custom view. But the width is 600 in the mentioned methods, not the screen width.
func viewWillAppear(_ animated: Bool)
This is called on the viewController after the view hierarchy is in place and the geometry is set up.
It is usually the best place to arrange geometry-dependent viewController code, and is called just before transition animations are run.
It is followed by a call to viewDidAppear which is called after transition animations have completed.
update
as you want to set this directly in a custom view (rather than in the viewController) the appropriate UIView function to override is layoutSubviews. Be sure to call super.layoutSubviews() in the override.
override func layoutSubviews() {
super.layoutSubviews()
//self.frame will be correct here
}
This will be called after the viewController's viewWillAppear and before viewDidAppear
update 2: collectionView cells
Collection view cells get their frame data from the collectionview's layout. When a cell needs to know it's geometry, you can override applyLayoutAttributes
func applyLayoutAttributes(_ layoutAttributes: UICollectionViewLayoutAttributes!)
One of the default layoutAttributes is the frame property. See also my comment below on how to extract the frame directly from collectionView.layout.
Since viewDidLayoutSubviews() is getting called multiple times, I'd recommend using the viewDidAppear() delegate.
viewDidLoad() is called before any frame was set.
viewDidLayoutSubviews() is called during frame sizing and will be called multiple times with different frame sizes (usually frameZero before a frame is calculated).
viewDidAppear() All frames are set.
You should have an IBOutlet to your UIView and in the viewDidLayoutSubviews() method, get the size by yourViewOutlet.frame.size.