Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Synchronizing rotation animation between the keyboard and the attached view - Part 2
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification object:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
}
// called on iOS-7 and below on step: #1
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
self.animatingRotation = YES;
}
// called on iOS-7 and below on step: #3
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
// called on iOS-7 and below on step: #5
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
self.animatingRotation = NO;
}
// called on iOS-8 on step: #1
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// called on step: #2
self.animationDuration = [context transitionDuration];
self.animationCurve = [context completionCurve];
self.animatingRotation = YES;
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// called on step: #5
self.animatingRotation = NO;
}];
}
// called on iOS-7 and below on steps: #2, #4
// called on iOS-8 on steps: #3, #4, #6, #7
- (void)keyboardWillChangeFrame:(NSNotification*)notification {
[self adjustViewForKeyboardNotification:notification];
}
- (void)adjustViewForKeyboardNotification:(NSNotification *)notification {
NSDictionary *notificationInfo = [notification userInfo];
// Get the end frame of the keyboard in screen coordinates.
CGRect finalKeyboardFrame = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
// Convert the finalKeyboardFrame to view coordinates to take into account any rotation
// factors applied to the window’s contents as a result of interface orientation changes.
finalKeyboardFrame = [self.view convertRect:finalKeyboardFrame fromView:self.view.window];
if (!self.animatingRotation) {
// Get the animation curve and duration frp, keyboard notification info
UIViewAnimationCurve animationCurve = (UIViewAnimationCurve) [[notificationInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSTimeInterval animationDuration = [[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// On iOS8 if the animationDuration is 0,
// then the quicktype panel is being shown/hidden and the code executed here will be animated automatically
if (animationDuration == 0) {
[self adjustViewsForKeyboardFrame:finalKeyboardFrame];
} else {
[self adjustViewsForKeyboardFrame:finalKeyboardFrame withAnimationDuration:animationDuration animationCurve:animationCurve];
}
} else {
if ([UIView areAnimationsEnabled]) {
[self adjustViewsForKeyboardFrame:finalKeyboardFrame];
} else {
[UIView setAnimationsEnabled:YES];
[self adjustViewsForKeyboardFrame:finalKeyboardFrame withAnimationDuration:self.animationDuration animationCurve:self.animationCurve];
[UIView setAnimationsEnabled:NO];
}
}
}
- (void)adjustViewsForKeyboardFrame:(CGRect)keyboardFrame withAnimationDuration:(NSTimeInterval)animationDuration animationCurve:(UIViewAnimationCurve)animationCurve {
// Animate view synchronously with the appearance of the keyboard.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
[UIView setAnimationBeginsFromCurrentState:YES];
[self adjustViewsForKeyboardFrame:keyboardFrame];
[UIView commitAnimations];
}
- (void)adjustViewsForKeyboardFrame:(CGRect)keyboardFrame {
// Calculate new position of the view
CGRect frame = self.floatingView.frame;
frame.origin.y = frame.origin.y - frame.size.height;
self.floatingView.frame = frame;
// Update other related views, for example the height of a tableView
CGRect tableViewFrame = self.tableView.frame;
tableViewFrame.size.height = frame.origin.y;
self.tableView.frame = tableViewFrame;
}

Excellent work. This is really great. The comments really help explain how its working.

Doesn't work for me.
Keyboard will change frame event fires before viewWillTransitionToSize.
Trying to figure out what I am doing wrong.

Great blog post. Thanks for posting the code!

I think there is a typo on line 95:
frame.origin.y = frame.origin.y - frame.size.height;

should be
frame.origin.y = keyboardFrame.origin.y - frame.size.height;

right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment