UITableViewCell layoutSubViews: why don't I get animation? - ios

I always thought that whatever changes I perform in layoutSubViews: is done animated?
Is this incorrect information?
In my case I'm inheriting from a UITableViewCell.
The controller gets informed that the user wants to enlarge the cells, so I first use a UITableView animation block to increase row height. The height increases smoothly animated to the new height.
Then I loop my visible cells, set a flag and call setNeedsLayout:
The cells indeed layout and adust the content to the new height but without animation.

No, that is not correct, the default approach for layoutSubviews will not be performed animated, it is up to you to begin / commit an animation block or use the blocks animation feature.

Related

Animate UICollectionView contentInset adjustment

Is there any way to animate the invalidateLayout() call on a UICollectionView layout? I have a collectionView with a custom layout, and a view that is animating on top of that collectionView. I would like to animate the repositioning of the cells in the collection view (much like a default UIScrollView implementation would do), but calling invalidateLayout() during an animation block repositions the cells with a fade animation, rather than an interpolation of the frames.
Is there any way to dictate the type of animation used in the layout change?
I finally found the answer, and hope this helps someone else. The trick was simply to call collectionView.performBatchUpdtes(nil, completion: nil) inside the animation block.

very tall cell in UITableView cause very slow scroll performance

I have a very tall cell with massive text content in it. Reveal shows it's height is 7000+. When scroll during that cell(it's so tall that will take a while) the tableView's scroll performance is particularly bad.
After Time profiler the tableView scroll. It shows the drawRect: method of one of subviews cost the most. That subview is a third party custom textView. I breakpoint the drawRect: method the backtrace like so:
And it turns out the drawRect: is called many times when scroll during that very tall cell. So what cause the drawRect: is called during scroll inside one cell??
Having a quick look at the custom text view you linked, it looks like -setNeedsDisplayInRect: is called whenever the text view frame or bounds is set, and on touch events.
Looks it's the UIResponder touch methods that are the culprit, in which case setting userInteractionEnabled to NO on the SETextView should solve the problem. Of course, you may well want to keep interactions enabled on the text view, but I'm sure you can come up with something!

How to distinguish reason for UICollectionViewLayout's prepareLayout (iOS6)?

AFAIK, the reason that cause UICollectionViewLayout restart layout process are:
UICollectionView's frame change
UICollectionView reload data
UICollectionView insert/delete items
UICollectionView's bound change (if shouldInvalidateLayoutForBoundsChange return YES)
In my custom layout implementation, I want to change the UICollectionViewLayoutAttributes of certain items as the bound changes (stick header to the top like UITableView, animate item in/out .etc).
Problem is that for whatever reason it is, the UICollectionView always call its layout object's prepareLayout method (which contains heavy layout computation) and that make jerky scrolling.
I'm going for the solution that opt out the layout computation if the reason is UICollectionView's bound change.
How to check what reason the prepareLayout call?
I set a flag in shouldInvalidateLayoutForBoundsChange: so I know not to recalculate everything when that happens (on every frame...).
You can set another flag when prepareForAnimatedBoundsChange: is called, which happens when new items are inserted or when the bounds of the collection view change. You can then know if the bounds were changed because of scrolling or because of resize thanks to the flag you set in shouldInvalidateLayoutForBoundsChange:.
However, you should not have to worry too much of why you have to prepare the layout, since you should recalculate it fully in most cases anyways. In my project the only case where I do something differently in prepareLayout is when the invalidation was caused by scrolling.

Timing child view layout with UICollectionView layout changes

I have a UICollectionView that has a custom layout that changes the sizes of its cells when the device rotates. When the layout changes the size of a cell, layoutSubviews is called on each cell. This is what I want. However layoutSubviews does not execute in an animated manner but the change in size of the cell does. I would like to synchronize the two changes.
For example right now if the cell gets larger, the subviews resize instantly and then the cell size animates its change. I don't think I should put animation code in layoutSubviews. Is that correct? What is the best way to handle this?

Resized UITableView's cells' frames are not updated

I have a UITableView that I resize when the keyboard shows.
// MonoTouch code
// Resize the table so it's not hidden by the keyboard
var keyboardFrame = UIKeyboard.BoundsFromNotification(notification);
var tableFrame = myTable.Frame;
tableFrame.Height = theView.Frame.Height - keyboardFrame.Height;
myTable.Frame = tableFrame;
// Bring the current cell back in view
this.InvokeOnMainThread(()=>{
if(currentCell != null) myTable.ScrollRectToVisible(currentCell.Cell.Frame, true);
});
However, when I try to perform an action on that cell that is sensitive to that cell's current position on the screen (such as attaching a UIPopoverController), I find that the frame of that cell is showing the original location prior to the table resize and scrolling.
I've tried the following all yielding the same results of the frame still pointing to the old location (a lot of these were experimenting to see if they did anything not knowing what would work and what wouldn't):
Using SetNeedsLayout on the cell, the subviews of the table, the table.
Using LayoutIfNeeded on the cell, the subviews of the table, the table and the view containing the table
Multiple combinations of SetNeedsLayout and LayoutIfNeeded
Spawning a new thread, sleeping on that thread for a ridiculous amount of time (to allow time for the UI to perform a redraw/update/whatever) and then looking at the Frame
Spawning a new thread, sleeping for that ridiculous amount of time and then calling the different layout functions
I'm not certain if it's the resize or the scrolling that is where the breakdown is happening.
When you scroll the table using a gesture, the cell frames seem to be updated properly because I can always show a popover view in the correct location relative to that cell I'm attaching it to. So I don't understand why resizing the table and scrolling it programmatically wouldn't do the same.
Does anyone know how to force a UITableView to update it's cells' frames without doing a ReloadData (ReloadData causes many unwanted effects in this case)?
This is behavior is expected. The UITableView inherits from UIScrollView. The UIScrollView, apart from its frame, has another property, ContentSize. The two are separate. While the frame represents the position and size in relation to its parent view, the ContentSize defines the area of the content of the scroll view, so that the object will "know" by what amount to scroll each time.
Changing the frame or bounds of the UITableView, or any view for that matter, does not necessarily change the frame(s) of its subviews. This behavior depends on the superview's ContentMode property.
Anyway, the table cell's frames do not change, because they are relevant to the ContentSize property. Since it is working correctly before resizing the table view, I can only assume that the ContentSize and Frame of the table view match at that point. After resizing the table view, the ContentSize remains intact so you have inconsistency between the two values.
Instead, you should use either the ConvertRectToView or ConvertRectFromView methods to get the rectangle of the cell in relation to the tableview's frame.

Resources