I have a UIToolbar
that is positioned at the bottom of the screen. When the user taps on a UITextField
in the toolbar, the keyboard appears, and I detect the keyboard size and move the toolbar up by changing its auto layout constraint constant. (It has a bottom spacing constraint to its superview.) This is working well, until the user undocks (or splits) the keyboard on iPad. At that point the toolbar is positioned incorrectly. I noticed in the Messages app the toolbar is always positioned above the keyboard even when the user undocks the keyboard, and it always perfectly sits above it while the user is repositioning the keyboard. After doing some research, it was suggested to handle this by listening for UIKeyboardWillChangeFrameNotification
and examining UIKeyboardFrameEndUserInfoKey
. However, that value may not exist, therefore I'm not sure what to do in that case.
My question is, is the correct approach to listen to keyboard frame change notification(s) and update the auto layout constraint, or is there some other approach to take (inputAccessoryView
for the text field popped into mind)? If so, how does one detect and handle the various scenarios (hiding, appearing, updating frame, undocking, repositioning) to guarantee it's always positioned precisely above the keyboard or at the bottom if there is no keyboard (or there is a hardware keyboard in use)?
See below for how I am currently handling the keyboard appearance/disappearance/frame change in the UIKeyboardWillChangeFrameNotification
handler (mix of Obj-C + pseudocode).
The problem with this is it incorrectly positions the toolbar upon undocking/splitting, repositioning while undocked, and using a hardware keyboard. Also I discovered expanding/collapsing QuickType while the keyboard is undocked does not trigger UIKeyboardWillChangeFrameNotification
(does while docked).
keyboardFrameWillChange {
CGSize keyboardBeginSize = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGSize keyboardEndSize = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGFloat newOffset = 0;
CGFloat toolbarPositionOffset = self.toolbarBottomConstraint.constant;
//get collection view's contentInset and contentOffset
//keyboard is appearing or disappearing or device is rotating with keyboard up
if keyboardEndSize.height == keyboardBeginSize.height {
if toolbarPositionOffset > 0 { //if dismissing
newOffset = keyboardEndSize.height;
toolbarPositionOffset -= newOffset;
//update content inset and offset
} else { //else appearing
newOffset = keyboardEndSize += newOffset;
toolbarPositionOffset += newOffset;
//update content inset and offset
}
}
//keyboard height increasing (expanding QuickType)
else if keyboardEndSize.height > keyboardBeginSize.height {
newOffset = keyboardEndSize.height - keyboardBeginSize.height;
toolbarPositionOffset += newOffset;
//update content inset and offset
}
//else keyboard height decreasing (collapsing QuickType)
else {
newOffset = keyboardBeginSize.height - keyboardEndSize.height;
toolbarPositionOffset -= newOffset;
//update content inset and offset
}
self.toolbarBottomConstraint.constant = toolbarPositionOffset;
//set new contentInset and offset
[self.toolbar layoutIfNeeded];
}