KeyboardDidShow вызывается, когда клавиатура не отображается - PullRequest
0 голосов
/ 23 сентября 2018

, поэтому я настроил наблюдатели клавиатуры с помощью KeyboardDidShow, чтобы я мог сдвигать изображение вверх, только когда клавиатура отображается.Однако KeyboardDidShow запускается при запуске каждого представления, а также в случайное время.Я пытался отслеживать кадры клавиатуры и смещать вид только при изменении кадра, но время от времени вид все еще смещается даже без отображения клавиатуры.Обычно это происходит всякий раз, когда представление запускается впервые, поэтому я попытался добавить задержку, но она не очень надежна.

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    }

@objc func keyboardDidShow(_ notification: Notification) {

    let userInfo = notification.userInfo!
    let beginFrameValue = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)!
    let beginFrame = beginFrameValue.cgRectValue
    let endFrameValue = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)!
    let endFrame = endFrameValue.cgRectValue

    if beginFrame.equalTo(endFrame) {
        return
    } else {
        let indexPath = IndexPath(item: 0, section: 0)
        if UIScreen.main.bounds.height == 812 {
            collectionView?.contentInset = UIEdgeInsets(top: 318 + view.safeAreaInsets.bottom, left: 0, bottom: 73, right: 0)
        } 
        collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
    }
}

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Для экземпляров UIViewController вам необходимо наблюдать эти уведомления только тогда, когда вид видим и не подписываться на уведомление несколько раз.Лучший способ сделать это:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)        
    NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardWillChangeFrame(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}

А вот рабочий код из моего проекта для обработки рамки из кейборда

@objc private func onKeyboardWillChangeFrame(_ notification: NSNotification) {
    // extract values
    if let userInfo = notification.userInfo,
        let keyboardFrameEnd = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
        let animationCurveInt = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.intValue {

        /*
         СУКАБЛЯТЬ
         With upgrate to Swift 4.2 UIView.AnimationCurve(rawValue: 7) returns actual instance of
         UIView.AnimationCurve which crashes on access, mod by 4 limits value to max
         */
        let animationCurve = UIView.AnimationCurve(rawValue: animationCurveInt % 4) ?? .easeIn

        // View chanages
        let topPoint = self.view.convert(keyboardFrameEnd.origin, from: self.view.window)
        let height = self.view.bounds.size.height - topPoint.y

        ... update your constraints or manually update vars that affect layoutSubviews()...

        let animationDuration: TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        var animationOptions: UIView.AnimationOptions = []
        switch animationCurve {
            case .easeInOut: animationOptions = .curveEaseInOut
            case .easeIn: animationOptions = .curveEaseIn
            case .easeOut: animationOptions = .curveEaseOut
            case .linear: animationOptions = .curveLinear
        }

        // run animation
        UIView.animate(withDuration: animationDuration, delay: 0, options: animationOptions, animations: {
            self.view.layoutIfNeeded()
        })
    }
}
0 голосов
/ 23 сентября 2018

Проблема в том, что вы настроили неправильное уведомление.Не используйте UIKeyboardDidShow.Используйте UIKeyboardWillShow и изучите старый фрейм, новый фрейм и то, будет ли новый фрейм покрывать ваше представление.

Достижение надежной реализации не тривиально, но это, безусловно, хорошо известная ранее решенная проблема, которая имеетздесь много раз объясняли.

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