WIP: hide caption keyboard

It's tricky because we're hopping from one first responder to another.

Specifically, from the CaptionView.textView, which shows the keyboard, to
making the AttachmentApprovalViewController first responder, which shows the
BottomToolbar message text field, so in short order, we're getting multiple
notifications.

User hit's "Done" with caption

- Point A - CaptionView is positioned at the top of the keyboard
- Hide keyboard (frame change details must be calculated by y offset, since willChanage notification doesn't "shrink" the keyboard frame, it just offsets it to be non-visible.
- Point B - caption view is positioned at the bottom of the screen, input accessory view not visible
- Show Keyboard (not actually showing the *keyboard* here, but rather the VC's input accessory view)
- Point C - caption view is positioned atop the input accessory view

We want to animated smoothly from A->C, skipping B. But how do we do that robustly? We could track something like "last known input accessory view height" and never present the captionView below that. But I'm worried it won't be very robust since the input accessory view can change height, e.g. text view grows with text content or dynamic text changes.
This commit is contained in:
Michael Kirk 2018-11-24 10:37:47 -06:00
parent 838012d1ec
commit b108f284bd

View file

@ -198,12 +198,98 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
self.setCurrentItem(firstItem, direction: .forward, animated: false)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillChangeFrame(notification:)),
name: .UIKeyboardWillChangeFrame,
object: nil)
// NotificationCenter.default.addObserver(self,
// selector: #selector(keyboardWillChangeFrame(notification:)),
// name: .UIKeyboardWillChangeFrame,
// object: nil)
observers = [
NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil) { [weak self] notification in
guard let strongSelf = self else { return }
guard let userInfo = notification.userInfo else {
owsFailDebug("userInfo was unexpectedly nil")
return
}
guard let keyboardStartFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
guard let keyboardEndFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
Logger.debug("UIKeyboardWillShow frame: \(keyboardStartFrame) -> \(keyboardEndFrame)")
strongSelf.keyboardWillShow(notification: notification)
},
// NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil) { [weak self] notification in
// guard let userInfo = notification.userInfo else {
// owsFailDebug("userInfo was unexpectedly nil")
// return
// }
//
// guard let keyboardStartFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect else {
// owsFailDebug("keyboardEndFrame was unexpectedly nil")
// return
// }
//
// guard let keyboardEndFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
// owsFailDebug("keyboardEndFrame was unexpectedly nil")
// return
// }
//
// Logger.debug("UIKeyboardDidShow frame: \(keyboardStartFrame) -> \(keyboardEndFrame)")
// },
NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil) { [weak self] notification in
guard let strongSelf = self else { return }
guard let userInfo = notification.userInfo else {
owsFailDebug("userInfo was unexpectedly nil")
return
}
guard let keyboardStartFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
guard let keyboardEndFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
Logger.debug("UIKeyboardWillHide frame: \(keyboardStartFrame) -> \(keyboardEndFrame)")
strongSelf.keyboardWillHide(notification: notification)
}
// NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil) { [weak self] notification in
// guard let userInfo = notification.userInfo else {
// owsFailDebug("userInfo was unexpectedly nil")
// return
// }
//
// guard let keyboardStartFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect else {
// owsFailDebug("keyboardEndFrame was unexpectedly nil")
// return
// }
//
// guard let keyboardEndFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
// owsFailDebug("keyboardEndFrame was unexpectedly nil")
// return
// }
//
// Logger.debug("UIKeyboardDidHide frame: \(keyboardStartFrame) -> \(keyboardEndFrame)")
// },
]
}
var observers: [NSObjectProtocol] = []
override public func viewWillAppear(_ animated: Bool) {
Logger.debug("")
super.viewWillAppear(animated)
@ -238,20 +324,24 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
var lastObservedKeyboardHeight: CGFloat = 0
@objc
func keyboardWillChangeFrame(notification: Notification) {
Logger.debug("")
// NSDictionary *userInfo = [notification userInfo];
func keyboardWillShow(notification: Notification) {
guard let userInfo = notification.userInfo else {
owsFailDebug("userInfo was unexpectedly nil")
return
}
guard let keyboardStartFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
guard let keyboardEndFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
Logger.debug("\(keyboardStartFrame) -> \(keyboardEndFrame)")
lastObservedKeyboardHeight = keyboardEndFrame.size.height
viewControllers?.forEach { viewController in
@ -264,6 +354,40 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
}
}
@objc
func keyboardWillHide(notification: Notification) {
guard let userInfo = notification.userInfo else {
owsFailDebug("userInfo was unexpectedly nil")
return
}
guard let keyboardStartFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
guard let keyboardEndFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect else {
owsFailDebug("keyboardEndFrame was unexpectedly nil")
return
}
Logger.debug("\(keyboardStartFrame) -> \(keyboardEndFrame)")
lastObservedKeyboardHeight = keyboardEndFrame.size.height
if keyboardStartFrame.height == keyboardEndFrame.height {
lastObservedKeyboardHeight -= keyboardEndFrame.maxY - keyboardStartFrame.maxY
}
viewControllers?.forEach { viewController in
guard let prepViewController = viewController as? AttachmentPrepViewController else {
owsFailDebug("unexpected prepViewController: \(viewController)")
return
}
prepViewController.updateCaptionViewBottomInset()
}
}
// MARK: - View Helpers
func remove(attachmentItem: SignalAttachmentItem) {