How do I reset tableview's contents height after hidden UIView - ios

Hi I'm trying to resize tableview's height after hidden indicatorView.
self.tableView.reloadData()
self.refresher.endRefreshing()
self.indicator.stopAnimating()
self.indicatorView.isHidden = true
When I set indicatorView as hidden but TableView's height still has space of indicatorView's height.

Somehow, You need to implement tableView(_:heightForRowAt:). For example:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// pseudo:
/*
if a condition related to hide the indicator (for example response from calling an api to get some data) is true, retrun -for example 100-, else (the response has not been called yet) retrun another value.
*/
}
You can also check the indexPath.row for chaning a specific row height:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// check if it is the second row:
if indexPath.row == 1 {
}
}
So, after calling self.tableView.reloadData() it should be called and assign the new height for the row.
Hope this helped.

Embed tableView and indicatorView in a stackview.
Like in this answer, but with Vertical Axis.

Related

How to narrow UITableView cell height if there is dynamic structure in Swift?

I have a tableView and cells. The Cells are loaded from a xib and they have a label with automatic height. I need to narrow one cell if the user taps on it.
I have tried hiding - doesn't work
I have tried removeFromSuperView()- doesn't work
Is there any alternative?
When setting up your tableViewCell store the height anchor you want to update
var yourLabelHeightAnchor: NSLayoutConstraint?
private func setupLayout() {
yourLabelHeightAnchor = yourLabel.heightAnchor.constraint(equalToConstant: 50)
// Deactivate your height anchor as you want first the content to determine the height
yourLabelHeightAnchor?.isActive = false
}
When the user clicks on a cell, notify the tableView that the cell is going to change, and activate the height anchor of your cell.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourTableViewCellIdentifier") as? YourCell
self.tableView.beginUpdates()
cell?.yourLabelHeightAnchor?.isActive = true
self.tableView.endUpdates()
}
Did you try to do something like this:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var result: CGFloat
if (indexPath.row==0) {
result = 50 }
else {result = 130}
return result
}
This is just an example where height is changed for the first row. I tested on my application and it gave result like this.

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.

swift messaging app, uitableview not responding correctly to keyboard?

A similar question is this, except I don't have estimated row heights, I store the actual heights into a dictionary, and either use those, or use UITableViewAutomaticDimension.
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeightDict[indexPath.row] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = cellHeightDict[indexPath.row] {
return height
} else {
return UITableViewAutomaticDimension
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = cellHeightDict[indexPath.row] {
return height
} else {
return UITableViewAutomaticDimension
}
}
So I'm making a messaging app in Swift 4 right now. When the user shows the keyboard, I want the messages to shift up with the keyboard. So in order to do this, I have a variable keyboardHeight which correctly gets the height of the keyboard:
let keyboardHeight: CGFloat = ((userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height)!
I change the height of the table view by keyboardHeight:
self.messageTableViewHeight.constant -= keyboardHeight
So the users can see all of the messages. And to shift up the messages with the keyboard animation, I changed the contentOffset of the table view:
self.messageTableView.contentOffset.y += keyboardHeight
All of this is in a UIView.animationWithDuration, and I call self.view.layoutIfNeeded() after, so the shifting and everything works fine. But, when I send a message without scrolling to the bottom, the messageTableView content jumps down??? And it seems to shift down by keyboardHeight, at least when I eye it. I am using messageTableView.reloadData(). Here are some images.
Before message sent
It jumps up in between the "Hi" and "Testing" messages.
After message sent
As soon as you reload the data of the tableview messageTableView.reloadData(). Every row is reloaded but it is not able to calculate the actual content size somehow. You can try reloading the data in the main queue.
DispatchQueue.main.async {
messageTableView.reloadData()
}
If it still doesn't works, you can add one more thing to the above code. Suppose you have an array of messages in your class. var messages then you can use this code to display data correctly in the tableview.
DispatchQueue.main.async {
messageTableView.reloadData()
if messages.count > 0 {
let indexPath = IndexPath(row: messages.count - 1, section: 0)
self.messageTableView.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
}
Hope this helps. Happy coding.

Swift UIView Border adjusts after UITableView scrolling

I have a problem with my UITableView sections (and their height, I guess).
Within a section header, I have a view (named cornerRadiusView) within which there are few labels. These labels have dynamic content (fetched from a REST service). So whenever a UILabel height is increased, I am increasing the height of the cornerRadiusView to properly accommodate the content.
The problem is, all this works as expected only when I scroll my tableView. Till then, the heights are improper.
Here I am posting GIF to show what's going on.
I can give more details and code as needed. Could someone please look at where there is a problem?
You can use below functions
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
And reload table view in below method
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableview.reloadData()
}
And if you are maintaining dynamic height then manage those height in cell
override func layoutSubviews()
{
}

Wrap Text in UITableView Custom Cell When It Reaches End of Screen (Swift)

I have a table that loads data from a database but the problem is if the text being loaded is too long, it goes off the screen. I'm trying to find a way for the text to go onto the next line and have the cell resize automatically to fit this change. Does anyone know how this is done? The cell has three labels but one of them is allowed to be multi-lined.
EDIT:
I got it to work using auto constraints but how can I resize the table cell so that the actual items fit inside the cell and do not go over the cell boundary?
Set label number of "Lines" to ZERO. And set "Line Breaks" to "Word Wrap"
Adding these two methods along with above code fixed the problem with custom font
tamilRow.textLabel?.numberOfLines=0
tamilRow.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
func tableView(tableView: UITableView, heightForRowAtIndexPath
indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
swift 5
let unselectedCellHeight: CGFloat = 130.0
func tableView(_: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if selectedCellIndexPath == indexPath {
//return selectedCellHeight
return UITableView.automaticDimension
}
return unselectedCellHeight
}

Resources