Переместить вид, когда определенное текстовое поле выбрано быстро

Я создал приложение-генератор мемов, чтобы лучше изучить Swift и Xcode. Я учусь перемещать представление, когда пользователь взаимодействует с текстовым полем, которое будет закрыто клавиатурой. У меня эта функциональность работает, за одним исключением. Желаемая функциональность заключается в том, чтобы представление перемещалось вверх, когда пользователь вводит текст для нижнего текстового поля, а не для верхнего. Представление перемещается вверх независимо от текстового поля, с которым взаимодействует пользователь.

Как я могу назначить эту функцию только нижнему текстовому полю? Вот мой исходный код:

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate {

    @IBOutlet weak var imagePickerView: UIImageView!
    @IBOutlet weak var cameraButton: UIBarButtonItem!
    @IBOutlet weak var topText: UITextField!
    @IBOutlet weak var bottomText: UITextField!

    let memeTextAttributes:[String:Any] = [
        NSAttributedStringKey.strokeColor.rawValue: UIColor.black,
        NSAttributedStringKey.foregroundColor.rawValue: UIColor.white,
        NSAttributedStringKey.font.rawValue: UIFont(name: "HelveticaNeue-CondensedBlack", size: 30)!,
        NSAttributedStringKey.strokeWidth.rawValue: -5.0]

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        subscribeToKeyboardNotifications()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Diable camer a button if camera ource isn't available
        cameraButton.isEnabled = UIImagePickerController.isSourceTypeAvailable(.camera)
        topText.delegate = self
        bottomText.delegate = self
        topText.textAlignment = .center
        bottomText.textAlignment = .center
        topText.defaultTextAttributes = memeTextAttributes
        bottomText.defaultTextAttributes = memeTextAttributes
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        unsubscribeFromKeyboardNotifications()
    }

    // MARK: Delegate Methods

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
            imagePickerView.image = image
            self.dismiss(animated: true, completion: nil)
        }
    }

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.dismiss(animated: true, completion: nil)
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        textField.text = ""
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.topText.resignFirstResponder()
        self.bottomText.resignFirstResponder()
        return true
    }

    // MARK: Move the keyboard up when the bottom textfield is tapped

    @objc func keyboardWillShow(_ notification:Notification) {
        view.frame.origin.y = 0 - getKeyboardHeight(notification)
    }

    func getKeyboardHeight(_ notification:Notification) -> CGFloat {
        let userInfo = notification.userInfo
        let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect
        return keyboardSize.cgRectValue.height
    }

    func subscribeToKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: .UIKeyboardWillHide, object: nil)
    }

    func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
    }

    // MARK: Move view down when keyboard is dismissed

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

    // MARK: IBActions

    @IBAction func pickAnImageFromAlbum(_ sender: Any) {
        let pickerController = UIImagePickerController()
        pickerController.delegate = self
        pickerController.sourceType = .photoLibrary
        present(pickerController, animated: true, completion: nil)
    }

    @IBAction func pickAnImageFromCamera(_ sender: Any) {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .camera
        present(imagePicker, animated: true, completion: nil)
    }
}

4 ответа

Решение

Вы можете просто попробовать это

  //make a global textField to keep reference
var currentTappedTextField : UITextField?
//use this method to get tapped textField
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
   currentTappedTextField = textField
    return true
}
// now move view only when textfield is bottom
@objc func keyboardWillShow(_ notification:Notification) {
    if(currentTappedTextField == bottomText){
   view.frame.origin.y = 0 - getKeyboardHeight(notification)
    }
}

Добавить представление в scrollview. использование

pod 'IQKeyboardManagerSwift'

Это будет автоматически обрабатывать это. В приложении делегат напишите этот код:

 IQKeyboardManager.sharedManager().enable = true
 IQKeyboardManager.sharedManager().keyboardDistanceFromTextField = 30.0

Если вы хотите для одного текстового поля:

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { 
    if textField == toptextField {
        IQKeyboardManager.sharedManager().enable = false 
    }
    else {
        IQKeyboardManager.sharedManager().enable = true
    } 
    return true
}

Подход без использования внешней структуры:

  1. Используйте ограничение снизу от текстового поля до родительского представления.
  2. Отрегулируйте постоянное значение в зависимости от того, показана клавиатура или скрыта.

шаги:

  1. Создайте нижнее ограничение от вашего текстового поля до родительского представления.
  2. Установите постоянную ограничения в начальное желаемое значение
  3. Добавить сохранить ограничение как свойство в контроллере представления
  4. соблюдать UIKeyboardDidShow Уведомление и получить конец кадра клавиатуры. Используйте отрицательную высоту конечного кадра в качестве константы нижнего ограничения.
  5. Аналогичным образом сделайте то же самое в UIKeyboardWillHide и установите нижнюю константу ограничения в исходное значение константы

Вам просто нужно наблюдать уведомление клавиатуры в вашем viewDidLoad:

    override func viewDidLoad() {
        super.viewDidLoad()            
        NotificationCenter.default.addObserver(self,
                                           selector: #selector(keyboardWillShow(_:)),
                                           name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self,
                                           selector: #selector(keyboardWillHide),
                                           name: NSNotification.Name.UIKeyboardWillHide, object: nil)   
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

И объявите методы селектора, чтобы изменить ограничение представления:

@objc
func keyboardWillShow(_ notification: Notification) {
    if let keyboardHeight = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
        yourViewBottomConstraint.constant = keyboardHeight.cgRectValue.height + constantHeight
        UIView.animate(withDuration: 0.25, animations: {
            self.view.layoutIfNeeded()
        })
    }
}

@objc
func keyboardWillHide() {
    yourViewBottomConstraint.constant = constantHeight
    UIView.animate(withDuration: 0.25, animations: {
        self.view.layoutIfNeeded()
    })
}

Только не забудьте реализовать UITextFieldDelegate:

extension ViewController: UITextFieldDelegate {
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.view.endEditing(true)
        return false
    }
}
Другие вопросы по тегам