I have an imageView on a UITableViewCell, and I want to set height of the cell / imageView to a different value compare what I set in prototype cell. I do not want to implement heightForRowAtIndexPath method, because I do not want to precalculate the height of the content. If UITableViewAutomaticDimension is set and at least on iOS 8 heightForRowAtIndexPath does not need to implement.
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 3
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")!
let iv = cell.viewWithTag(1) as! UIImageView
iv.image = UIImage(named: "img1")
let cs = iv.constraints.first! as NSLayoutConstraint
cs.constant = 100
cell.layoutIfNeeded()
cell.setNeedsUpdateConstraints()
return cell
}
Structure of the prototype:
Although the height of the cell in prototype is set to 44.0 px, but in cellForRowAtIndexPath method I want to override this value with 100.0 px.
It'll not work the way you do.
You should implement delegate method of UITableViewDelegate
func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// calculate size of image and return its height here
}
Related
I'm trying to build a table view, one of the cells in this TableView is a tabs widget.
so I'm creating this tab widget as a CollectionView. the cells of the collectionView have different subViews and each cell has it's own size.
what I'm trying to achieve is Self-sizing cells in the collectionView, but it is not working.
I'll provide you with the way I used so I can get your help.
//MARK: TableView
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DetailsTabs", for: indexPath) as! DetailsTabs /*this cell has 2 collectionViews. The first collectionView is the tabs and the second collectionView is the content that should be diplayed. I gave the first collectionView a fixed height, trailing leading and top. the second collectionView has trailing, leading bottom, and top to the first collectionView*/
cell.postDetail = postDetail
cell.widgets = self.Template
cell.parentController = self
cell.Shownavigationbar = self.Shownavigationbar
return cell
}
//MARK: DetailsTabs Class
override func awakeFromNib() {
//code to setUp the collectionViews
//pagesLayout is the UICollectionViewFlowLayout for the second collectionView
pagesLayout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width, height: 1)
}
//MARK: IN collectionView Cells I added this function:
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
var frame = layoutAttributes.frame
frame.size.height = ceil(size.height)
layoutAttributes.frame = frame
return layoutAttributes
}
note: the content of the collectionView cells might be webView or tableview.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
you should use UITableViewAutomaticDimension in estimatedHeightForRowAtIndexPath
hope this is working fine for you...!
I have an UITableView with a default cell where I just add a string:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = tasks[indexPath.row].name
cell.textLabel?.textColor = .white
cell.textLabel?.textAlignment = .center
return cell
}
My problem is that the cell is too big for just some normal text. Here is a screenshot, the cell has the blue background:
I didn't have this issue before, when my data source was an array on String's. The issue appeared after I changed from Strings to custom objects. Not sure if this is related.
How can I fix this ? I tried setting the row height to custom value, but it doesn't have any effect.
edit with table view code:
extension TasksViewController {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = tasks[indexPath.row].name
cell.textLabel?.textColor = .white
cell.textLabel?.textAlignment = .center
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
dummyTxt.textField.text = tasks[indexPath.row].name
dummyTxt.becomeFirstResponder()
dummyTxt.textField.becomeFirstResponder()
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .destructive, title: "Delete") { (_, index) in
self.tasks.remove(at: index.row)
}
return [delete]
}
}
Set this on tableView:
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
Do NOT override heightForRowAt delegate method.
And then just make sure that the prototype cell that you registered as "Cell" has proper constraints that can be used to calculate its height. In your case make sure that both top and bottom anchors of the label are constrained to the top and bottom anchors of the cell.
Use following delegate method with returning some integer value, if you need same size for every cell.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 40
}
Hopes It may help you.
Try this:
To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout.
Assign and implement tableview dataSource and delegate
Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight
Implement delegate/dataSource methods (i.e. heightForRowAt and return a value UITableViewAutomaticDimension to it)
-
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Don't forget to set dataSource and delegate for table
table.dataSource = self
table.delegate = self
// Set automatic dimensions for row height
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
}
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
For label instance in UITableviewCell
Set number of lines = 0 (& line break mode = truncate tail)
I have a table view with height of cells set to automatic.
Once in a few runs, a few cells in the table are displayed empty (white space). Upon debugging, I noticed that the 'cellForRowAtIndexPath' function returns these cells as usual. Also, every time this bug shows up, the console has this message:
"Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead."
Scrolling up and down a couple of times fixes the issue and cells are displayed.
I use this following functions for height:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
I have been stuck with this for a week and any help would be greatly appreciated!
Edit: Code for the cells:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var row = indexPath.row
tableView.allowsSelection = false;
let cellIdentifier = "testTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! testTableViewCell
let post: PostMdl!
if(row < posts.count) {
post = posts[row]
}
else {
return cell
}
cell.label.delegate = self
cell.label.enabledTextCheckingTypes = NSTextCheckingType.Link.rawValue
cell.label.userInteractionEnabled = true
cell.brandName.text = post.brandName
cell.timeStamp.text = post.timeStamp
cell.brandImg.sd_setImageWithURL(post.brandImgUrl, placeholderImage: UIImage(named: "placeHolder"))
if let img = post.postImg {
cell.mainImg.image = img
} else {
cell.mainImg.image = UIImage(named:"lazyLoad")
}
cell.label.text = post.postTag
cell.labelDistanceFromImg.constant = 30
cell.labelDistanceToBtm.constant = 30
cell.postTag = post.postTag
cell.socNtwkImg.image = UIImage(named: post.socNtwk)
return cell
}
I guess you had set wrong constraints to subviews of UITableViewCell.contentView.
This image shows what I reproduce your error:
Please note the right constaints of red view, it just has Top Left Right Height, lacks bottom constraint, when I add it and it looks good:
Yes, there still have problem that Unable to simultaneously satisfy constraints, we can modify the priority of height constraint, default priority is required(1000), we change to Hight(750), it works!
I don't know your cell's detail, but the error's reason is likely, hope my answer helps you.
Append codes
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return tableView.dequeueReusableCellWithIdentifier("cell")!;
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}
What is your mobile phone version of the iOS?
In the previous iOS8 version I also encountered similar problems.
My method is as follows:
tableView.estimatedRowHeight = 88.0
tableView.rowHeight = UITableViewAutomaticDimension
Hope can help you
hello I have a dynamic TableViewController in which there is one cell which has one image, and labels. I have set constraint of all of them. The problem is its not viewing correctly.
This is how its viewing
Code:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 103
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.setNeedsLayout()
tableView.layoutIfNeeded()
self.tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return newarray.count
}
override
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("requestcell", forIndexPath: indexPath) as! NewRequestTableViewCell
let image : UIImage = UIImage(named: "placeholder_product_image")!
cell.imageView!.image = image
cell.requestTitle.text = "IPHONE 6s PLUS"
cell.DestinationCountry.text = "Pakistan"
return cell
}
I don't know what else to do. Please help how can I have row like I designed
The problem here is the height of your cell
add the following methods in your code: (replacing of course <#cell_height#> by the value of your choice, or by UITableViewAutomaticDimension)
override func tableView(_ tableView: UITableView,
heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return <#cell_height#>;
}
In order for tableView self sizing to work, you need to add constraint to both top and bottom of UILabel.
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 103
I think your trying is right, but you need to increase the estimatedRowHeight. i.e, 300 or 600.
And you need to add constraints on Storyboard suitably.
so just add up, left, right, bottom distance constraints.
Never give the width & height constraints there.
Beside you need to call the cell.contentView.layoutIfNeeded just in the cellForRowAtIndexPath method.
I think it will work then.
Sincerely,
Harri.
I have a header and a body inside my tableviewcells. I'm trying to get the body to wrap but I'm having issues.
This is the code I'm using in my view controller
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("mainCell") as? mainCell {
cell.mainHeader.text = (mainHeader[indexPath.row])
cell.mainBody.text = (mainBody[indexPath.row])
cell.mainBody.numberOfLines = 0
cell.mainBody.lineBreakMode = NSLineBreakMode.ByWordWrapping
return cell
} else {
return mainCell()
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mainHeader.count
}
}
I searched and thought that the numberOfLines = 0 and lineBreakMode = NSLineBreakMode would work but it's obviously not.
Sorry if this is simple, thanks in advance.
#Daven
I know this probably won't help, but I don't think I have that or if I do I'm unsure of what it is. Also updated original code with everything that is in my VC but the vars
I have this for my custom cell
import UIKit
class mainCell: UITableViewCell {
#IBOutlet weak var mainHeader: UILabel!
#IBOutlet weak var mainBody: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func configureCell (text:String) {
mainHeader.text = text
mainBody.text = text
}
}
To make your cell expand as its label grows, you'll need to make sure you've done a few things. Set your tableView's estimatedRowHeight to a value, like
tableView.estimatedRowHeight = 200.0;
tableView.rowHeight = UITableViewAutomaticDimension
or via this method:
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 200.00
}
You also have the option of using this method, but it's not necessary if all your cells are going to vary in height:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
You may also find this tutorial helpful (this is what I used :)). It shows what your autolayout constraints should look like. More information about self-sizing cells is also here.
Assuming you want your cell to expand when the text is longer than one line, you want to set the cell height to be automatic using the delegate function:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
and set the estimated row height using
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return currentInfoSelectorOption.rowHeight + 100
}
Then use autolayout in your cell to set the height. You can do this by setting the top and bottom distance constraints of the cell to the label as a constant value and setting the labels number of lines to 0. This should allow the label to expand and push the cell with it