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

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.

Related

Only first collectionViewCell reacts to user interactions

The setup
I have a rather complex view hierarchy which made me do terrible things with tableViews and collectionViews. Right now I'm having a regular grouped TableView with custom TableCells. TableCell itself contains a couple of views and a Collection View. The height of the table cell is calculated based on number of items in the data source. On its creation table cell creates a collection view with a calculated size to fit necessary data.
-- UITableView
---- UITableViewCell
------ UICollectionView
--------- UICollectionViewCell
The problem
I've encountered unusual problem with a custom collectionViewCell. I have a vertical single-column collectionView with dynamic amount of cells. Ideally tapping on the cell should call didSelectItemAt. The cell also has three buttons. Tapping on the button should trigger some action. All of the desired functions work only for a first cell. The rest of the cells are not responsive to any actions.
Things that look strange
By default the scrolling of a collectionView inside of the tableViewCell is disabled because it basically fits all the content based on calculated height and doesn't require scrolling. (Also I don't want it to interfere with tableView scrolling logic).
First
I've tried to hardcode some value for the height of collectionView and enable scrolling. What happened is a mystery for me.
Let's say that calculated height required for the collectionView to show all the content without scrolling is 740. When I manually set it to be 280 (this is enough for exactly 2 cells to fit) and enabled scrolling my first cell were still working, but also when I scrolled collection just a little bit my second cell started to act normally as well. When I scrolled back to the top of the collectionView it was disabled once again.
So it looks like when the scrolling is enabled and will actually occur because of insufficient height to fit the content, cells behave as they should. As soon as I set height of the collectionView to be enough to fit its content, things go wrong.
Second
In some cases I can actually tap on the second cell and it will call the delegate. But the weird thing is it works when I tap in the top area of the cell, like 10pts from the top. The other areas of the cell are unresponsive so are the rest of the cells in the collection.
The working delegates and buttons with enabled scrolling forces to think that this has nothing to do with delayed or canceled touches. The frame for collectionView and height of the table cell are calculated properly as well.
xCode 8.3, iOS9+
As it turned out when I was creating my tableViewCell, I hardcoded the height of the collection to value of 214. The reason for that is very simple. I create a cell programmatically and with tableViewCells created programmatically the height of the cell is always 44. When you override init(style: UITableViewCellStyle, reuseIdentifier: String?)
You need to either hardcore the height, or update it in cellForRowAtIndexPath. Even though I updated collection frame when it was filled with data, the container view of this collection wasn't updated resulting in some sort of clipping area for user interactions.

Unable to resize an UITableViewCell containing an UIView

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:

Each cell with different layout in TableView, how is scroll optimised?

If I have a UITableView with each cell having a different layout. For example, cell 1 has one text field, cell two has two text fields and so on, in this case height of tableview cell varies based on how many text fields it has one below the other. For this specific scenario, will I be able to make use of reuseIndetifier and reuse the cell.
Is tableView reuseIdentifier useful only when layout of each cell is same? Or can I still reuse cells by making use of single identifier but adding textfields in cellForRowAtIndexPath dynamically?
I experimented a bit. I can do some basic reuse of cells by having a cell with empty template/blank cell. But in the cellForRowAtIndexPath I can dynamically create text fields and add. This works perfectly fine, allowing me to add as many number of views required to be added to TableView cell. I am using blank cell, which will be reused on scroll. However I am not sure that will be the impact on performance when I create and add UI elements dynamically to the cell in cellForRowAtIndexPath. Any ideas there?

Using a Custom UITableViewCell with Prototype Cells

For reference, this tutorial I am following: http://mobile.tutsplus.com/tutorials/iphone/customizing-uitableview-cell/
I have to create a custom UITableViewCell, and from the tutorial, it said to leverage Prototyping cells and subclass UITableViewCell. Then connect the UI elements in the prototype cel to the custom class (of UITableViewCell).
The problem I am running into here is, there is only one cell for the whole table view that is displaying data. However, I am able to click on empty cells in the background behind that one cell that contains data. If i scroll up or down, cellForRowAtIndexPath is called and another cell gets displayed. However its only displaying once cell at a time for the whole table view.
Does anyone know what the problem could be here? Any help is appreciated, thanks!
Figured out what the problem is, my labels (that are supposed to be inside the custom prototyping cell) were added to the parent view and not the content view of UITableViewCell. This is because my prototype cell did not have a content view for some reason. I had to add a another prototype cell and delete the previous one.
reference: How to add subviews to a custom UITableViewCell in a storyboard

Monotouch: Force UITableView to recalculate height of each cell without reloading data

I have a custom cell created using OwnerDrawnElement with autoresizeable UITextView in it.
When text changed there should be appropriate layout redraw and cell height recalculation.
The problem is how to preserve keyboard opened.
There is a method inside UITableView - ReloadRows which actually helped me in some fashion.
I can't call it for my cell because it is the first responder and can't I cant resign it.
But when I call it for another cell my cell is getting resized as I wanted but I have unnecessary another cell redraw.
So I wonder what method is called to relayout UITableView NOT reload data?!
The same method is probable called when you scroll up and down, cells become visible and height is recalculated.
I've tried standard SetNeedsDisplay(), SetNeedsLayout(), ReloadInputViews(), LayoutSubviews(), but it didn't do the same. Maybe I need use them somehow differently. I've tried to call them for cell and whole tableview objects.
I've looked into ReloadRows method and found out that it calls some API stuff:
Messaging.void_objc_msgSendSuper_IntPtr_int(base.SuperHandle, UITableView.selReloadRowsAtIndexPathsWithRowAnimation_, nSArray.Handle, (int)withRowAnimation);
So it doesn't what method forces tableview to recalculate height of each cell without reloading data either.
Can you help me with that?
Try to update cells frames, then call UITableView's empty update block:
tableView.BeginUpdates();
tableView.EndUpdates();

Resources