Note that there are some explanatory texts on larger screens.

plurals
  1. POUIView block animation transitions with animated content on showing/hiding keyboard
    primarykey
    data
    text
    <p>In my app I have a text field on some view which is covered by the keyboard when it shows up. So I have to scroll the view (or even rearrange the subviews). To do this I:</p> <ol> <li><p>register for keyboard notifications:</p> <pre><code>[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moveViewUp) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moveViewDown) name:UIKeyboardWillHideNotification object:nil]; </code></pre></li> <li><p>upon receiving a notification, move the view using block animations like this:</p> <pre><code>- (void)moveViewUp { void (^animations)(void) = nil; oldViewFrame = self.view.frame; animations = ^{ CGRect newViewFrame = oldViewFrame; newViewFrame.origin.y -= kViewOffset; self.view.frame = newViewFrame; }; [UIView animateWithDuration:1.0 animations:animations]; } - (void)moveViewDown { void (^animations)(void) = nil; animations = ^{ self.view.frame = oldViewFrame; }; [UIView animateWithDuration:1.0 animations:animations]; } </code></pre></li> </ol> <p>This works fine, the view scrolls up and down, until I add some more animation. Specifically I'm adding a transition to a next view when the user taps a button:</p> <pre><code>- (IBAction)switchToNextView:(id)sender { // [self presentModalViewController:nextViewController animated:YES]; [UIView transitionFromView:self.view toView:self.nextView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight completion:nil]; } </code></pre> <p>Now we got to the problem.<br> If the first view was shifted when the button was tapped (that means that the keyboard was visible), the transition to the next view starts simultaneously as the keyboard slides down, but the view itself <strong>doesn't move down</strong>, so for a split second we can actually see the underlying view. That's not right. When I present the next view modally (see the commented line) all animations go as I want them to: i.e. the keyboard is hiding, the view is flipping from right <em>and</em> scrolling down -- all at the same time. This would be fine, but the problem is that I actually don't have a <code>UIViewController</code> for that view. In fact I'm trying to simulate the modal behavior without <code>UIViewController</code> (why so? <a href="https://stackoverflow.com/questions/5720130/present-login-screen-on-app-startup">perhaps it's just a bad design, I'll post another question on that</a>). </p> <p>So why does in this case the animation from <code>moveViewDown</code> method is not triggered at the proper time?</p> <h2>Update 1</h2> <p>I added a debug print to each function to check the order of calling, this is what I get:</p> <pre><code>-[KeyboardAnimationViewController moveViewUp] __-[KeyboardAnimationViewController moveViewUp]_block_invoke_1 &lt;-- scroll up animation -[KeyboardAnimationViewController switchToNextView:] -[KeyboardAnimationViewController moveViewDown] __-[KeyboardAnimationViewController moveViewDown]_block_invoke_1 &lt;-- scroll down animation </code></pre> <p>Even if I explicitly move the view down before the transition like this</p> <pre><code>- (IBAction)switchToNextView:(id)sender { // [self presentModalViewController:nextViewController animated:YES]; NSLog(@"%s", __PRETTY_FUNCTION__); if (self.view.frame.origin.x &lt; 0) [self moveViewDown]; [UIView transitionFromView:self.view toView:self.nextView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight completion:nil]; } </code></pre> <p>I get <em>exactly</em> the same log.</p> <h2>Update 2</h2> <p>I've experimented some more and made following conclusions:</p> <ol> <li>If I call <code>moveViewDown</code> or <code>resignFirstResponder:</code> explicitly, the animation is postponed until the end of current run loop, when all pending animations actually start to play. Though the animation block logs to the console immediately -- <strong>seems strange to me!</strong></li> <li>The method <code>transitionFromView:toView:duration:options:completion:</code> (perhaps <code>transitionWithView:duration:options:animations:completion:</code> too, didn't check this one) apparently makes a snapshot of the "from-view" and the "to-view" and creates an animation using these snapshots solely. Since the scrolling of the view is postponed, the snapshot is made when the view is still offset. The method somehow <strong>disregards even the <code>UIViewAnimationOptionAllowAnimatedContent</code> option</strong>.</li> <li>I managed to get the desired effect using any of <code>animateWithDuration: ... completion:</code> methods. These methods seems to <strong>disregard transition options</strong> like <code>UIViewAnimationOptionTransitionFlipFromRight</code>.</li> <li>The keyboard starts hiding (implicitly) and sends corresponding notification when <code>removeFromSuperview</code> is called.</li> </ol> <p>Please correct me if I'm wrong somewhere.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload