I'm making a simple texting app for practice and the UITableView has lots of cells containing messages.
It works well with one-line messages but, as you can see on the bottom, with multi-line texts the size of the UITableViewCell starts getting in the way and cutting the message short. Just in case, here's the code for my cellForRowAtIndexPath method:
internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if usernames[indexPath.row] == PFUser.currentUser()?.username {
cell = tableView.dequeueReusableCellWithIdentifier("text")!
} else {
cell = tableView.dequeueReusableCellWithIdentifier("reply")!
(cell.viewWithTag(2) as! UILabel).text = usernames[indexPath.row]
}
(cell.viewWithTag(1) as! UILabel).text = messages[indexPath.row]
return cell
}
Basically I just need a solution that will enable this app to support multi-line messages. Thanks in advance for any help!
Two things you need to do:
1) In viewDidLoad, specify these:
tableView.rowHeight = UITableViewAutomaticDimension
# The estimated row height number is not that important, just approximate it
tableView.estimatedRowHeight = 140
2) Define all constraints for your custom cell. Make sure top and bottom constraints specifically are defined.
The second step is particularly important.
1) On Storyboard,
In Attribute Inspector section.
Set Lines = 0
2) In func viewDidLoad(),
tableView.estimatedRowHeight = 50.0
tableView.rowHeight = UITableViewAutomaticDimension
You can use self-sizing table view cells and UITableViewAutomaticDimension. This is quite good article about it.
The trick to getting Auto Layout to work on a UITableViewCell is to ensure you have constraints to pin each subview on all sides — that is, each subview should have leading, top, trailing and bottom constraints. Then, the intrinsic height of the subviews will be used to dictate the height of each cell. You’ll do this now.
Then setup rowHeight to UITableViewAutomaticDimension:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
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
}
}
The content in the cells is aligned to the center.
This caused the cells were separated by unwanted white space.
I have tried the following code
In viewDidLoad
tableView.layoutMargins = UIEdgeInsets.zero
tableView.separatorInset = UIEdgeInsets.zero
tableView.separatorStyle = .none
In cellForRowAt
cell.layoutMargins = UIEdgeInsets.zero
cell.separatorInset = .zero
I am looking for a utility method to customize the space between the cells.
Please find the image below
Cell row height
Cells have exactly 0 space between them, so the cells themselves have to have a top/bottom margins.
To simply test what I've just said, set background of the cell to .red. If I'm wrong, you will have white stripes between red cells.
To get it right:
Look for top/bottom margins/constraints inside the cell and remove them
Make sure that all constraints make the row height unambiguous and use automaticDimension or calculate row height by yourself and hardcode it.
Use tableView:heightForRowAtIndexPath:. This lets you set the size regardless of the content in your cell.
Depending on your cell configuration, maybe setting automaticDimension could resolve it:
self.tableView.rowHeight = UITableView.automaticDimension
Otherwise, you may want to decrease the cell height:
public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CELL_HEIGHT_VALUE
}
Hope this helps.
I am populating my UITableView from a web service. Here are all the constraints. Some of the items like Cheese Burgers has 10 lines of text which is not displayed.
And here is the result:
To enable automatic resizing of your UITableViewCell, set the rowHeight and estimatedRowHeight of your UITableView in your controller's viewDidLoad() method, like so:
self.tableView.estimatedRowHeight = 150.0
self.tableView.rowHeight = UITableViewAutomaticDimension
And then if you would like or you need to implement the heightForRow UITableViewDelegate method, don't forget to pass again the UITableViewAutomaticDimension to whatever row or section that needs an auto resizing cell, like so:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let section = indexPath.section
if let itemSection = ItemTableViewSections(rawValue: section) {
switch itemSection {
case .header: return 80.0
case .photos: return 95.0
case .note: return UITableViewAutomaticDimension
case .rejectOptions: return 50.0
}
}
return 0
}
Lastly, don't forget to select an answer if an answer really answers your question just like in your last question :)
EDIT: I made a sample project that uses Storyboard and targeting merely iOS 11. All works fine. Just don't forget to set your label's constraint - top, bottom, leading, and trailing. These constraints will be required for autoresizing cell. Lastly, set the UILabel's number of lines to 0.
increase Vertical Content Hugging Priority by 1 of UILabel
When all else fails, try setting Content Compression Resistance Priority to 1000. That's how I fixed my problem.
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!
I have a UITableViewCell subclass that fills my UITableView. It's a simple subclass with just a variable length UILabel in it, and I want to resize the cell based on the length of this label. In my Storyboard I have constraints set up that pin the label 15pt away from the edges of the cell's contentView.
However, in heightForRowAtIndexPath, it keeps giving me the incorrect height unless I specify the preferredMaxLayoutWidth value for the UILabel. This seems unnecessary, as it can be determined based on the constraints I've set on the label. Intuitively, it's the width of the cell - 30 (15pt from each side) but that shouldn't have to be set explicitly, especially because I may change it to say, 20, later.
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! MyTableViewCell
let str = strangs[indexPath.row]
cell.myLabel.text = str
// If the following line is not included it does NOT return the right height
// cell.myLabel.preferredMaxLayoutWidth = tableView.bounds.width - 30
return cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
}
How do I call systemLayoutFittingSize: to calculate the height of my cell without explicitly setting preferredMaxLayoutWidth on the label?