Last active
July 29, 2021 08:00
-
-
Save smnh/e864896ba37bc4cfdce6 to your computer and use it in GitHub Desktop.
Synchronizing rotation animation between the keyboard and the attached view - Part 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (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; | |
} |
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
Excellent work. This is really great. The comments really help explain how its working.