UITableViewCell height animation together with content - ios

I've searched on Stack Overflow and other sources but despite similar problem title I can't find a solution.
What I want to do is to animate UITableViewCell height together with content. Here is an example:
There is a blue panel in the middle of the cell. I'd like this panel's height to be animated together with cell itself.
I've tried 2 ways:
First: Changing row height and setting constraints as on the picture above:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.beginUpdates()
tableView.endUpdates()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let selectedIndexPath = tableView.indexPathForSelectedRow
return indexPath == selectedIndexPath ? 120.0 : 70.0
}
Second: Setting row's height to UITableViewAutomaticDimension, adding height constraint to the blue area and changing this constraint if user taps on cell.
Link to the repo
Both ways change blue region heigh instantly and then animate cell height. I need blue region to animate smoothly together with cell heigh, so white spacing between cells is unchanged.

Related

How to use dynamic height of UITableViewCell in auto-layout and move other views to up when bottom view is hidden?

I have a UITableViewCell in xib and its outlets in corresponding UITableViewCell subclass. I am returning height of cell from
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat {
return 400
}
I need to hide some views based on the data available in each row of the table and bottom view should shifted to top of the cell. When I am hiding view from cell then there is empty space left in place of hidden view & bottom views are not shifting to top part of the cell.
Here is How I am hiding cell view.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
.....
cell.opetion4.isHidden = true
cell.opetion3.isHidden = true
}
This is my cell.
After hide 2 middle labels it is looking as follows.
But I want to remove this empty space and want to shift bottom label to top as follows.
At first, make the height of UITableViewCell to UITableView.automaticDimension
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Embed all of your questionLabels in a UIStackView (vertical) excluding bottomLabel. Set AutoLayoutConstraint between UIStackView and bottomLabel.
Set the numberOfLines property of UILabels to 0(zero).
Set the Distribution of the UIStackView as Fill
Then, in your tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell method hide the labels. And it will automatically handle the spaces between UILabels
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cell.questionLabel1.text = labelOneText[indexPath.row]
cell.questionLabel2.text = labelTwoText[indexPath.row]
cell.questionLabel3.text = labelThreeText[indexPath.row]
if labelOneText[indexPath.row] == "" {
cell.questionLabel1.isHidden = true
}
if labelTwoText[indexPath.row] == "" {
cell.questionLabel2.isHidden = true
}
if labelThreeText[indexPath.row] == "" {
cell.questionLabel3.isHidden = true
}
return cell
}
Final Output:
First I suggest you to set UITableViewCell Height to automatic dimensions . Attach all the children to one another and last child to uiview of xib . Now hiding view does not adjust size of cell so you need to play with height constraint of uiview you are hiding .
Make height constraint as strong in IBOutlet else it will crash since cells are re-using and constraint after setting once will become nil . You need to make sure that height constraint are change according to display cell requirement , thats mean for each cell maintain some datasource that decide to show or hide the view every time when cellforrowatIndexpath method called.
Hope this helps
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat {
return UITableView.automaticDimension
}
now in cell, put all your views and there siblings which you want to hide/show in UIstackview (horizontal). now if you hide one view, it will be hidden and its apace will be also hidden to no white space will be showing, and no need to handle extra constraints. it will all handled by stackview.

Label size is not changing

I am trying to make a Chat app. I have a tableView and prototype cell in which I have UILabel. But I am stuck with label size(HxW). Please take a look in the image below:
The first label is taking extra width and height is less. I want that label should take width according to its content but till the button.
These are the contraints:
For the height I am using:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}

How to expand UITableViewCell height in dynamically?

I have a UITableView. In my tableview l I want to dynamically add another view into my cell and expand the cell height. I have seen some examples but those are with UILabels. UILabels can changes the height according to the text height. But how can I manually add another view and expand those cells?
Please help me
Thanks
If you use the manually calculate the cell height,its easy,after you add another view,you calculate the height,then call reloadData or reloadRowsAtIndexPaths,and return the height in tableview:heightForRowAtIndexPath function.
If you use the auto calculate the cell height.you should let system know how to calculate,you should set the autolayout clearly and completely.You should add the another view`s left、right、top、bottom constraint and the system will auto canculate the height.So the cells will Be expanded.
You can set cell height by override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
Implement these two UITableViewDelegate methods:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
// return estimatedHeight
}
View in your dynamic cell needs to have top, bottom, trailing, leading and height constraints. Setting view height constraint constant will set cell height according to view height.
You can have view height constraint property in your dynamic cell:
#IBOutlet weak var customViewHeightConstraint: NSLayoutConstraint!
Constraint constant value can be changed in cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellId", for: indexPath) as! Cell
switch indexPath.row {
case 0:
cell.customViewHeightConstraint.constant = 100
case 1:
cell.customViewHeightConstraint.constant = 200
case 2:
cell.customViewHeightConstraint.constant = 300
case 3:
cell.customViewHeightConstraint.constant = 400
default:
cell.customViewHeightConstraint.constant = 100
}
return cell
}

Animating UIView with Autolayout animates UITableView's checkmark

I have strange behaviour. My whole view controller looks like this (vertical order):
UILabel,
UITableView,
UIView (that will slide in&out when needed). [see p.s.]
I added constraint between UIView and bottom layout guide and I'm animating it with this method:
func toggleContinueButton(_ toggleOn: Bool) {
if toggleOn {
self.buttonViewConstraint.constant = 0
} else {
self.buttonViewConstraint.constant = -80
}
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
For some strange reason this screws checkmark, which is now "flying" from outside of left margin of screen and right into correct and expected position, on the right side of selected cell. Belowe I have simple code for selecting/deselecting:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)!.accessoryType = .checkmark
self.updateContinueButtonState()
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)!.accessoryType = .none
self.updateContinueButtonState()
}
Has anybody ever met such weirdness?
p.s. tried two versions: first, where sliding UIView is hovering in&out on top of tableView, and second where sliding in UIView is shrinking tableView's height. None worked.
Its hard to say, but you might try calling layoutIfNeeded first, then changing the constraint, then calling it again inside the animation block. That gives other layout changes time to update first.

UITableView cell size of screen

I have a table view controller with a navigation controller, and when there is no data for the table view, I want to display a single table cell with instructions on how to add new data. I can display the table cell, but I do not understand how I can get the height of the cell to span the visible height (table height - navigation item height). My goal is to have the label inside of my table cell be vertically centered in the device. I've tried using self.tableView.frame.height, but that gives me the scrollable height, which is larger than the visible area.
Edit: I failed to mention I'm doing this from tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat.
I have found a Good Enough™ answer to my own question:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
tableView.isScrollEnabled = false
return tableView.frame.height - (self.navigationController?.navigationBar.frame.height)!
}

Resources