Swift - Отключить клавиатуру и вызвать кнопку TouchUpInside одновременно не работает при использовании UIKeyboardWillChangeFrame - PullRequest
0 голосов
/ 06 ноября 2019

Я использую swift и у меня возникают проблемы с TouchUpInside: если я использую UIKeyboardWillChangeFrame или UIKeyboardWillShow / UIKeyboardWillHide, и клавиатура отображается, а кнопка, которую я пытаюсь нажать, находится за клавиатурой, когда клавиатура отображается изначально. (Если я прокручиваю вниз до кнопки до появления и нажимаю, touchUpInside не вызывается.)

Кажется, что TouchDown работает одинаково независимо от того, показывает клавиатура или нет, но TouchUpInside не вызывается. Если кнопка находится над верхней частью клавиатуры, когда клавиатура изначально отображается, TouchUpInside работает. Я использую Keyboard Notification, чтобы установить высоту представления ниже моего scrollView, чтобы поднять мой scrollView, когда клавиатура отображается. Из того, что я вижу, это обычно только когда кнопка является последним элементом в scrollView (и поэтому, вероятно, будет позади клавиатуры, когда клавиатура показана).

@IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var saveButton: UIButton!
@IBAction func saveTouchUpInside(_ sender: UIButton) {
   print("touchupinside = does not work")
}
@objc func saveTouchDown(notification:NSNotification){
   print("touchdown = works")
}

viewWillAppear:

textField.delegate = self

NotificationCenter.default.addObserver(self,selector:#selector(self.keyboardNotification(notification:)),name: 

NSNotification.Name.UIKeyboardWillChangeFrame,object: nil)
self.saveButton.addTarget(self, action:#selector(ViewController.saveTouchDown(notification:)), for: .touchDown)

deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        let endFrameY = endFrame?.origin.y ?? 0
        let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
        if endFrameY >= UIScreen.main.bounds.size.height {
            self.keyboardHeightLayoutConstraint?.constant = 0.0
        } else {
            self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
        }
            UIView.animate(withDuration: duration, delay: TimeInterval(0),options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil)
        }
    }

Я хотел бы закрыть клавиатуру и вызвать saveTouchUpInside одновременно, без использования TouchDown.

1 Ответ

0 голосов
/ 07 ноября 2019

Я абстрагирую взаимодействие с клавиатурой как отдельный класс, чтобы мои контроллеры не распухли (также следует separation of concerns). Вот класс менеджера клавиатуры, который я использую.

import UIKit


/**
*  To adjust the scroll view associated with the displayed view to accommodate
*  the display of keyboard so that the view gets adjusted accordingly without getting hidden
*/
class KeyboardManager {

    private var scrollView: UIScrollView

    /**
    *  -parameter scrollView: ScrollView that need to be adjusted so that it does not get clipped by the presence of the keyboard
    */
    init(scrollView: UIScrollView) {

        self.scrollView = scrollView

        let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self,
                                                                     selector: #selector(adjustForKeyboard),
                                                                     name: UIResponder.keyboardWillHideNotification, object: nil)
        notificationCenter.addObserver(self,
                                                                     selector: #selector(adjustForKeyboard),
                                                                     name: UIResponder.keyboardDidChangeFrameNotification, object: nil)
    }

    /**
    * Indicates that the on-screen keyboard is about to be presented.
    *  -parameter notification: Contains animation and frame details on the keyboard
    *
    */
    @objc func adjustForKeyboard(notification: Notification) {

        guard let containedView = scrollView.superview else { return }

        let userInfo = notification.userInfo!
        let keyboardScreenEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let keyboardViewEndFrame = containedView.convert(keyboardScreenEndFrame, to: containedView.window)

        let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
        let rawAnimationCurveValue = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber).uintValue

        UIView.animate(withDuration: TimeInterval(truncating: duration),
                                     delay: 0,
                                     options: [UIView.AnimationOptions(rawValue: rawAnimationCurveValue)],
                                     animations: {

                                        if notification.name == UIResponder.keyboardWillHideNotification {
                                            self.scrollView.contentInset = UIEdgeInsets.zero
                                        } else {
                                            self.scrollView.contentInset = UIEdgeInsets(top: 0,
                                                                                                                                    left: 0,
                                                                                                                                    bottom: keyboardViewEndFrame.height,
                                                                                                                                    right: 0)
                                        }

                                        self.scrollView.scrollIndicatorInsets = self.scrollView.contentInset

        },
                                     completion: nil)
    }

    deinit {
        let notificationCenter = NotificationCenter.default
        notificationCenter.removeObserver(self)
    }

}

Используется примерно так:

  • создать ссылку на менеджер клавиатуры
 private var keyboardManager: KeyboardManager!
  • и назначить менеджер клавиатурыкласс, как показано ниже в viewDidLoad, где self.scrollView - это scrollView, с которым вы работаете
 self.keyboardManager = KeyboardManager(scrollView: self.scrollView)

Это должно решить проблему. Если это не сработает, возможно, пример проекта поможет в этом разобраться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...