TextField переместился вверх, когда покрыт клавиатурой, не остается в положении - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь решить общую проблему, чтобы переместиться вверх TextField, когда он покрывается клавиатурой. В основном я следовал документации Apple от Перемещение содержимого, расположенного под клавиатурой

Но я не использую ScrollView, просто имею два TextFileds внутри основного вида.

Lower один перемещается вверх, когда покрывается клавиатурой, и отлично работает на iPhone 8 или SE (с острыми углами экрана, где основной вид и SafeArea одинаковы).

У меня проблема с iPhone X, XS или 11 (с надписью Face ID и закругленными углами экрана, где безопасная зона и главный вид не совпадают).

На этих iPhone * TextField первоначально перемещается в нужное положение , но сразу после прикосновение к клавиатуре (после ввода буквы) само по себе прыгает вниз на несколько пикселей и снова прячется за клавиатурой .

Вот код, над которым я работаю:

//
//  ViewController.swift
//  TextFields
//
//  Created by Manoli on 24/04/2020.
//  Copyright © 2020 macForce. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var upperTextField: UITextField!
    @IBOutlet weak var lowerTextField: UITextField!

    var activeTextField: UITextField?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        upperTextField.delegate = self
        lowerTextField.delegate = self

        registerForKeyboardNotifications()
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        activeTextField = nil
        textField.resignFirstResponder()
        return true
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        activeTextField = textField
    }

    func registerForKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)

        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc func keyboardWillShow(_ notification: NSNotification) {

        let keyboardSpacing: CGFloat = 8.0 // Standard value for spacing between keyboard and textfield

        guard let userInfo = notification.userInfo,
            let keyboardFrameValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
            else { return }

        let keyboardFrame = keyboardFrameValue.cgRectValue

        guard let activeTextFieldFrame = activeTextField?.frame else { return }

        let positionShift = activeTextFieldFrame.origin.y + activeTextFieldFrame.height - keyboardFrame.origin.y + keyboardSpacing

        if positionShift > 0 {
            view.frame.origin.y = -positionShift
        }
    }

    @objc func keyboardWillHide(_ notification: NSNotification) {
        view.frame.origin.y = 0
    }
}

Здесь у меня есть ссылка на весь проект на GitHub.

Кто-нибудь имеет представление, почему это создает проблемы только для определенного типа * 10 52 * экран? Что-то не так с идеей, которую я использую в этом коде?

Большое спасибо за любой совет или предложение, всем хорошего дня.

Обновление:

Я обнаружил, что если вертикальные ограничения TextFields настроены для Superview, а не для Safe Area, это работает нормально (также на iPhone X и выше). Теперь я обновил проект на GitHub соответственно. (Единственное, что мне не нравится, это то, что вертикальные ограничения для Superview не являются симметричными, и они выглядят не совсем правильно на iPhone SE и 8 и ниже.)

Обновление:

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

ToDo: еще нужно выяснить, как анимировать изменения этого ограничения в соответствии с клавиатурой.

1 Ответ

0 голосов
/ 25 апреля 2020
func textFieldShouldBeginEditing(_ textField: UITextField) 
{
    activeTextField = textField
}

func showLoginKeyBoard()
{
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
}

 @objc func keyboardWillShow(notification: NSNotification)
{
    if activeTextField == upperTextField
    {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
            if self.view.frame.origin.y == 0
            {
                self.view.frame.origin.y -= keyboardSize.height
            }
        }
    }

    if activeTextField == lowerTextField
    {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
            if self.view.frame.origin.y == 0
            {
                self.view.frame.origin.y -= keyboardSize.height + 50
            }
        }
    }
}

func hideLoginKeyboard()
{
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(
        target: self,
        action: #selector(UIViewController.keyboardWillHide))
    tap.cancelsTouchesInView = false
    view.addGestureRecognizer(tap)
    self.view.endEditing(true)
}

@objc func keyboardWillHide(notification: NSNotification)
{
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1), execute:
        {
            if self.view.frame.origin.y != 0
            {
                UIView.animate(withDuration: 0.3, delay: 0.0, animations:
                    {
                        self.view.frame.origin.y = 0
                })
            }
    })
}

func deregisterFromKeyboardNotifications()
{
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

override func viewDidDisappear(_ animated: Bool)
{
    deregisterFromKeyboardNotifications()
}
...