Skip to content

Instantly share code, notes, and snippets.

@smnh
Last active July 29, 2021 08:00
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save smnh/e864896ba37bc4cfdce6 to your computer and use it in GitHub Desktop.
Save smnh/e864896ba37bc4cfdce6 to your computer and use it in GitHub Desktop.
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;
}
@EmperiorEric
Copy link

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

@AdiletAbylov
Copy link

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

@bizzemfrog
Copy link

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