Skip to content

Commit

Permalink
Merge pull request MessageKit#125 from MessageKit/refactor/keyboard-h…
Browse files Browse the repository at this point in the history
…andling

Refactoring keyboard handling
  • Loading branch information
SD10 authored Sep 19, 2017
2 parents fad170b + c9fdb2d commit 847338c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 42 deletions.
18 changes: 15 additions & 3 deletions Example/ChatExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ChatExample-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
17575422C6ED250D743DD40C /* [CP] Embed Pods Frameworks */ = {
Expand All @@ -367,13 +370,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ChatExampleUITests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
1E9549B97552A057E870E4D4 /* [CP] Embed Pods Frameworks */ = {
Expand Down Expand Up @@ -412,9 +418,12 @@
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-ChatExample/Pods-ChatExample-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/MessageKit/MessageKit.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MessageKit.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand All @@ -427,13 +436,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ChatExampleTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
57DC8C6D452F2FB13B25D6AA /* [CP] Copy Pods Resources */ = {
Expand Down
2 changes: 1 addition & 1 deletion Example/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 9ac65b8dedf0e1b63fea245b089b6645c4e66309

COCOAPODS: 1.2.1
COCOAPODS: 1.3.1
64 changes: 26 additions & 38 deletions Sources/MessagesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ open class MessagesViewController: UIViewController {
open var messageInputBar = MessageInputBar()

private var messageInputBarCopy: MessageInputBar?

private var isFirstLayout: Bool = true

override open var canBecomeFirstResponder: Bool {
return true
Expand Down Expand Up @@ -64,17 +66,23 @@ open class MessagesViewController: UIViewController {

open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setupMessageInputBarCopy()
if isFirstLayout {
setupMessageInputBarCopy()
}
}

open override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
addKeyboardObservers()
removeMessageInputBarCopy()
}

override open func viewDidLayoutSubviews() {
messagesCollectionView.contentInset.top = topLayoutGuide.length
open override func viewDidLayoutSubviews() {
// Hack to prevent animation of the contentInset after viewDidAppear
if isFirstLayout {
addKeyboardObservers()
messagesCollectionView.contentInset.bottom = messageInputBar.frame.height
isFirstLayout = false
}
}

// MARK: - Initializers
Expand Down Expand Up @@ -115,14 +123,12 @@ open class MessagesViewController: UIViewController {

messagesCollectionView.translatesAutoresizingMaskIntoConstraints = false

let constraints: [NSLayoutConstraint] = [
messagesCollectionView.topAnchor.constraint(equalTo: view.topAnchor),
messagesCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
messagesCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
let top = messagesCollectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: topLayoutGuide.length)
let leading = messagesCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor)
let trailing = messagesCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
let bottom = messagesCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)

messagesCollectionView.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor),
]
NSLayoutConstraint.activate(constraints)
NSLayoutConstraint.activate([top, bottom, trailing, leading])
}

// MARK: - MessageInputBar
Expand Down Expand Up @@ -257,44 +263,26 @@ extension MessagesViewController: UICollectionViewDataSource {
extension MessagesViewController {

fileprivate func addKeyboardObservers() {

NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardDidChangeState), name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardDidChangeState), name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardDidChangeState), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardDidChangeState), name: .UIKeyboardWillChangeFrame, object: nil)

}

fileprivate func removeKeyboardObservers() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
}

func handleKeyboardDidChangeState(_ notification: Notification) {

guard let keyboardEndFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect else { return }
let keyboardFrame = self.view.convert(keyboardEndFrame, from: self.view.window)

switch notification.name {
case Notification.Name.UIKeyboardDidShow:
// Only runs once
messagesCollectionView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: messageInputBar.frame.height, right: 0)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
case Notification.Name.UIKeyboardDidChangeFrame, Notification.Name.UIKeyboardWillShow:
if (keyboardFrame.origin.y + keyboardFrame.size.height) > view.frame.size.height {
// Hardware keyboard is found
messagesCollectionView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: messageInputBar.frame.height, right: 0)
} else {
// Software keyboard is found
messagesCollectionView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: keyboardEndFrame.height, right: 0)
}
case Notification.Name.UIKeyboardWillHide:
messagesCollectionView.contentInset = UIEdgeInsets(top: topLayoutGuide.length, left: 0, bottom: messageInputBar.frame.height, right: 0)
default:
break

if (keyboardEndFrame.origin.y + keyboardEndFrame.size.height) > view.frame.size.height {
// Hardware keyboard is found
messagesCollectionView.contentInset.bottom = view.frame.size.height - keyboardEndFrame.origin.y
} else {
//Software keyboard is found
let bottomInset = keyboardEndFrame.height > messageInputBar.frame.height ? keyboardEndFrame.height : messageInputBar.frame.height
messagesCollectionView.contentInset.bottom = bottomInset
}

}

}

0 comments on commit 847338c

Please sign in to comment.