Using drawRect stretches during orientation change - iphone

I have a tableView. Instead of having multiple subviews in each tableViewCell , i have added one main subview which draws each of the other subviews in its drawRect method.
(I have read somewhere that this makes scroll animation look better. Also apple has a sample project CustomTableViewCell).
First , problem is when i changes the orientation of device, then drawRect does not call automatically. And each tableviewcell appears to be stretced.
I solved this by using
mainView.contentMode = UIViewContentModeRedraw
This solves the problem. Now when the orientation change is done, drawRect is called automatically .
But during the orientation change, the animation of rotating view still shows each tableview cell stretched. It is a very small thing, but still it is noticeable. Can anyone suggest something on this ?????

You can't redraw during animation (not easily, anyway).
Split the table cell into components again and setup autoresizing correctly. The animation will then animate only component positions and it will look fine.
Where did you read drawRect: would make scroll animation better? Did you have some problems with scrolling animation?
Edit:
IMHO There is no way how to fix resizing animations and keep the performance increase from using drawRect: instead of subviews.

Related

Animate UIView setFrame to force drawRect on each animatable frame

I've got a UIView with a UILabel on top. I have the UILabel's content mode set to 'UIContentModeLeft'. As expected, when I animate the frame of the UIView to be smaller than the original size, the label 'jumps' to the final frame without animating nicely.
As far as I can see, UIContentModeRedraw does not force 'drawRect' to be called on every 'animated frame'. I've tried using a custom CALayer as well but can't seem to cause the frame to resize smoothly.
Is there any way to do this? The animation as it stands is extremely glitchy. UIContentModes are not useful and I can't use a frame for contentStretch as well as none of the edges of the label can be stretched. What I really need is a 'refresh' of the label every time the parent view resizes.
There's no way of doing this unfortunately, so I've learnt. The only other way is to actually run a timer that updates the frame every time it's invoked. This results in a very jerky animation given a resize of a complex view is time consuming. I ended up achieving the same thing with some pre-rendered onscreen elements and a whole lotta 'magical effects' behind the scene.

Why does animating a subview cause its parent view's layoutSubviews method to be called?

I'm doing UIView animation on individual subviews that have a number of sibling views that I don't want affected by the single-view animation. However layoutSubviews is being called on the containing superview when I do the animation, causing the other siblings to be rearranged as well.
(I should explain that I'm doing initial subview layout in the parent view's layoutSubviews method; I only want it to be called the first time I'm setting up the subviews, not when I'm animating them individually later on.)
Why is the parent view's layoutSubviews method being called when animating its subviews?
I can imagine "sorting a grid of icons", you'll just have to animate one icon and the rest works automatically.
On the other side: What autoresizing masks do you have set for the view you're animating? Perhaps it has to do with that. What type of UIView are you animating? Perhaps it changes shape and thus calls [self.superview setNeedsLayout] to tell the superview that it changed shape.
Other idea: Has your superview "autoresizedSubviews" set?
I've found that even setting transformations on the layers of a view can trigger the view's setLayoutSubviews. It took me by surprise too, but maybe just because I don't need the behavior right now. It might sometimes become handy, I guess…

How do I properly handle rotation of a UIScrollView containing UIImageViews?

I'm developing an image viewer, much like the Photos App.
It's a UIScrollView with paging enabled with images loaded from the internet, so I've adapted portions of the LazyTableImages sample. The Scroll View and each ImageView inside of it have all of their autoresize mask flags set.
When I first observed how resizes were happening during rotation, it looked good, but once I started trying to interact with the scroll view, I realized that I also had to programmatically change the size of the contentView. I did that by implementing didRotateFromInterfaceOrientation: in my view controller.
[self.scrollView setContentSize:CGSizeMake(numberOfImages * portraitWidth, [scrollView bounds].size.height)];
With interaction behaving properly, I then discovered that, if I was viewing the second photo and rotated, portions of both the 1st and 2nd photos would be shown on the screen. I needed to change the contentOffset as well.
I've tried to fix this two ways - both by using the scrollRectToVisible:animated: method of UIScrollView, as well as trying to set the contentOffset property directly. And I've experimented by putting this code in implementations of both the "one-step" and "two-step" responses to changes in Orientation. For example:
-(void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
[self.scrollView setContentOffset:CGPointMake(currentlyViewedPhotoIndex * largeImageHeight,0) animated:YES];
In all cases though, it just looks janky as hell. Either I clearly see the scroll happen, or it just jumps. Uuuuuuuuuuugly! Is there a way to do this so that it behaves exactly like the Photos app does?
What I wound up doing instead - just before rotation starts, hide the UIScrollView and create a UIImageView that contains the currently viewed image. Rotate, that image will rotate all nice and pretty, and when rotation completes remove the ImageView and unhide the Scroll View.
Update - if you're reading this today (anytime after iOS 6), use a UIPageViewController and set transitionStyle to UIPageViewControllerTransitionStyleScroll, for crissakes.
I did something slightly different when faced with the same problem. In willRotateToInterfaceOrientation:duration:, I hide all of the UIScrollView's subviews except for the currently displayed subview, and in didRotateFromInterfaceOrientation: I unhide the subviews.

Subclassing UIScrollView for drawing w/o views

I'm contemplating subclassing UIScrollView (the way UITextView does) to draw a fairly large amount of text (formatted in ways that NSTextView can't).
So far the view won't actually scroll. I'm setting contentSize, and when I drag, I see the scroll indicator. But nothing changes (and I don't get a drawRect: message).
An alternate approach is to use a child view, and I've done this. The view can be over 5000 pixels high, however, and I'm a bit concerned about performance on an actual device.
(The other approach, be like UITableView, would be a huge pain -- I'm "porting" Mac Cocoa code, and a collection of views would be a huge architecture change.)
I've done some searching, but haven't found anyone who is using UIScrollView to do the drawing. Has anyone done this and know of any pitfalls?
All that UIScrollView does when the user scrolls is update its bounds rectangle, which causes the scroll views subviews to move. You could try setting the scroll view's contentMode to UIViewContentModeRedraw. From the docs:
UIViewContentModeRedraw
Redisplays the view when the bounds change by invoking the setNeedsDisplay method.

Is Core Animation causing my subviews to call -drawRect for every single frame?

I made a nice UIView subclass which paints all its stuff in -drawRect:, because people said that's good. That view is a subview of another. This another view is beeing animated with Core Animation: It's scaled down, rotated and moved. However, I encountered this: -drawRect seems to get called trillion of times during animation, and performance sucks.
Is that normal or did I do something wrong, probably?
And I have found this in the documentation of UITableViewCell, which is strange:
However, drawing in editing mode is
not encouraged because, as you might
recall, custom drawing while cells
animate into and out of editing mode
severely affects performance.
So -drawRect: is very very bad when doing any core animation thing? I also remember from some other apple resource, that they "don't redraw during animation". Paradoxon. Again.
If your UIView's contentMode is set to UIViewContentModeRedraw then, according to the documentation setNeedsDisplay will be called whenever the bounds change. I'm not sure if this would be true during animation, however (I was under the impression the animation system behaved differently) but could explain the flurry of calls to drawRect.
drawRect: should only be called after setNeedsDisplay: YES is called on your view. I'm guessing that as the scaling is happening your view is being asked to redraw. If the scaling, rotating, and moving is part of a transition you may be able to perform the transition on a cached view.