I have a table view controller with a prototype cell with style "Left Detail."
-In my viewDidLoad() I have self.tableView.estimatedRowHeight = 40 and self.tableView.rowHeight = UITableViewAutomaticDimension like many solutions have said to do. However, when my detail label gets too big (like with the description cell), the cell doesn't grow with the text.
-I tried to reload the data in viewDidAppear(animated:) as well, but that didn't help.
-I don't have anything in my heightForRowAtIndex func right now, but have tried to set that too and it didn't fix my problem.
-I also tried cell.sizeToFit() in my cellForRowAtIndexPath after the cells are populated.
Am I missing something obvious? Or is there something in the "Left Detail" style that is restricting the cell height?
You're not missing anything obvious that I'm aware of, but likely running into an edge case involving the built-in cell style. There are a small number of issues with self-sizing where it mostly works for the built-in styles but can fail for certain cases.
This is a side-effect of how the built-in styles manage their labels and constraints differently from how it would be done for a custom cell style. If you examine the built-in cell's content view in the debugger, its constraints array is empty.
For one edge case, if one of the built-in labels was not needed for a cell, Apple optimizes it by completely removing that view from the cell. When that cell gets reused and the label needs to be added back in, the constraints don't get updated for that initial occurrence. It was possible to work around that particular issue by ensuring that both labels always have text, so the view never was removed.
You definitely should not need to include heightForRowAtIndexPath. You should remove that, then see if you can work around the built-in style issue within cellForRowAtIndexPath. If not, you may have to use a custom cell which mimics the Left Detail style.
Either way, I'd recommend submitting a bug report with a small sample project that illustrates that "Left Detail" issue, as Apple has fixed many of these issues and built-in style self-sizing has been far more usable.
Related
Nowadays fortunately it's trivial to have an iOS table where every cell has a dynamic height. So in the cell vertical constraints ..
---- top of content view
- vertical constraint to
-- UILabel, with, .lines set to zero
- vertical constraint to
---- bottom of content view
Assume the UILabel texts vary greatly one word, 20 words, 100 words,
In the table set
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 200 // say
and you're done, these days it works perfectly of course.
However, I had the common situation where you load the table, imagine ten cells.
I populate the UILabel with "Loading..."
Only then - say, a second or two later - do we get the information for the text content. It arrives say a second later and the cell changes the text to "Some long text .. with many lines".
In fact I was surprised to learn it seems UITableView does NOT handle this. The cell in question gets stuck on the original short height.
So, after the larger text is set, I tried all permutations of the usual:
maintext.sizeToFit()
contentView.layoutSubviews()
contentView.layoutIfNeeded()
on the cell, doesn't work.
I tried sending a setNeedsLayout and/or layoutIfNeeded to the table itself, doesn't work.
I thought about .reloadData() on the table itself but - doh - that would again trigger the content being drawn from the server and loaded again, so that's not ideal.
Please note that:
Obviously there are any number of workarounds for the specific example such as not using dynamic data
I am completely aware how to manually animate the height of one cell (like when you "expand" one to show something else when the user taps)
This question is about autolayout and table view - which, thanks Apple, nowadays flawlessly handles completely dynamic cell heights involving UILabels with lines zero.
But what about if the text in such a label changes?
It seems that the table view system does NOT handle this.
Surely there's a way?
When the content of a cell changes the layout (in this case, the height) you must inform the table view that the layout has changed.
This is commonly done with either:
tableView.beginUpdates()
tableView.endUpdates()
or:
tableView.performBatchUpdates(_:completion:)
Why is that not triggered automatically?
I suppose it could be to allow you to do your own animation, or you may want to delay the update, or some other reason that doesn't come to mind at the moment.
Or, it may be due to maintaining backward compatibility?
I don't know. I imagine Apple could tell us...
.
Hello, everyone!
So, I made a Custom Layout for my UICollectionView.
This Custom Layout has support for dynamic cell sizing (just the width of the cell is changed).
Also, the UICollectionView has drag 'n drop to the user be able to reorder the cells.
With the dynamic cell size off, the reorder works without any problem (GIF)
With the dynamic cell size on, the reorder has some issues during the dragging animation (like this).
The example project is in this Github repository:
https://github.com/rgipd/uicollectionview-reorder-error
The Github's README.md file has all the errors listed as well.
I already read some blog and answers, like this one:
https://nshint.github.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/
Also, I did implement the invalidationContextForInteractivelyMovingItems... method, but, even with the NSHint example (that you can download) in the article, when you drag a small cell to occupy the space of larger cell, some cells are replaced and errors appears! Also, the cells stay swapping with cursor at middle because the hard-coded call to moveAt method (probably).
The problem in the article's author example is in the Github repository's Wiki:
https://github.com/rgipd/uicollectionview-reorder-error/wiki/NSHint-reorder-collection-view-error
Anyone can help me out with this issue?
Thanks in advance!
UPDATE: 28 July 2020
Nothing new. Can't do it with simple horizontal UICollectionView Custom Layout as well.
I want to add something like what’s in the app store app:
As you can see, it isn’t just one cell that is paged, but you can also see the two edges of the cells from the left and right as well. I tried to implement this in my app by making each cell slightly smaller than the size of the collectionView, and then enabled isPagingEnabled, but when I flipped from cell to cell, it didn’t page from cell to cell, rather the width of the entire UICollectionView every time. This ended up in an unwanted effect where each page turned resulted in an increasing offset where cells were shifting further and further off the screen.
I researched a bit on this and implemented the targetContentOffset(forProposedContentOffset... but it was never called and didn’t work.
Preferably, I would want to keep the smooth behavior of the built-in pagination and just be able to tweak it.
Thanks!
Instead of implementing the peeking behavior yourself delegate it to a third party library iCourasel. Implementing it yourself you will ended up a UICollectionView inside of UITableViewCell. As of your requirement iCarouselTypeLinear suits your requirement.
I'm building something similar to the compose page of the native iPhone Mail app.
But, I'm putting two text fields on one row, and I want to separate them with a vertical divider (an additional view) that's the same color & weight as the horizontal cell separators.
Apple's docs say:
If you want to customize cells by simply adding additional views, you should add them to the content view so they will be positioned appropriately as the cell transitions into and out of editing mode.
But, what if I know, like in this case, that my cell will never go into editing mode?
Also, the horizontal cell separators are subviews of the cell, not the cell's content view. So, I think it'd also make sense if I added the vertical divider to the cell, not the cell's content view.
Can I just add additional views to the cell itself, instead of its content view?
You can add additional views directly to the cell, but it's best practice to add them to the cell's content view. Even if you're cells never go into editing mode, this is what Apple and other developers that may be working on your code (or you in the future) are expecting. So, this will make it easier for them to work with your app.
For example, what if Apple hypothetically decided to put gutters on the left & right side of plain style table views in a future release of iOS? Then, they would probably inset the cell's content view but not the cell itself. That way, if you position your additional views relative to the content view, your app has a better chance of looking good and the additional views have a better chance of not getting clipped by Apple's hypothetical gutters. OK, I doubt Apple would do such a thing, but the point is that if you add your additional views to the cell's content view instead of the cell itself, you're code will be more robust.
For your specific case, I still recommend adding the vertical divider to the cell's content view because you can. You might even consider setting the tableView.separatorStyle = UITableViewCellSeparatorStyleNone and redrawing custom separators by adding a separator view to the bottom of each of your cells' content views. This way, you can be sure that the style of the vertical divider you add will always match that of the separators. Again, this will make your code more robust and protect you if Apple decides to change the style of their separators. Sure, you can use cell.separatorColor. And, you can guess the separator weight with cell.frame.size.height - cell.contentView.frame.size.height. But, such cleverness might get you in trouble.
As the Buddha admonishes Siddhartha, "Beware of too much cleverness!"
I've been searching through here and googling like crazy for a possible solution to this problem. Thus far I'm turning up exactly nothing that actually fixes it so I'm hoping someone can help.
I'm working on the UI for a iPad app. I'm doing it using interface builder. I worked with storyboards briefly but I don't like them all that much so I'm sticking with IB for now. Unfortunately I'm not very experienced with the workings of IOS Ui but it's been going relatively smoothly so far. In my app, I have a view controller, which holds a view containing a pair of sub views. One subview contains a rather windows like header bar (i like the look). The second contains a UITableView. The UITableView is set up properly as far as I can tell, and feeds it's info from a data source using custom UITableViewCells. The UITableView is set to grouped though currently there is only one section. The table is in edit mode by default because I want the user to be able to add new items and use the VC as a selection dialog. The view controller is presented (rather than pushed) using UIModalPresentationFormSheet (again, because I like the view) but I don't know that has any bearing on the problem. The cell border is flush with the X origin, the only reason the text isn't currently starting there is because I went into my cell and move the label over, leaving a gap between the edge of the cell and the label containing my text.
The Offending View http://bit.ly/144cbjT
The Problem: The UITableViewCells, for some reason are positioning themselves at X: 0. This puts them outside the border drawn on the UITablewView when you set it to grouped style. I could probably just turn off the border and get away with it, but I like the look so i want to keep it. I've tried messing around with constraints and anchor points on the cells, the content of the cells, the table itself, the view... I've tried simply moving my cell's labels over a bit. I've also had clipping subviews turned on and off. I've made sure the controls are being loaded properly from the XIB. I've made sure everything is added as a subview where needed. I've made sure I've tried everything I could think of short of setting the cell's X position in code. But since I'm not sure how to tell where the border is, I'd rather have the tableview or the cell do the work itself.
The question: How do I fix this? The selection accessory should be outside the grouping box. The text should be inside, not bleeding out onto the background like it is.I believe the content of the cell should be displayed inside the border within the yellow area.
The odd thing is, this is my fifth or sixth table in this app and I've been doing them all basically the same. Thus far this is the only one I've had trouble with.
Can anyone shed some light as to what's going on?
Thanks in advance
I think that to get this in code, you'd have to do something explicit, so the most likely candidate is a messed up IB file.
Since it doesn't cost anything, I'd just delete the tableView from the IB and then re-add it. If that doesn't work, try recreating the complete IB.
Hope that helps