I've making a simple UITableViewCell prototype in a storyboard, but I'm having some issues with the self-sizing aspect. As you can see in the image below, the cell size increases, but the text doesn't move down. (It has 0 lines.) Here's the table's view controller.
import UIKit
class ViewController: UITableViewController {
let events = ["Kaufman Family Finished Project Reception", "Home Remodelers' Survival Guide", "Mori Family Mid-Construction Showcase"]
let locations = ["La Cañada Flintridge", "Claremont", "Claremont"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 70.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return events.count;
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("EventCell") as EventTableViewCell
cell.eventName.text = events[indexPath.row]
cell.eventLocation.text = locations[indexPath.row]
return cell
}
}
Obviously I can't provide you with dozens of screenshots of the storyboard, so comment if you need other information. Here's some basic pictures though.
Hard to tell from the constraint diagram... for this arrangement to work you need:
Event Name label set to 0 lines (you said you do)
Event Name label set to word wrap (by default it isn't)
Event Name label constrained to top of cell and leading/trailing edges of cell
Event Name label bottom constrained to top of Event Location label
Same conditions for Event Location label - word wrap, 0 lines, if you want it to have variable number of lines
Event Location label constrained to bottom of cell and leading/trailing edges of cell
This should allow both labels to dynamically size their height and for the cell to size itself to accommodate the label heights and margins.
One last thing... you are calling sizeToFit on the label after setting the text, right?
Here are some images from a project of mine where resizing labels work:
Final result:
"Questions Here" is the label being changed.
Size Inspector
Properties Inspector
Related
Can we able to set the multiline label with left and right side as image. please check the attached image.
Yes, I am using tableview cell xib. Need to do this with constraints.
I tried
left imageview - leading, width, height, vertically in container
second label - top, bottom , leading to first image , trailing to second image. number of lines = 0.
right image view embed with UIView - this is for when select the image background colour changed to blue with checkmark image
constraint - trailing, width , height , vertically in container
The issue is label is getting truncated when large text is there.
After that,I tried to remove the width of second image, but getting constraint issue.
Please help me to resolve this issue.
Thankyou in advance.
The cell can be prevented from performing dynamic auto-resizing for a variety of reasons:
Constraints could be preventing dynamic height:
To confirm the constraints, run the app in the debugger, then tap on the “Debug View Hierarchy” button and confirm the constraints. It is a quick way to see all the constraints (and make sure there are not any that you did not intend):
If you had some extraneous constraint (e.g., an unintended height combined with top/bottom), that could cause the label to not grow in height to fit the text.
The table view could be defined to not support automatic dimension of the cells:
Another possible source of the problem is the table view’s row height was set to some fixed value, preventing the label from expanding to fit the text. Confirm that the table view’s row height is set to automaticDimension. Either in IB:
Or, programmatically:
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 44
}
You could have something in code that is forcing a particular cell height:
Needless to say, make sure you are not implementing a specific height in tableView(_:heightForRowAt:). The use of automaticDimension, above, means that you should not implement this delegate method at all.
Maybe the number of lines is getting reset to 1.
While in the view debugger, look at the properties for the label, and make sure the numberOfLines is still set to zero. Make sure there isn’t some code somewhere that is resetting the numberOfLines.
Not that it is relevant, but this is the code that generated the above image. Not much here to see, admittedly:
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var strings = [
"This is a very long string that goes on and on. This is so long that it will take a few lines. This one takes four lines, but the next one takes only one.",
"This is short string.",
"This is a very long string that goes on and on."
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return strings.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.customLabel.text = strings[indexPath.row]
return cell
}
}
I am making a simple contacts application with controllers: ContactTableViewController and custome cell: ContactTableViewCell. I created a custom table view cell where the style is custom, identifier is ContactTableViewCell, and class is also ContactTableViewCell.
The cell has two UILabel fields, which are exposed to ContactTableViewCell.swift class as follows:
import UIKit
class ContactTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var info: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
print("cell loaded with name: ", name)
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Now I want to display them in my ContactViewController, and the relevant part of my controller looks like this:
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
// here we communicate with parts of the app that owns the data
override func tableView(_ tableView : UITableView
, cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
let id = "ContactTableViewCell"
// deque a cell as an instance of ContactTableViewCell
guard let cell = tableView.dequeueReusableCell(withIdentifier: id, for : indexPath)
as? ContactTableViewCell else {
fatalError("dequed cell is not instance of ContactTableViewCell")
}
cell.name.text = "hello"
cell.info.text = "hello information"
However, when I run the simulation I only see two rows of "hello", even though it should be something like:
hello
hello information
repeated twice. What is the problem here?
Most probably you don't have enough room to fit both labels. You can either set the row height in storyboard by:
Selecting your tableview
Go to size inspector
Change the Row Height
OR
You can implement tableView(_:heightForRowAt:) method in your tableView's delegate. i.e.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return desired height for your cell
return 90.0
}
It is a contraint issue. You have to define height, width, x and y positioning for both the name UILabel and the info UILabel. Font size places a dominant role for height with UILabels and width can be based on the number of characters in the UILabel x font size so you do not have to explicity express height and width constraints for a UILabel, but for a UIButton you would have to explicitly define constraints for x,y,width,height. For UILabel we only have to define x and y constraints.
What happens when you do not clearly define the constraints for your UI elements is that the rendering of your View will have unpredictable results and UI elements quite often just do not appear on the view.
It looks like, from your code, you are using XCode designer to add your UILabels so that is what you can use to add constraints. You can also add constraints programmatically as well. But I am pretty sure you are using XCode Storyboard designer.
Whether programmatically or through XCode designer you need add a constraint for the name UILabel to the top and left of the super view, you can reposition later, and then constrain x and y alignment of the info UILabel to the name UILabel, horizontally aligning to the name UILabel and +8 vertical spacing to the bottom of the name UILabel, this will place the info UILabel below and centered to the name UILabel.
See this guide: https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithConstraintsinInterfaceBuidler.html
And this Stackoverflow answer: https://stackoverflow.com/a/34448801/1258525
Not the first two constraints I have circled in this picture, this defines the x and y for the Video Quality UILabel:
And then see how the next label below, Onset Threshold constraints itself to the leading edge of the Video Quality label and then the divider below the VideoQuality label:
My theory the 2nd label is truncated not getting sufficient width, and may be the number of lines in the second label is 1. Hence try setting number of line to 0 and check the width and auto layout constraints.
I have such problem, while trying to create a simple messenger.
Here what I came to:
class ChatBubleUIView that class is responsible for creating a bubleview with label in it. It works fine, calculating view height according to label height
Inside my cell I've created a content view. In the cell class, I'm adding new ChatBubleUIView instance as a subview to content View.
The problem is that, content doesn't scale up to the size of my ChatBubleInstance.
class ChatMessageTableViewCell: UITableViewCell, MessageCellConfiguration {
var message: Message?
override func awakeFromNib() {
super.awakeFromNib()
}
func configureCell() {
let chatBubleView = ChatBubleUIView(message: message!)
self.addSubview(chatBubleView)
}
}
In my tableView delegate
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "messageCell") as! ChatMessageTableViewCell
let data = currentUser.mesaageHistory[indexPath.row]
cell.message = data
cell.configureCell()
return cell
}
Also I have set estimated row height for my tableView
messageTableView.rowHeight = UITableViewAutomaticDimension
messageTableView.estimatedRowHeight = 44
What should I do to set to my tableView row height chatViewBubleUIView instance height.
Previously, I solved this problem using old-school approach, programmaticly determine chatViewBubleUIView instance height and then implement heightForRowAtIndexPath. But I'd like to do that using AutoLayoaut.
set your label's four constraint like top,bottom,leading,trailing and number of height of your label should be 0. Then it will automatically increased it's height as per content. If you are taking this label in any view then view's constrains should be same as label i have mentioned above!
Question is fairly self explanatory and I may be missing something simple. The following is done in Interface Builder.
I have created a UITableViewController, I've set the Content to Static Cells and Style to Grouped.
I've defined the number of Sections as well as the number of Rows for each section. I've set the Style of each cell to be Basic.
Now, within each cell, I have the default Content view and Label. For the label I have set the Text to Plain, Font to Body and Lines to 0. Normally this allows me to achieve Dynamic Type with UILabels.
I hook up the cells as IBOutlets and set their text (only) programmatically.
When I run the app, everything is there, except that the Font of the labels (as well as the height of each cell) is unchanged (not Dynamic Type).
Therefore, my question is, can Dynamic Type be achieved for a label within a Basic (non Custom) Static Cell or are these cells meant to be "as they are"?
The closest question I've seen on SO is this, however it refers to Custom Cells.
Also tried implementing
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
but to no avail.
Dynamic type does work with static tables, but in my tests, just not with "Basic" cell type. Change it to a "Custom" cell type, add your label and the four constraints, and make sure to choose one of the dynamic fonts (e.g. "Title 3").
If you want the cell height to adjust accordingly, make sure you have both top and bottom constraints. And as you discovered, you can't just set the row height to UITableViewAutomaticDimension, but rather you have to implement that delegate method, e.g. in Swift 3:
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
I've scoured through all of the questions here regarding a similar issue and I still seem to have this problem no matter what I do. I'm on iOS 8.3.
You can find the full code at: https://github.com/DanielRakh/CellHeightTest.git
I have a cell that dynamically resizes based on the content of a UILabel that varies from single to multi-line text. Everything seems to be fine initially but when I start scrolling fast and quickly switch directions
I get a warning in the debugger:
2015-03-10 02:02:00.630 CellHeight[21115:3711275] 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.
Here's how it looks in the simulator. I've marked the discrepancies in red:
Here's the simple setup in IB where I have a UILabel pinned top(11), bottom(11), leading(8), and trailing(8) with a custom cell at 45pts:
Here is my code. The cell is a custom subclass thats pretty much empty except for the IBOutlet for the label:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var arr = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for _ in 1...10 {
arr.append("This is an amount of text.")
arr.append("This is an even larget amount of text. This should move to other lines of the label and mace the cell grow.")
arr.append("This is an even larger amount of text. That should move to other lines of the label and make the cell grow. Crossing fingers. This is an even larger amount of text. That should move to other lines of the label and make the cell grow. Crossing fingers.")
}
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 45.0
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
tableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! TstTableViewCell
cell.tstLabel.text = arr[indexPath.row]
return cell
}
}
EDIT: I've found that if I created the cells programmatically and set the constraints programmatically everything seems to work as intended. Weird. This seems to be an IB + AL issue.