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
}
Related
I have a tableview , it has two rows.
Tableview's height is 700. The first row height is 150 and the second row height is 100 but I'd like the second cell to cover the rest of the space in tableview.
I know I can use the below for tableview height. But I'd like to
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
Simply, just replace this method
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tblHeight = infoTable.bounds.size.height
return indexPath.row == 0 ? 150 : tblHeight - 150
}
just change infoTable with your table name.
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.
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.
I use dynamic height cells for my UITableView with this code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "QuestionsCell", for: indexPath) as! QuestionsCell
cell.label1.text = ""
cell.label2.text = ""
cell.label1.text = some text from array
cell.label2.text = some text from array
cell.label1.lineBreakMode = .byWordWrapping
cell.label1.numberOfLines = 0
cell.label1.sizeToFit()
return cell
}
Then I've pinned all constraints in Storyboard for each element (top, bottom, leading and trailing). On iPhone everything works fine, but on iPad when I scroll the UITableView this is happening (dynamic label height):
sizeToFit() only makes cell1 as big as it needs to be for the text.
You also need to use automatic height sizing for the table view cells.
In viewDidLoad,
self.tableView.rowHeight = UITableViewAutomaticDimension
You will also want to make sure you have a vertical constraint from your bold label to the "12 days ago" label, to ensure there is always vertical space between them, so they don't overlap.
you need to implement this delegate method:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
if this does not work then check if there is vertical spacing constraints between top textView and bottom textView.
I got two cells in my UITableView. One is a custom UITableViewCell and the other is a cell with a UITextView inside and called the type TextViewCell.
Because they are static I the cells are loaded in viewDidLoad method from a xib:
textCell = Bundle.main.loadNibNamed(String(describing: TextViewCell.self),
owner: self, options: nil)?.first! as! TextViewCell
ratingCell = Bundle.main.loadNibNamed(String(describing: RatingCell.self),
owner: self, options: nil)?.first! as! RatingCell
Now I try to change the height with the the heightForRowAt delegate:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1 {
return textCell.textView.contentSize.height
}
return ratingCell.ratingView.frame.height
}
I disabled scrolling on the UITextView but the cell is not resizing properly. In fact the cells gets smaller.
The constraints of the TextViewCell look like this:
Any suggestions?
I think you need to use self-sizing UITableViewCell. Replace your current implementation of heightForRowAt with the following:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Now height of cells in your UITableView object will be calculated automatically based on constraints.
Also, add some estimated value for row height:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100.0 // You can set any other value, it's up to you
}
Now you will see that the UITextView view fills the whole UITableViewCell cell.
You should get the height of UITextView in heightForRowAt and return this height as cell height. See example below
let lblDescLong = UITextView()
lblDescLong.textAlignment = .left
lblDescLong.text = “your text for text view”
lblDescLong.font = YourFont(size: 12)
let newSize = lblDescLong.sizeThatFits(CGSize(width: widthForTextView, height: CGFloat.greatestFiniteMagnitude))
return newSize.height