123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- /*
- MIT License
- Copyright (c) 2017-2018 MessageKit
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
- import Foundation
- extension MessagesViewController {
- // MARK: - Register / Unregister Observers
- internal func addKeyboardObservers() {
- NotificationCenter.default.addObserver(self, selector: #selector(MessagesViewController.handleKeyboardDidChangeState(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(MessagesViewController.handleTextViewDidBeginEditing(_:)), name: UITextView.textDidBeginEditingNotification, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(MessagesViewController.adjustScrollViewInset), name: UIDevice.orientationDidChangeNotification, object: nil)
- }
- internal func removeKeyboardObservers() {
- NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
- NotificationCenter.default.removeObserver(self, name: UITextView.textDidBeginEditingNotification, object: nil)
- NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
- }
- // MARK: - Notification Handlers
- @objc
- private func handleTextViewDidBeginEditing(_ notification: Notification) {
- if scrollsToBottomOnKeybordBeginsEditing {
- guard let inputTextView = notification.object as? InputTextView, inputTextView === messageInputBar.inputTextView else { return }
- messagesCollectionView.scrollToBottom(animated: true)
- }
- }
- @objc
- private func handleKeyboardDidChangeState(_ notification: Notification) {
- guard let keyboardEndFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
-
- guard !isMessagesControllerBeingDismissed else { return }
-
- let newBottomInset = view.frame.height - keyboardEndFrame.minY - iPhoneXBottomInset
-
- let differenceOfBottomInset = newBottomInset - messageCollectionViewBottomInset
-
- if maintainPositionOnKeyboardFrameChanged && differenceOfBottomInset != 0 {
- let contentOffset = CGPoint(x: messagesCollectionView.contentOffset.x, y: messagesCollectionView.contentOffset.y + differenceOfBottomInset)
- messagesCollectionView.setContentOffset(contentOffset, animated: false)
- }
-
- messageCollectionViewBottomInset = newBottomInset
- }
- @objc
- internal func adjustScrollViewInset() {
- if #available(iOS 11.0, *) {
- // No need to add to the top contentInset
- } else {
- let navigationBarInset = navigationController?.navigationBar.frame.height ?? 0
- let statusBarInset: CGFloat = UIApplication.shared.isStatusBarHidden ? 0 : 20
- let topInset = navigationBarInset + statusBarInset
- messagesCollectionView.contentInset.top = topInset
- messagesCollectionView.scrollIndicatorInsets.top = topInset
- }
- }
- // MARK: - Helpers
- internal var keyboardOffsetFrame: CGRect {
- guard let inputFrame = inputAccessoryView?.frame else { return .zero }
- return CGRect(origin: inputFrame.origin, size: CGSize(width: inputFrame.width, height: inputFrame.height - iPhoneXBottomInset))
- }
- /// On the iPhone X the inputAccessoryView is anchored to the layoutMarginesGuide.bottom anchor
- /// so the frame of the inputAccessoryView is larger than the required offset
- /// for the MessagesCollectionView.
- ///
- /// - Returns: The safeAreaInsets.bottom if its an iPhoneX, else 0
- private var iPhoneXBottomInset: CGFloat {
- if #available(iOS 11.0, *) {
- guard UIScreen.main.nativeBounds.height == 2436 else { return 0 }
- return view.safeAreaInsets.bottom
- }
- return 0
- }
- }
|