dynamic cell height in ios using constrain programatically in swift - ios

I am working on a project in swift which needs the cell size to be dynamic according to the label content, so i searched for dynamic cell height, i found some solution but all of it included use of storyboard for assigning constrain. Is it possible to do it without storyboard. Is it possible to do it programatically? I mean applying self sizing without storyboard
my code is:
class a: UITableViewDelegate, UITableViewDataSource {
tableView = UITableView(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height), style: UITableViewStyle.Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
self.view.addSubview(tableView)
}
Hope the question is clear.
Thanks in advance.
Edit: None of the answers below is helpful

Try this method.
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
return // get cell text label high and return +10 or +20 height. what is label height..
}

iOS 7 compatible: https://github.com/smileyborg/TableViewCellWithAutoLayout
iOS 8 only: https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8

You can try this method.
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
self.dashBoardTableView.rowHeight = UITableViewAutomaticDimension
if (CellIdentifier == "dashBoardTableCellID")
{
dashBoardTableView.rowHeight = 96
}
else
{
dashBoardTableView.rowHeight = 60
}
return self.dashBoardTableView.rowHeight
}

Yes you can, you can create your constraints in code.
I suggest you look at the class NSLayoutConstraint:
NSLayoutConstraint Apple documentation

iOS 8 suppoorts self sized tableview cells. To enable it first create your cell with correct constraints. End use code below
tableView.estimatedRowHeight = 50
tableView.cellHeight = UITableViewCellAutomaticDimension
estimatedRowHeight is just hint for tableview. When tableview reuses cells it looks its content and adjust sizes acoording to it.

Related

spacing between UITableViewCells swift3

I am creating a IOS app in swift and want to add spacing between cells like this
I would like to give space of each table view cell same like my attach image.
How I can do that? and Right now all cells are coming without any space.
swift3
you can try this in your class of tableView cell:
class cell: UITableViewCell{
override var frame: CGRect {
get {
return super.frame
}
set (newFrame) {
var frame = newFrame
frame.origin.y += 4
frame.size.height -= 2 * 5
super.frame = frame
}
}
}
From Storyboard, your view hierarchy should be like this. View CellContent (as highlighted) will contain all the components.
Give margin to View CellContent of 10px from top, bottom, leading & trailing from its superview.
Now, select the tblCell and change the background color.
Now run your project, make sure delegate and datasource are properly binded.
OUTPUT
NOTE: I just added 1 UILabel in View CellContent for dummy purpose.
Update: UIEdgeInsetsInsetRect method is replaced now you can do it like this
contentView.frame = contentView.frame.inset(by: margins)
Swift 4 answer:
in your custom cell class add this function
override func layoutSubviews() {
super.layoutSubviews()
//set the values for top,left,bottom,right margins
let margins = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
contentView.frame = UIEdgeInsetsInsetRect(contentView.frame, margins)
}
You can change values as per your need
***** Note *****
calling super function
super.layoutSubviews()
is very important otherwise you will get into strange issues
If you are using UITableViewCell to achieve this kind of layout, there is no provision to provide spacing between UITableViewCells.
Here are the options you can choose:
Create a custom UIView within UITableViewCell with clear background, so that it appears like the spacing between cells.
You need to set the background as clear of: cell, content view.
You can use UICollectionView instead of UITableView. It is much more flexible and you can design it the way you want.
Let me know if you want any more details regarding this.
One simple way is collection view instead of table view and give cell spacing to collection view and use
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let widthSize = collectionView.frame.size.width / 1
return CGSize(width: widthSize-2, height: widthSize+20)
}
And if you want tableview only then add background view as container view and set background color white and cell background color clear color set backround view of cell leading, trilling, bottom to 10
backgroundView.layer.cornerRadius = 2.0
backgroundView.layer.masksToBounds = false
backgroundView.layer.shadowColor = UIColor.black.withAlphaComponent(0.2).cgColor
Please try it. It is working fine for me.
You can use section instead of row.
You return array count in numberOfSectionsInTableView method and set 1 in numberOfRowsInSection delegate method
Use [array objectAtIndex:indexPath.section] in cellForRowAtIndexPath method.
Set the heightForHeaderInSection as 40 or according to your requirement.
Thanks,Hope it will helps to you
- Statically Set UITableViewCell Spacing - Swift 4 - Not Fully Tested.
Set your tableView Row height to whatever value you prefer.
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = <Your preferred cell size>
tableView.rowHeight = UITableViewAutomaticDimension
// make sure to set your TableView delegates
tableView.dataSource = self
tableView.delegate = self
}
extension YourClass : UITexFieldDelegate, UITextFieldDataSource {
//Now set your cells.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! UITableViewCell
//to help see the spacing.
cell.backgroundColor = .red
cell.textLabel?.text = "Cell"
return cell
}
//display 3 cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
//now lets insert a headerView to create the spacing we want. (This will also work for viewForHeaderInSection)
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
//you can create your own custom view here
let view = UIView()
view.frame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: 44) //size of a standard tableViewCell
//this will hide the headerView and match the tableView's background color.
view.backgroundColor = UIColor.clear
return view
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44
}
}

Self-Sizing Table View Cell in Xcode 9

I have a UITableViewController where the cell's self sized correctly using Xcode 8 and Swift 3. Now that I'm using Xcode 9 and Swift 4, they aren't expanding and are just using the default height of 44.
(I have about a sentence or two in each UITableViewCell)
I was using this before:
// MARK: - Table view delegate
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
... but was able to comment it out because per Updating Your App for iOS 11 said that the default would be self-sizing now:
I've tried playing around with changing the deployment target to iOS 11, playing around in Storyboard (but I'm using a Table View Cell style Basic so there is not much AutoLayout to be done), and I can't figure out what is going on.
I have the UILabel title set to 0 Lines, and have Line Break Word Wrap, but still not getting anywhere close to getting the cell to expand based on the text content inside of it in Xcode 9. Any ideas?
Thanks!
Edit:
Here's the options (that I don't have) for pinning since it is a Basic cell:
I had the same problem and solved it with to lines of code:
class MyTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = UITableViewAutomaticDimension
tableView.rowHeight = UITableViewAutomaticDimension
}
Maybe it is a bug in Xcode.
Update
New in Xcode 9 beta 3:
Interface Builder now supports setting the estimatedRowHeight of UITableView. This allows self-sizing table cells by setting the estimated height to a value other than zero, and is on by default. (17995201)
I had the same broken table view issue. Fix was just one click.
Go to your xib or storyboard scenes with table views, go to the size inspector, and you'll see the table view heights (even on dynamic table views) as 44, and sections will be 22. Just click "automatic" and boom, it will present as expected.
Note that I also specify the following in viewDidLoad of the UITableViewController subclass (layoutSubviews solves issues with the first load of a tableViewController not positioning correctly in relation to a non-translucent navBar).
self.tableView.estimatedRowHeight = 180;
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.tableView layoutSubviews];
In addition to
tableView.estimatedRowHeight = UITableViewAutomaticDimension
tableView.rowHeight = UITableViewAutomaticDimension
you should set a height constraint for the contentView of the tabeleViewCell.
class CustomTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let height: CGFloat = 200
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
I got the same issue and I read about it in many documentation, satisfying answer was something like this, You have to check both options in order to get proper height, because estimated height is needed for initial UI setup like scrollview bars and other such stuff.
Providing a nonnegative estimate of the height of rows can improve the performance of loading the table view. If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.
When you create a self-sizing table view cell, you need to set this property and use constraints to define the cell’s size.
The default value is 0, which means there is no estimate. (Apple Documentation)>
see this image for storyboard
Also note that there is a bug in xCode 9, when you try to apply Lazy loading in automatic height calculation, it will scroll unexpectedly, so I'll recommend you to use programmatic way in this regard.
self.postTableView.estimatedRowHeight = 200;
self.postTableView.rowHeight = UITableViewAutomaticDimension;
something Like this. Thanks!
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tblview: UITableView!
var selectindex = -1
var arrnumber = ["1","2","3","4","5"]
var image = ["index.jpg","rose-blue-flower-rose-blooms-67636.jpeg","index.jpg","rose-blue-flower-rose-blooms-67636.jpeg","index.jpg"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrnumber.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tblview.dequeueReusableCell(withIdentifier: "cell", for: indexPath)as! ExpandableTableViewCell
cell.lblnumber.text = arrnumber[indexPath.row]
cell.img.image = UIImage(named: image[indexPath.row] as! String)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (selectindex == indexPath.row)
{
return 250
}
else{
return 60
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if(selectindex == indexPath.row)
{
selectindex = -1
}else{
selectindex = indexPath.row
}
self.tblview.beginUpdates()
self.tblview.endUpdates()
}
}
For me, Safe Area was checked. Unchecking "Safe Area" did the work for me.

unable to Set Height of the CustomCells in swift

I have many customCells each cell may have a button which acts like a textbox or textArea.When the View loads they have very less height.
override func viewDidLoad() {
super.viewDidLoad();
self.view.backgroundColor = UIColor.groupTableViewBackground
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
self.tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
}
And i have the following constraints defined on the cell
Will auto layout work with prototype cells at all?
If not how to implement this?
I tried with HeightforrowAtIndexPath method layout looks good only after scroll. Initial load of the view will not come with good layout.
below is my code for this.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (eleData.elementType=="apple")
{
return 90;
}
else if (eleData.elementType=="banana")
{
return 50;
}
else
{
return 30;
}
}
Any suggestions .
Thank you in advance.
Quick google search gives you your answer...
UITableView dynamic cell heights only correct after some scrolling
You need to add layout if needed before returning your cell in the cellForRowAtIndexPath method:
cell.layoutIfNeeded()

Dynamic Height Issue for UITableView Cells (Swift)

Text data of variable length are being injected into tableview cell labels. In order for each cell height to be properly sized, I have implemented in viewDidLoad():
self.tableView.estimatedRowHeight = 88.0
self.tableView.rowHeight = UITableViewAutomaticDimension
This estimates the height to be 88.0 pixels and should resize the height automatically if larger. It works perfectly for cells that have yet to be scrolled to (as UITableViewAutomaticDimention is called upon scrolling to the cell), but not for the cells that are initially rendered onscreen upon loading the table with data.
I have tried reloading the data (as suggested in many other resources):
self.tableView.reloadData()
in both viewDidAppear() and viewWillAppear() and it did not help. I am lost.. does anyone know how to render the dynamic height for the cells loaded initially on screen?
Try This:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
EDIT
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Swift 4
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Swift 4.2
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Define above Both Methods.
It solves the problem.
PS: Top and bottom constraints is required for this to work.
Here is example
Use this:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300
and don't use: heightForRowAtIndexPath delegate function
Also, in the storyboard don't set the height of the label that contains a large amount of data. Give it top, bottom, leading, trailing constraints.
SWIFT 3
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160
AND!!!
In storyBoard: You HAVE TO set TOP & BOTTOM constraints for your Label.
Nothing else.
This strange bug was solved through Interface Builder parameters as the other answers did not resolve the issue.
All I did was make the default label size larger than the content potentially could be and have it reflected in the estimatedRowHeight height too. Previously, I set the default row height in Interface Builder to 88px and reflected it like so in my controller viewDidLoad():
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0
But that didn't work. So I realized that content wouldn't ever become larger than maybe 100px, so I set the default cell height to 108px (larger than the potential content) and reflected it like so in the controller viewDidLoad():
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 108.0
This actually allowed the code to shrink down the initial labels to the correct size. In other words, it never expanded out to a larger size, but could always shrink down... Also, no additional self.tableView.reloadData() was needed in viewWillAppear().
I know this does not cover highly variable content sizes, but this worked in my situation where the content had a maximum possible character count.
Not sure if this is a bug in Swift or Interface Builder but it works like a charm. Give it a try!
Set automatic dimension for row height & estimated row height and ensure following steps:
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Set automatic dimensions for row height
// Swift 4.2 onwards
table.rowHeight = UITableView.automaticDimension
table.estimatedRowHeight = UITableView.automaticDimension
// Swift 4.1 and below
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
}
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Swift 4.2 onwards
return UITableView.automaticDimension
// Swift 4.1 and below
return UITableViewAutomaticDimension
}
For Example: if you have a label in your UITableviewCell then,
Set number of lines = 0 (& line break mode = truncate tail)
Set all constraints (top, bottom, right left) with respect to its superview/ cell container.
Optional: Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data.
Here is sample label with dynamic height constraints.
For Swift 3 you can use the following:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Dynamic sizing cell of UITableView required 2 things
Setting the the right constraint of your view inside the table view cell (mostly it includes giving your view proper top , bottom and traling constraints)
Calling these properties of TableView in viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
This is a wonderfull tutorial on self-sizing (dynamic table view cells) written in swift 3 .
In my case - In storyboard i had a two labels as in image below,
both labels was having desired width values been set before i made it equal. once you unselect, it will change to automatic, and as usual having below things should work like charm.
1.rowHeight = UITableView.automaticDimension, and
2.estimatedRowHeight = 100(In my case).
3.make sure label number of lines is zero.
In addition to what others have said,
SET YOUR LABEL'S CONSTRAINTS RELATIVE TO THE SUPERVIEW!
So instead of placing your label's constraints relative to other things around it, constrain it to the table view cell's content view.
Then, make sure your label's height is set to more than or equal 0, and the number of lines is set to 0.
Then in ViewDidLoad add:
tableView.estimatedRowHeight = 695
tableView.rowHeight = UITableViewAutomaticDimension
To make autoresizing of UITableViewCell to work make sure you are doing these changes :
In Storyboard your UITableView should only contain Dynamic Prototype Cells (It shouldn't use static
cells) otherwise autoresizing won't work.
In Storyboard your UITableViewCell's
UILabel has configured for all 4 constraints that is top, bottom,
leading and trailing constraints.
In Storyboard your UITableViewCell's
UILabel's number of lines should be 0
In your UIViewController's
viewDidLoad function set below UITableView Properties :
self.tableView.estimatedRowHeight = <minimum cell height>
self.tableView.rowHeight = UITableViewAutomaticDimension
For Swift i checked this answer in iOS 9.0 and iOS 11 also (Xcode 9.3)
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Here you need to add top, bottom, right and left constraints
For Swift 4.2
#IBOutlet weak var tableVw: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Set self as tableView delegate
tableVw.delegate = self
tableVw.rowHeight = UITableView.automaticDimension
tableVw.estimatedRowHeight = UITableView.automaticDimension
}
// UITableViewDelegate Method
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Happy Coding :)
This is simple when doing 2 things:
setting the automatic height
tableView.rowHeight = UITableView.automaticDimension
creating all TableViewCells with FULL constraints from top to bottom. The last element MUST define some bottom spacing to end the cell.
So the layout engine can compute the cell heigth and apply the value correctly.
Unfortunately, I am not sure what I was missing. The above methods don't work for me to get the xib cell's height or let the layoutifneeded()or UITableView.automaticDimension to do the height calculation. I've been searching and trying for 3 to 4 nights but could not find an answer.
Some answers here or on another post did give me hints for the workaround though. It's a stupid method but it works. Just add all your cells into an Array. And then set the outlet of each of your height constraint in the xib storyboard. Finally, add them up in the heightForRowAt method. It's just straight forward if you are not familiar with the those APIs.
Swift 4.2
CustomCell.Swift
#IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
#IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
#IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!
#IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
#IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!
MyTableViewVC.Swift
.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell
.
.
myCustomCells.append(cell)
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant + myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant
return totalHeight + 40 //some magic number
}
I use these
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
Try
override func viewWillAppear(animated: Bool) {
self.tableView.layoutSubviews()
}
I had the same problem and it works for me.
You should just set all constraints for TOP, BOTTOM and HEIGHT for each object on cell view/views and remove exists middle Y position if have. Because where you didn't this, puts artifacts on another views.
For objective c this is one of my nice solution. it's worked for me.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row];
cell.textLabel.numberOfLines = 0;
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
We need to apply these 2 changes.
1)cell.textLabel.numberOfLines = 0;
cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
2)return UITableViewAutomaticDimension;
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0
And don't forget to add botton constraints for label
I was just inspired by your solution and tried another way.
Please try to add tableView.reloadData() to viewDidAppear().
This works for me.
I think the things behind scrolling is "the same" as reloadData. When you scroll the screen, it's like calling reloadData() when viewDidAppear .
If this works, plz reply this answer so I could be sure of this solution.
I had also got this issue initially, I had resolved my issue from this code
try avoiding the use of self.tableView.reloadData() instead of this code for dynamic height
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
When using a static UITableView, I set all the values in the UILabels and then call tableView.reloadData().
What worked for me was creating a height constraint on my custom cell that I set at runtime (I've got an expand/collapse button in each cell).
Then in heightForRowAt in the parent, I had to do a combination of suggested answers:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if let cell = tableView.cellForRow(at: indexPath) as? GroupTableViewCell {
return cell.heightConstraint.constant
}
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 88.0
}
I use the already calculated height constraint constant where it's available and UITableView.automaticDimension otherwise. This was the only way to get the correct height and maintain the correct cell state when the cell gets recycled.
I hear it's considered bad practice to reference the cell itself inside heightForRowAt, but I don't see another way of doing it with custom cell objects with dynamic heights whilst keeping all constraints satisfied.
self.Itemtableview.estimatedRowHeight = 0;
self.Itemtableview.estimatedSectionHeaderHeight = 0;
self.Itemtableview.estimatedSectionFooterHeight = 0;
[ self.Itemtableview reloadData];
self.Itemtableview.frame = CGRectMake( self.Itemtableview.frame.origin.x, self.Itemtableview.frame.origin.y, self.Itemtableview.frame.size.width,self.Itemtableview.contentSize.height + self.Itemtableview.contentInset.bottom + self.Itemtableview.contentInset.top);
Set proper constraint and update delegate methods as:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
This will resolve dynamic cell height issue. IF not you need to check constraints.
Swift 5 Enjoy
tablev.rowHeight = 100
tablev.estimatedRowHeight = UITableView.automaticDimension
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tablev.dequeueReusableCell(withIdentifier: "ConferenceRoomsCell") as! ConferenceRoomsCell
cell.lblRoomName.numberOfLines = 0
cell.lblRoomName.lineBreakMode = .byWordWrapping
cell.lblRoomName.text = arrNameOfRooms[indexPath.row]
cell.lblRoomName.sizeToFit()
return cell
}

Self Sizing Cell in Swift, how do I make constraints programmatically?

I'm trying to do a sidebar with self sizing cells in swift. I found this great tutorial : http://www.appcoda.com/self-sizing-cells/
As far as I know you need 3 things to make a self sizing cell:
Define auto layout constraints for your prototype cell
Specify the estimatedRowHeight of your table view
Set the rowHeight of your table view to UITableViewAutomaticDimension
The last two are covered in the tutorial by code, but the first one is explained by the story board, and my problem is how do I implement it by code??
I have this method where I get my custom cell, I think that I have to implement the constraints(in the tutorial you can see what kind of constrains) here but I don't know how, so please could you give me some help?
override func tableView(tableView: (UITableView!), cellForRowAtIndexPath indexPath: (NSIndexPath!)) -> UITableViewCell{
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CellId")
cell!.backgroundColor = UIColor.clearColor()
cell!.textLabel?.textColor = UIColor.darkTextColor()
let selectedView:UIView = UIView(frame:CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height))
selectedView.backgroundColor = UIColor.orangeColor().colorWithAlphaComponent(0.3)
cell!.selectedBackgroundView = selectedView
//asignar valores a la celda
cell!.textLabel?.text = tableData[indexPath.row]
cell!.textLabel?.numberOfLines = 0
cell!.setTranslatesAutoresizingMaskIntoConstraints(false)
}
return cell!
}
Update 1:
The text goes beyond the 3rd break of line in the 1st and the 3rd row, but here only show me max. of 3 breaklines
Thanks!
Don't add layout constraints in tableView(_:cellForRowAtIndexPath:).
You should not instantiate a table view cell in that method yourself. Instead, you should register one with the UITableView (probably in the viewDidLoad() method of your view controller) (registerClass(_:forCellReuseIdentifier:) or registerNib(_:forCellReuseIdentifier:)).
In tableView(_:cellForRowAtIndexPath:) you use dequeueReusableCellWithIdentifier(_:forIndexPath:) to get an instance of the cell. The table view will reuse cells as you scroll, so that it doesn't have to create new ones all the time. Essentially, let's say you never see more than 15 cells on screen at the same time, then there won't be more than that many instances.
Now, when you register your table view cells (see above) you should probably subclass UITableViewCell and then either set your layout constraints in code (maybe override init(style:reuseIdentifier:)) or you can create a .nib file and use that. Then you can set up the constraints in Xcode through the graphical UI.
Let me know if you have any questions.
I found a good function to make cell dynamic size
func dynamicHeight(text:String, font:UIFont, width:CGFloat) -> CGFloat{
let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.height
}
Call this function in heightForRowAtIndexPath
I hope it works.
Try this:-
First add this two functions in your class
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Second in order to make the UITableViewAutomaticDimension work make sure you have added all the left, right, bottom, and top constraints relative to cell container view.

Resources