Automatic height adjustment for static UITableViewCell doesn't work - swift

I have a static UITableView and I want to set the row height for three of the cells dynamically. So in viewDidLoad() I implemented the following code:
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableView.automaticDimension
I also implemented the heightForRowAt method:
(The first two cells of the first section should have a fixed height)
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 && indexPath.row == 0 {
return CGFloat(85)
} else if indexPath.section == 0 && indexPath.row == 1 {
return CGFloat(145)
}
return UITableView.automaticDimension
}
This the result which I'm currently getting:
I changed the lines of the labels to 0, too and the constraints of the labels inside the cells are 0, 12, 0, 12 (top, right, bottom, left).
Does anybody know, why the cell in section 3 doesn't display the data in the right way?
Edit:
(How it looks after the implementation of the suggestion above)

Because sizeToFit() did not work for you, we are going to try something a little more involved.
The cell in section 3 is displaying the data the right way. This is because UILabels don't automatically adjust their height to accommodate the text inside. Here's what you need to do:
1. Create a height constraint for your UILabel In your interface builder, add a constraint for the height of the UILabel in section 3's cell. Connect this height constraint to your view controller's class via an #IBOutlet:
class YourViewController: UIViewController {
#IBOutlet var cellLabel: UILabel!
#IBOutlet var cellLabelHeight: NSLayoutConstraint!
...
}
2. Add String extension that calculates height I am unsure of where/when you are setting the text of the UILabel in question, but I know you are doing this somewhere as you have described it as being "dynamic". Whenever you do set the text of the UILabel in question, you now also need to change the constant of the height constraint that we made in order to accommodate this text. So, we need to be able to calculate the height of the UILabel based on its width and font. We can add an extension to String in order to do this:
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil)
return ceil(boundingBox.height)
}
}
3. Set the height constraint's constant based off the UILabel's text The final step is to set the height of the UILabel height constraint we made by using the extension we just created:
cellLabel.text = "DummyDataDummyDataDummyDataDummyDataDummyDataDummyDataDummyDataDummyData"
//This will be called immediately after you set the text for the UILabel in question
cellLabelHeight.constant = cellLabel.text.height(withConstrainedWidth: cellLabel.frame.width, font: cellLabel.font)

The cell in section 3 is displaying the data the right way. Unless you tell it otherwise, a UILabel will not automatically adjust to accommodate the text within it.
What I need you to do is select the UILabel in question, then in the attributes inspector, set the Number of Lines to 0.
You also said that this UILabel is dynamic, meaning you are setting it's text somewhere in your code. Immediately after you set this UILabel's text, you are going to want to call myLabel.sizeToFit(). This should adjust the label's height to accommodate the text within.
If this doesn't work, I have another, more involved solution that should work for you.

Please look at the below;
Select your cellLabel and set the Lines value to 0:
Also apple says Self-Sizing
Summary :
lay out your table view cell’s content within the cell’s content view. To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge. If your views have intrinsic content heights, the system uses those values. If not, you must add the appropriate height constraints, either to the views or to the content view itself.
Change the bottom constraint of the AuthorLabel from equal to Greater than or equal

Related

NSGridView custom view intrinsic size

I'm building a simple NSGridView, and want to have a custom NSView as each element of the grid. Eventually, each NSView will be a xib based label (NSTextField) centered in the NSView.
The problem I am having is with the intrinsic size of the NSView. I want to define the size of the NSView and have auto layout work based on that. I added this code to the custom view (labelView):
override var intrinsicContentSize: NSSize {
return NSSize(width:100, height:100);
};
And it is indeed called; but apparently ignored. As a test, I have on the same row some other labels, and the height for the row is always set to the largest of the row text heights (including the label in the custom view); but the length is set to the longest of column text fields, ignoring the label in the custom view. And anyway, I want to arbitrarily make the NSView a certain height and length, as I tried (but failed) to do with the intrinsicContentSize.
NSStackview seems to do the right thing; but NSGridView does not.
I can force the width of a particular column with
grid.column(at:0).width = 400;
but want I really want to do is define the size of the NSView, and let autolayout use that as a building block.
This strikes me as a conceptual error on my part, so if someone could explain these NSGridView-autolayout-NSView subtleties, I think many might benefit.
I was having the exact same issue, tried to use custom NSView's inside a NSGridView and couldn't get them to draw correctly. What finally worked for me was setting the following:
let gridSize = 5
let cellSize: CGFloat = 50
gridView.xPlacement = .fill // this was key part of the solution
gridView.yPlacement = .fill
for i in 0 ..< gridSize {
gridView.row(at: i).height = cellSize
gridView.column(at: i).width = cellSize
}
Note that I'm setting the size of each cell with the row height and column width of the NSGridView, and not using the NSView size, but this is the only way I got it working.

how can i set a dynamic height to collection view cell in swift?

HI everyone i'm looking for a working method that allows to dynamically set the height in my collectionViewCell because I tried various other answers without success.
My situation is pretty simple, I have a cell with an image, a UIlabel that displays username and a UILabel which contains some text. It's a common Comment cell for a post. My Screen
I tried this method but it doesn't work precisely because the height is too much compared to what is necessary
private func estimatedFrameForText(text: String) -> CGRect {
let size = CGSize(width: 270, height: 80)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
return NSString(string: text).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17)], context: nil)
}
so my question is: there is a correct way to implement dynamic size on collection view cell like layout attribute wrap_content for Android?
UPDATE
I solved my problem using constraints and Automatic Estimated Size on Collection View. Setting up all constraints I forced the width of LABEl to be equal to the cell width and for the height I set the top and bottom spacing for the UILabel (with lines 0) to be equal to its content view (the one standard for the UiCollectionViewCell)
IT'S also important to set the size of the collection view cell to automatic
VIEW IMAGE

Setting the height: TableViewCells with custom Nib that are different sizes

I have a TableViewController that has a custom TableViewCell under the identifier "customCell". Heres an image of the configuration of the cell along with the IBOulets connected to it:
The cell takes information from my backend and presents it. The description text view (just noticed that I accidentally named it descriptionLabel) doesn't allow scrolling so it expands based off of the content that it's holding. The database is being processed correctly from the database, and it's displaying on the app. The only problem is that the cell is not its correct height. On the TableViewControl that's registering this cell through its identifier, I automatically set the height of the cell using UITableViewAutomaticDimension in heightForRow:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
but that's not working either. *The only thing that works is when I set the height of each cell to a standard value such as 200. That doesn't work for me because each cell will be a different height because of the length of the textView.
How do I set the height of a custom nib (tableViewCell) so that it adjusts based off of the content within it instead of setting the height to a specific value?
1-Remove both textViews and replace them with labels
2- Title lbl with theses constraints
top,leading,trailing , .lines = 0
3- Description lbl with theses constraints
bottom ,leading,trailing to contentView,top to bottom of title lbl , .lines = 0
Off course you can leave the 2 textviews , but you have to give each one an initial height and do this in
override func layoutSubviews() {
super.layoutSubviews()
self.titleTvHeight.constant = self.titleTv.contentSize.height
self.desTVheight.constant = self.desTv.contentSize.height
}
//
Don't forget to set this in viewDidLoad of the VC
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableViewAutomaticDimension
Anyway you can remove heightForRowAt

Swift - autoresize UiTableViewCell to fit content [duplicate]

In my story board I have a UITableView with dynamically generated UITableViewCells. Each cell contains 2 labels and 1 text view:
I have a code that adjust the size of the textfield to the amount of text:
let fixedWidth = cell.myComment.frame.size.width
cell.myComment.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
let newSize = cell.myComment.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = cell.myComment.frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
cell.myComment.frame = newFrame;
and it works fine, when I set a background color of my textView to red I see:
and the cell itself - I'm setting the size in here:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
if indexPath.row == 0 {
return 100//this is my static cell
}
else {
return 117; //for now it's hardcoded - how can I set this value dynamically based on content?
}
}
So as I wrote in the comment above - how can I set the height of the cell dynamically based on the amount of text in the text view?
The key to getting self-sizing table cells (autolayout-based, which I recommend) is as follows:
Add your subviews to the contentView of the UITableViewCell
Provide constraints between your subviews and the contentView such that your subviews reach all edges of the table cell. In your case, this probably means aligning the leading, trailing, top, and bottom edges of your UITextView to the corresponding edges of the contentView.
Set the row height to UITableViewAutomaticDimension instead of a hardcoded CGFloat.
Somewhere in your controller, provide an estimation of the height with tableView.estimatedRowHeight = x (a hard coded constant is fine, this is for performance).

Automatically adjust width of a view based NSTableView based on content

Title should read: Automatically adjust width of the containing NSWindow of a view based NSTableView based on NSTableCellView's NSTextField content intrinsic content size.
A bit like this other question, I would like to implement an autocompletion NSWindow with an NSTableView inside it that adjust to the width of the length of the available autocompletions implemented as NSTextField inside an NSTableCellView. Each autocompletion should obviously be displayed on one line...
The previous question has been answered but was only related to the hight of the NSTableView. I would like to know how to do the "same" for the width. I would like to implement the solution as much as possible using auto layout.
I've tried to set the horizontal "Content Hugging Priority" and the "Content Compression Resistance Priority" to the maximum of 1000 for each view element participating in the final display of the NSWindow. I was thinking that the intrinsic content size of the NSTextField would force all other elements to adjust but it does not work.
Setting the NSTableColumn width does not work either since the NSClipView of the NSScrollView is not modified by this width: the NSScrollView adjusts and creates horizontal scroll bars to cover the entire "document".
Here is a link to a sample project to demonstrate the problem:
sample project
Any help would be greatly appreciated!
I fixed the problem using this code with the scrollViewWidthConstraint being an IBOutlet to the NSScrollView width constraint, localTableView being an IBOutlet to the NSTableView and tableColumn being an IBOutlet to the NSTableColumn (the only one in my case).
Note: The linked project on GitHub has been updated with the changes.
override func viewDidLoad() {
super.viewDidLoad()
self.updateTable()
}
func updateTable() {
localTableView.reloadData()
var computedWidth: CGFloat = 0
for var row = 0; row < 10; row++ {
let tableCellView = self.tableView(localTableView, viewForTableColumn: tableColumn, row: row) as! NSTableCellView
computedWidth = max(computedWidth, tableCellView.textField!.intrinsicContentSize.width)
}
scrollViewWidthConstraint!.constant = computedWidth
scrollView.needsUpdateConstraints = true
}