Unable to resize an UITableViewCell containing an UIView - ios

I have a custom table view cell. I have a UIView in the tableview cell that is shown only when the table is expanded. I toggle the height for table view cell each time on tap to show the UIView. I also need to detect clicks on some of the components of UIView.
->tablecell1
-->UIView1 height h1
->tablecell2
-->UIView2 height h2
The cell height of the cell should vary according to the size of UIView. Currently I am calling
tableView:heightForRowAtIndexPath: for varying the height on cell click. However this doesn't work if the UIViews are of variable heights and the bigger view gets clipped.
Is there a better way of solving it?

Ok so real quick tableView:heightForRowAtIndexPath: shall not be called by your controller.
The biggest problem I always run into when dynamically sizing cells is that that heightForRowAtIndexPath is called very early on in the table layout process, so essentially the height of each cell must be know prior to asking the tableview to layout. Anyway I am going to assume that you are using a custom table view cell and have placed a UIView inside there... If you haven't, do.
First: Throw a class function into the CustomTableViewCell called heightNeededForTableViewCellWithView:(UIView *)view and determine the height you would want, handle the condition where view is nil and what the default size shall be.
Second: Call this class function when tableView:heightForRowAtIndexPath: is called and since you own the datasource in your controller you can dynamically return the heightNeededForTableViewCellWithView:viewAtRow based off the view you would want to show for that row!
Third: When a user taps a cell, remember which index they tapped and call [tableView reloadData] which will call tableView:heightForRowAtIndexPath:

Related

Dynamically update uicollectionview cell height

I am working on a quite complicated case
I have a nested UICollectionView
The outer UICollectionView A is for vertical scrolling,
and it's the first cell, is UICollectionView B, for horizontal scrolling.
It has been implemented perfectly, but now there is one more requirement
When scrolling the first cell to the second page, there is one more banner appeared on the bottom of the first cell.
Therefore I need to update the height of cell when scrolling.
If I try to call invalid layout when scrolling, it will be very low efficient. Are there any more methods to support it?
Solved.
First after received the data from the server, each cell height will be calculated and [collectionview reload] will be called.
Then after layouting the collectionview, the size for each cell is cached according to the indexpath.
To implement the 'realtime' resizing, the gesture will call a resizing function directing through a delegate, and directly modify the size cache and call [collectionview.layout invalidlayout].
It looks smooth.

iOS (Swift) - How to change any graphic (layout, size of UIView and etc.) in reusable UITableViewCell

The situation is pretty simple (as pretty common as I thought). I have an UITableView in my application that has lets say 3 rows (all are visible on the screen). Next I tap on one of them and this action changes something in all three cells (e.g. change scale of some UIView that is in this every cell) and everything is ok.
This is ok until I have only visible cells on the screen. I know that cellForRowAtIndexPath works only for visible cells. So how can we change such kind of properties (not data properties) for all the cells?
cellForRowAtIndexPath is where you prepare the cell for display. You should be doing the changes in here.
How are you modifying the view scale inside the cells when the user taps on a cell?
You should be triggering a reloadData() on the tableview which will reload the tableview and trigger the cellForRowAtIndexPath calls. You can also reload specific indexes inside the tableview if needed.
Inside your cellForRowAtIndexPath you should use some logic or state variable to control how you configure your cell. Dont dump all the code inside that function, pass arguments to your cell in a function e.g configureCell(subviewScale: CGFloat) and let the cell configure itself.
Dont forget to reset the scale of the subview in prepareForReuse() on your custom cell so that when the cell is about to be dequeued and reused, it gets its properties reset.

How to dynamically resize UITableViewCell based on UITableView scrolling?

I have tried looking for an answer to this question but so far I haven't got any luck.
Context
I have a UITableView inside a standard UIViewController (NOT a UITableViewController..). I have subclassed UITableViewCell and all the cells in the tableview are from the same class.
Requirement
I would like to find an efficient way to resize the cells based on the scrolling of the tableview. For example, when the cell is at the bottom of the visible list, the height is X. When the cell moves up on the screen, its height should proportionally increase to 2X.
Additional Info
I am close to just ditch the UITableView way and start making my own control that would implement such a feat by subclassing a UIScrollView. However, I would like to see if it is possible before going this path. I did see some very interesting SO posts but nothing that would put me on the right path.
Any hint or help would be highly appreciated.
You would need to respond to the scroll view delegate method scrollViewDidScroll: and implement it to record the cell at the top of the table view and reload the table view. Then your table view delegate method tableView:heightForRowAtIndexPath: sets the cell height by the relationship between the index path and the top cell index path.
Your main issue is performance while reloading the table view all the time.
If you wanted to roll your own solution it would be along the lines of the above description anyway, but you would be able to be more efficient than the table view as the table view will call the tableView:heightForRowAtIndexPath: method once for every row for every reload in order to calculate the total height of the table content.

UITableViewCell frame height not matching tableView:heightForRowAtIndexPath:

I'm constructing a UITableView with variable height custom table cells, their height determined by the size of a contained multi-line UILabel. I've got the tableView:heightForRowAtIndexPath: delegate method wired up and calculating the final height correctly using sizeWithFont:constrainedToSize:.
I've run across strange issue: by the time the data source method tableView:cellForRowAtIndexPath: is called, the correct per-row height has already been determined as described above, but the frame of the cell does not match that height. Instead, the frame.size.height property of the cell is the default cell height of the table view (86 px, as I've set it in Interface Builder, the correct height when the contained UILabel has just one line of text), instead of being the height that tableView:heightForRowAtIndexPath: determined correct for that index path.
I'm producing the cells in cellForRowAtIndexPath: using dequeuing, that is,
// Using storyboards, this never returns nil, no need to check for it
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:#"SomeIdentifier"];
NSLog(#"%f", cell.frame.size.height); // 86, not correct if the cell contains a multi-line UILabel
It seems, then, that whatever iOS is doing behind the scenes, the dequeuing is not setting the frame property of the cell to match the calculated height. This in itself is not that surprising, dequeuing concerns itself with cell instances, not their geometry. The cells are rendered correctly, though, so the height property is being set somewhere, but it happens after cellForRowAtIndexPath:.
So: when I initially populate the table view, cell.frame.size.height is 86 for all the cells as they appear for the first time when I scroll the list downwards. Since the correct geometry is set sometime after the first cellForRowAtIndexPath: for each row before it's displayed, when I scroll back up, the height property is correct for each cell that comes back into view after being reused.
After this I can scroll the table view back and forth at will, and the height property remains correct for each cell from that point on.
What's the correct way of getting the correct cell height the first time around, before any dequeue-based reuse happens? I need this to do a bit of re-positioning of the subviews of the table cell. Do I need to manually call heightForRowAtIndexPath: in cellForRowAtIndexPath: and then manually set the frame of the freshly created CustomCell instance to match that height? This seems redundant, and I'd need to create a mechanism to detect when the cell is created for the first time with the wrong frame height vs. when it is dequeued with the correct frame height later to avoid this redundancy.
So, if someone can shed some light into what the logic is behind this, I'd appreciate it.
As suggested by Flexo, answering this myself is apparently better than adding an edit to the question. So, here's the previous edit as an answer:
Nevermind, I should read the docs better. I can get the correct frame in the tableView:willDisplayCell:forRowAtIndexPath: method of UITableViewDelegate, so that is the correct place to do subview customization that relies on the correct frame being set, not cellForRowAtIndexPath:.
Interesting that the docs say this, though:
After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.
...since the correct frame is already there when this delegate method is called. But anyway, problem solved.
Don't forget that the cell is a UIView, so overriding layoutSubviews is also a valid way to get the correct frame and adjust size/position of subviews. Just don't forget to call [super layoutSubviews].
Easiest way I found was just to call cell.layoutIfNeeded() before you do any setup on the cell. This makes sure all the layout constraints are calculated and the frames are set.

Can the height of a UITableViewCell be changed without reloading the table view?

I'm trying to resize a UITableViewCell without reloading the table view.
My UITableViewCell contains a UITextView so users can input list items that may be several lines (about four max) in length. Right now, I'm resizing the text view each time the user presses the return key, but I'd like to change the height of the table view cell as well.
The main problem I'm running into is that reloading the table view's data makes the text view lose focus. Is there any way to change the height of the UITableViewCell without reloading the table view, letting the user continue to input text in the text view?
To resize a table view row, try sending:
[tableView beginUpdates];
[tableView endUpdates];
These messages one immediately after the other should do the trick provided you have the correct height returned for that cell in the tableView:heightForRowAtIndexPath: method. The row should animate. You should be able to return the height of your cell using its bounds or just from knowing what you've set the cell height as.
Obviously "tableView" is the name of your table view.

Resources