how to vary the tableview height based on content - ios

I tried to vary the height of tableview based on content and I did that but the thing is below the tableView there will be a label. Whenever the table height increased or decreased, that label should be below. I tried it but that label is being at whatever the table height is given initially.If any oner helps me to do this would be great.

First remove below code if you have used in your code. We don't need it.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
Next, while setting up your UITableViewCell, make sure one of height constraint is not set. Here is an example for title and description.
/* Setup title label */
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 0),
titleLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 10),
titleLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -10),
titleLabel.heightAnchor.constraint(equalToConstant: 40)
])
/* Setup description label */
NSLayoutConstraint.activate([
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 0),
descriptionLabel.leftAnchor.constraint(equalTo: titleLabel.leftAnchor, constant: 0),
descriptionLabel.rightAnchor.constraint(equalTo: titleLabel.rightAnchor, constant: 0),
descriptionLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0)
])
Don’t forget to set numberOfLines to zero for descriptionLabel.
Boom, you are done.

First of all, you have to take a scrollview and add your tableview and a label into the contentView. Set the height of the contentView as a dynamic and set the IBOutlet to the tableView height constraint as below.
#IBOutlet var constTableHeight : NSLayoutConstraint!
after reloading the table set constTableHeight's value
let heightTBL : CGFloat = (tblView?.contentSize.height)!
constTableHeight?.constant = heightTBL

In your viewDidLoad method, add
self.tableView.estimatedRowHeight = 44 //default table view cell height
And then add this in your class,
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}

If you want that table view cell's height increase based on the label in it than you have to implement a couple of methods like this (Swift 4)
1- This method tells the cell that increases your height automatically
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
2- Implement estimated row height whatever you want let's say 140
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 140
}
3- When you place the label in the cell make sure the number of lines to "0". Add the top, leading, bottom and trailing margins to it.

override func viewDidLoad()
{
Tablename.estimatedRowHeight = 100
Tablename.rowHeight = UITableViewAutomaticDimension
}
and in your Tableview cell dont forget to give top,leading ,trailing and bottom margin to last ui component of your cell to make it dynamic in size.

Related

UItableView dynamic height depending on content

How can I make the tableview cell height dynamic,
I have 1 label and 1 image in the cell, My image height is constant of 70, label height depends on the api text, if my label text I large then the image view height so table view cell should adapt label height else image View.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
below image just picking height of image
Making a UITableViewCells height dynamic based on its content is obtained by doing the following:
Make sure the content of your UITableViewCell is constrained such the dynamic content is pinned to both the top and bottom of the cell.
A contrived example cell:
class Cell: UITableViewCell {
let label = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// Allows your text to expand multiple lines
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(label)
// Constrains a UILabel to the edges of the UITableViewCells content view
label.topAnchor.constraint(equalTo: commentBox.topAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: commentBox.bottomAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: commentBox.leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: commentBox.trailingAnchor).isActive = true
}
}
As you have above, return UITableViewAutomaticDimension from func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
To help your UITableView compute the dynamic height, its recommended to return an estimated size you think your cell is going to be.
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat

Remove the unwanted space between button and line swift xcode

I am new to iPhone application development.
I am designing the app like this. in this design, there are two buttons below to delete button and below to those two button, there is the line. that you are seeing in this picture.
What i want is, i want to add the line below to the delete button when those two buttons are hidden by some condition. if those two buttons visible means, that line should come below to those two button. Not below to the delete button.
I have added the following code in cellForRowAt function of TableView. it is not working.
cell.line.frame = CGRect(x: 0, y:cell.btnDelete.frame.maxY, width: cell.line.frame.width , height: 1 )
Any body can help me to solve this issue.
I have added following code to.
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
and
dataTable.rowHeight = UITableViewAutomaticDimension
dataTable.estimatedRowHeight = 100
You have to achieve this using some tricky way.Use Stack View Add Show,Hide buttons to one UIView.add all other components to another UIView.Add UIStackView to your custom cell and add constraints like this.
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.topAnchor.constraint(equalTo: topAnchor),
stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
])
set stackView distribution to .Fill.
when you want to show/hide buttons, you can add/remove the arranged subView from tableview cell stackView.If you are show/hide buttons in cellForItemAt make sure remove all arranged subviews before add.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.stackView.removeArrangedSubview(cell.viewOne)
cell.stackView.removeArrangedSubview(cell.viewTwo)
if isShowBuutons {
cell.stackView.addArrangedSubview(cell.viewOne) //View with All other elements
cell.stackView.addArrangedSubview(cell.viewTwo) //View with buttons
}else{
cell.stackView.addArrangedSubview(cell.viewOne) //View with All other elements
}
}

UITableViewCell frame margins in Swift

I want to enter cell coordinates. When I apply the following code, the cell disappears from the application. How do I adjust the frame margin?
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
cell.layoutMargins = UIEdgeInsets(top: 50, left: 25, bottom: 0, right: 25)
cell.preservesSuperviewLayoutMargins = false
}
For cells, try this:
override func tableView(tableView: UITableView,
willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath)
{
cell.separatorInset = UIEdgeInsetsZero
cell.preservesSuperviewLayoutMargins = false
cell.layoutMargins = UIEdgeInsetsZero
}
But based on the edited information, it seems that you have margin in the container view of the table view. Either this comes from your constraints between table view and view (check them one by one) or you have layout margins in the view, in which case try;
override func viewDidLoad() {
// ...
self.view.layoutMargins = UIEdgeInsetsZero
}
You need to set the row height to be the sum of the desired content height plus the desired margin height.
If all rows are the same height, set the rowHeight property of the table view to a number that is big enough for your needed content height plus the desired top and bottom margin.
If each row is a different height, then implement the heightForRowAt delegate method and return the needed total height (including margin).

Set constraint for the last row of Tableview

I am using a static table in UITableViewController, I want the height of the last row of the table is bigger than others and the bottom of it has a zero constraint to safeArea.buttom .
First I added the last row of table view as an outlet
#IBOutlet weak var lastRowOfCell: UITableViewCell!
Then I added these line to viewDidLayoutSubviews()
but none of them works:
lastRowOfCell.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
lastRowOfCell.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
Use this method
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == ('lastRow') {
return heightNeeded
}
}
And replace 'last row' with the row you need
and heightNeeded with the pixels or height constraints required

How to size a UIStackView depending on its content?

I would like to have a similar behavior than the <Table> HTML tag, in the sense where the frame is sized according to its content.
In my very context, I use an UIStackView as the content view of a UITableViewCell. As items in the cell are various information, the resulting height of the cell should be variable.
My strategy is to programmatically build a cell as a UIStackView with a .Vertical axis, as in the code snippet as follows:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let sv = UIStackView(frame: tableview.frame)
sv.axis = .Vertical
cell.addSubview(sv)
for i in information {
let l = UILabel()
l.text = i
sv.addSubViewAndArrange(l)
}
return cell
}
Unfortunately, the cell size does not adjust to the content, and as a result I have to set the cell height myself, as follows:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return cellHeight // a constant
}
How could I fix that?
UIStackView is designed to grow its size according to the content. In order for that to work, you need to set up the constraints between the UIStackView and the UITableViewCell. For example, if UIStackView is first-item and UITableViewCell is it's super-view, then this is how the constraints look like in interface builder:
If you like setting up constraints in code, that should work too.
For example, assuming stackView and cellView are the names, then above constraints' Swift-code would look like:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: cellView.topAnchor, constant: 0).isActive = true
stackView.bottomAnchor.constraint(equalTo: cellView.bottomAnchor, constant: 0).isActive = true
stackView.leadingAnchor.constraint(equalTo: cellView.leadingAnchor, constant: 0).isActive = true
stackView.trailingAnchor.constraint(equalTo: cellView.trailingAnchor, constant: 0).isActive = true
To demonstrate that this will work, I have this for the cellForRowAt function. Basically, it puts a number of UILabel inside the UIStackView and the label count is depending on the row number.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableviewCell", for: indexPath) as! TableviewCell
for i in 1...indexPath.row + 1 {
let label = UILabel()
label.text = "Row \(indexPath.row), Label \(i)"
cell.stackView.addArrangedSubview(label)
}
return cell
}
Here is the final result:
https://github.com/yzhong52/AutosizeStackview
I built this example I hope it helps, I've created a tableView which use a cell that contains a stackView and the views loaded in the stackView are gotten from a nib file
https://github.com/Joule87/stackView-within-TableViewCell

Resources