From 6f0e82fb7d25ba0e0a99c7affb6f18b5555473bc Mon Sep 17 00:00:00 2001 From: Igor Kashkuta Date: Wed, 6 Jul 2016 11:16:51 +0100 Subject: [PATCH] Fix jolty transitions between input items. (#174) --- .../Source/Input/ChatInputBarPresenter.swift | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift b/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift index dee4133..aa1103a 100644 --- a/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift +++ b/ChattoAdditions/Source/Input/ChatInputBarPresenter.swift @@ -35,15 +35,27 @@ protocol ChatInputBarPresenter: class { @objc public class BasicChatInputBarPresenter: NSObject, ChatInputBarPresenter { let chatInputBar: ChatInputBar let chatInputItems: [ChatInputItemProtocol] + let notificationCenter: NSNotificationCenter - public init(chatInputBar: ChatInputBar, chatInputItems: [ChatInputItemProtocol], chatInputBarAppearance: ChatInputBarAppearance) { + public init(chatInputBar: ChatInputBar, + chatInputItems: [ChatInputItemProtocol], + chatInputBarAppearance: ChatInputBarAppearance, + notificationCenter: NSNotificationCenter = NSNotificationCenter.defaultCenter()) { self.chatInputBar = chatInputBar self.chatInputItems = chatInputItems self.chatInputBar.setAppearance(chatInputBarAppearance) + self.notificationCenter = notificationCenter super.init() self.chatInputBar.presenter = self self.chatInputBar.inputItems = self.chatInputItems + self.notificationCenter.addObserver(self, selector: #selector(BasicChatInputBarPresenter.keyboardDidChangeFrame), name: UIKeyboardDidChangeFrameNotification, object: nil) + self.notificationCenter.addObserver(self, selector: #selector(BasicChatInputBarPresenter.keyboardWillHide), name: UIKeyboardWillHideNotification, object: nil) + self.notificationCenter.addObserver(self, selector: #selector(BasicChatInputBarPresenter.keyboardWillShow), name: UIKeyboardWillShowNotification, object: nil) + } + + deinit { + self.notificationCenter.removeObserver(self) } private(set) var focusedItem: ChatInputItemProtocol? { @@ -57,8 +69,10 @@ protocol ChatInputBarPresenter: class { private func updateFirstResponderWithInputItem(inputItem: ChatInputItemProtocol) { let responder = self.chatInputBar.textView - responder.inputView = inputItem.inputView + let inputView = inputItem.inputView + responder.inputView = inputView if responder.isFirstResponder() { + self.setHeight(forInputView: inputView) responder.reloadInputViews() } else { responder.becomeFirstResponder() @@ -75,6 +89,45 @@ protocol ChatInputBarPresenter: class { } return firstKeyboardInputItem } + + private var lastKnownKeyboardHeight: CGFloat? + + private func setHeight(forInputView inputView: UIView?) { + guard let inputView = inputView else { return } + guard let keyboardHeight = self.lastKnownKeyboardHeight else { return } + + var mask = inputView.autoresizingMask + mask.remove(.FlexibleHeight) + inputView.autoresizingMask = mask + + let accessoryViewHeight = self.chatInputBar.textView.inputAccessoryView?.bounds.height ?? 0 + let inputViewHeight = keyboardHeight - accessoryViewHeight + + if let heightConstraint = inputView.constraints.filter({ $0.firstAttribute == .Height }).first { + heightConstraint.constant = inputViewHeight + } else { + inputView.frame.size.height = inputViewHeight + } + } + + private var allowListenToChangeFrameEvents = true + + @objc + private func keyboardDidChangeFrame(notification: NSNotification) { + guard self.allowListenToChangeFrameEvents else { return } + guard let value = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } + self.lastKnownKeyboardHeight = value.CGRectValue().height + } + + @objc + private func keyboardWillHide(notification: NSNotification) { + self.allowListenToChangeFrameEvents = false + } + + @objc + private func keyboardWillShow(notification: NSNotification) { + self.allowListenToChangeFrameEvents = true + } } // MARK: ChatInputBarPresenter