iPhone Autorotate: Replace rotation animation with fade-in/fade-out? - iphone

Someone else asked a similar question previously, but I am interested in knowing whether the autorotate feature of the iPhone SDK will allow us to replace the rotation animation with another transition, such as a fade-in/fade-out. For a modal view, we can set the modalTransitionStyle but there is no such property for autorotate.
If I can't leverage the built-in functionality, how else can I implement this functionality?

There's the willAnimateRotationToInterfaceOrientation:duration: method, from the docs:
The default implementation
of this method does nothing. If you
override this method, you should not
override either the
willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
or
willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
method.
This method is called from within the
animation block that is used to rotate
the view. You can override this method
and use it to configure additional
animations that should occur during
the view rotation. For example, you
could use it to adjust the zoom level
of your content, change the scroller
position, or modify other animatable
properties of your view.
I guess you can modify it from here, and before and after with – willRotateToInterfaceOrientation:duration: and – didRotateFromInterfaceOrientation:.
This seems inefficient and sub-par to me, as it does not actually replace the transition at all.
I would make a category on UIView, that includes methods such as -willRotateUsingTransition: and pass a parameter that will tell it to fade, then set the view's alpha to zero. In each subclass override this to include any subviews that need their alpha changed, if that is applicable. Call this method when the views are about to be rotated (with the methods above) and then a clean-up method that restore the alphas when they will appear again.
Edit: Docs Docs Docs. A quick look, again, reveals this method: - (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration, which I thought to be deprecated. As part of the discussion it has the text from the second paragraph I posted from the docs earlier.

I achieved something similar by attaching the auto-orientation behaviour to a hidden view, and responding the relevant events by implementing my own custom effect. It was quite fiddly, and I don't remember all the details, but I did manage to exercise complete control over the behaviour.
I should say, though, that in my case, I wanted to have control over how the rotation was implemented. I wanted the primary layout to remain fixed, while rotating several subviews in concert. I can't think of a good reason to completely replace the rotation with a fade-out-then-in; it'll just confuse users for no good reason. The only reason I can think of for using a fade effect is that you want to swap to a substantially different UI, but even then, there's no reason to suppress the rotation effect.

Related

Supporting both AutoLayout and traditional layout

I have a custom subclass of UIButton that I want to re-use in multiple projects, some of which use interface builder and storyboards, and some of which may not. It involves setting the button's frame in several places.
If I add
self.translatesAutoresizingMaskIntoConstraints = YES;
in the initialization, everything looks and works right, however, I get:
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
Will attempt to recover by breaking constraint…etc
logged to the console. However, if I set
self.translatesAutoresizingMaskIntoConstraints = NO;
none of the button sizing works and the button is completely broken.
Is there a way I can suppress the error since it seems to degrade to the right thing or can I somehow manually remove the offending constraint?
I've tried dumping the constrains after the button is initialized, however, it does not seem to contain the constraint AutoLayout ends up breaking.
Edited: Below are links to a sample project and then my button code. It works great when auto layout is turned off in the storyboard, however, when auto layout is turned on, the buttons seem to position at the origin (seems to be because when initWithCoder is called, the buttons don't have superviews or any position information).
http://www.kudit.com/dump/KFB.zip
http://www.kudit.com/dump/KuditConfirmButton.zip
Your guess is correct, in that when the buttons are initialized from the storyboard (using initWithCoder:) the frame is zero - this is expected for views using autolayout - frames don't get assigned until later on.
I have your sample project mostly working under autolayout by creating a boolean ivar called hasSetup, which get set to YES inside the setup method. The setup method doesn't run if the frame is zero. I also call it again from layoutSubviews. This gets around the not-working-when-using-autolayout in storyboard problem.
The various layers still aren't the correct size though. You may want to look into resizing them from layoutSubviews.
You also can't use setFrame under autolayout - you need to make sure any constraints on your view (like the sizing constraints from the storyboard) are adjusted instead. It's going to get quite messy dealing with both possibilities.
They look really good though - hope to see them on GitHub when you've sorted these problems.

How to create a custom UIViewController transition animation?

This question seems to get asked a lot but I have never found a definitive answer as to whether or not it's possible to have custom transitions the same way UIKit does.
I know you can do tricks like take a screenshot of the current view and the upcoming view, and then animate those while you change view controllers under the animation. However, this takes quite a bit of memory, as you have basically 2 full extra screens worth of drawing (because of the screenshots).
I'm looking for a more elegant way of presenting view controllers with a custom animation. Or, is there a more memory-efficient way of doing the above approach?
There are several ways to accomplish this, depending on how you want to transition, whether your controllers are embedded in a container controller, etc. In the simplest case, where you have a single controller, and you want to transition to another controller, you can do it with the following steps:
instantiate the new controller (lets call it B, and the original one A)
add B's view as a subview of the window (gotten from self.view.window)
set B's frame to be off screen in which ever direction you want or make its alpha 0, or make it have zero size, depending on what kind of transition you want.
do what ever transition you want with animateWithDuration:animations:completion:
remove A's view (in the completion block)
in the completion block, make B the root view controller of the window
Essentially you're having the system automatically retain and release, along with do whatever is happening below the calls rdelmar's answer outlined. Transitioning a view controller is just animating a view while having the system keep your controller in memory.
But, to answer more of your questions, UIView animations create duplicates and cache the images, too. (Btw, the system cache doesn't unload its memory, so avoid UIImage imageNamed.
You will probably want to code it yourself using a timer if you want efficiency, and drum up all the graphics tricks you can think of.
And never, ever trust iOS to work the same way it did the last version. Everything I said is subject to being wrong the same way iOS 6 broke retain on annotating, and the manuals stated iOS 3 animations will become obsolete (and are now replaced instead?) gah, just saying be careful with efficiency, it may be broken or updated in the somewhat distant future if you try it.

Using AFOpenFlow: adding subviews not just images

I am using the AFOpenFlow library to generate a coverflow-like effect, but trying to add arbitrary UIViews to an AFOpenflowView, not just images. I am doing this by creating a subclass of of AFItemView, lets call it NewAFItemView, which represents the view I want to add. I also extended AFOpenFlowView, call it NewAFOpenFlowView and overrode the method
-(AFItemView *)coverForIndex:(int)coverIndex;
In the overridden method, I allocate an NewAFItemView object and return it as the cover view for that index. The NewAFItemView views appear correctly in the open flow but scrolling is immediately disabled. Switching back to allocating AFItemViews works but using NewAFItemViews does not scroll.
I have not overridden any of the touch events.
Any ideas on what might be happening?
Cheers.
why don´t you use iCarousel?
https://github.com/nicklockwood/iCarousel
i use this, and it works perfect for uiviews =).

Dealing with drawRect multiple calls

I discovered that my drawRect is being called more than once. Unfortunately this had the unfortunate side-effect of double-drawing everything because all my subviews are drawn in drawRect (I'm s strict atheist w.r.t. Interface Builder).
What is the best way to deal with a multiple calls to drawrect? A flag to check if it's being called again? Or clear the whole view and redraw from scratch (as I have done?)
What do you mean by "your subviews are drawn in drawRect"? If you mean that you're putting calls to -addSubview: in your drawRect, don't. Move those to a more appropriate place that gets called only when it needs to (probably the -initWithFrame: method for your view if the subviews are always there), and use drawRect only to do custom drawing.
Strictly speaking, being called multiple times is the entire point of -drawRect. It's called to update small parts of your view when needed. It's actually called quite often if you're updating your view (moving it around, updating the superview, etc.), so it should be as simple and fast as possible to avoid performance problems.
When UIKit calls drawRect:, the graphics context set up to draw into should already be cleared for you (unless you have set the clearsContextBeforeDrawing property to NO). Are you perhaps calling drawRect: manually instead of calling setNeedsDisplay/setNeedsDisplayInRect:?
Also, each view is responsible for drawing only its own content and not the content of its subviews.

More than 1 button on the left side of a NavigationBar

Is it possible?
I have a UINavigationBar that I'd like to have an 'edit' button next to the 'back' button. From what I've read you can only have one or the other, which makes no sense as they are separate properties of the navigationItem object(backBarButtonItem and leftBarButtonItem).
I'm assuming you have to somehow insert a custom UIView into the UINavigationBar. I'm looking into this option and if no better solution is given then I'll outline this method.
The short answer is:
Yes, you have to add your own UIButton views (or other UIControl subclasses) to the navigation controller, yourself. So, ignore the custom *ButtonItem properties and roll it yourself.
A little more involved answer is:
Apple makes it very easy to follow their HIG guidelines, but you're on your own if you want to break them or customize. In this case, only one button is allowed, because the actual hit region is bigger than the size of the displayed button--much easier to hit from a usability standpoint.
Extraneous:
btw, there is a subtle distinction between left/rightBarButtonItem and backBarButtonItem. left/right is specified on the current UIViewController. However back is specified by the previous UIViewController.
Using a custom view is indeed your only option here. The UINavigationBar is not terribly flexible. What you will need to do is create a UIView that contains UIButtons. Be sure you realize that if you use a custom view, you gain none of the automatic behaviors of the backBarButtonItem; you have to create your own IBActions, and the graphics for the buttons as well.
On a related note, I'm not sure this is the best idea. It's usually wise to stick to Apple's UI guidelines; is there no where else you can put the edit button? The right side of the bar, for example?
While #Kelvin's answer works for pre iOS 5, if you're using iOS 5+ there is now a leftBarButtonItems array property. Note that you also must set leftItemsSupplementBackButton to true.