Як визначити, коли клавіатура відображається та приховується


Відповіді:


166

У методі ViewDidLoad вашого класу, налаштованому на прослуховування повідомлень про клавіатуру:

// Listen for keyboard appearances and disappearances
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(keyboardDidShow:)
                                             name:UIKeyboardDidShowNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardDidHideNotification
                                           object:nil];

Тоді у вказаних вами методах (у цьому випадку keyboardDidShowі keyboardDidHide) ви можете щось з цим зробити:

- (void)keyboardDidShow: (NSNotification *) notif{
    // Do something here
}

- (void)keyboardDidHide: (NSNotification *) notif{
    // Do something here
}

Не працює, якщо ви перекладаєте поля. Цікаво, яким буде рішення для цього, і чи зможете Ви навіть переходити на фактичний iPad?
i--

@apprentice Ви маєте на увазі, що клавіатура не відображається, якщо перейти на вкладку?
Метью Фредерік

якщо є поля, все ще покриті клавіатурою, нижче поля з фокусом, вигляд залишатиметься на вкладці через сповіщення, що надсилається лише в момент, коли клавіатура ковзає вгору
i--

3
@apprentice Ви повинні керувати цим вручну, пересуваючи прокрутку навколо кожного текстового поля, яке стає активним, інша проблема, ніж знання, коли з'являється клавіатура. Зробіть свій контролер подання UITextFieldDelegat, а потім застосуйте textFieldShouldReturn:метод. Ви отримаєте textFieldщойно введений як аргумент, який ви можете порівняти із власним textFields та прокрутити scrollViewтак, щоб відображався відповідний textField.
Метью Фредерік,

95

Ви можете просто потрібно addObserverв viewDidLoad. Але маючи addObserverв viewWillAppearі removeObserverв viewWillDisappearзапобігають рідкісних аваріях , яке відбувається , коли ви міняєте вид.

Свіфт 4.2

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear), name: UIResponder.keyboardWillShowNotification, object: nil)
}

@objc func keyboardWillAppear() {
    //Do something here
}

@objc func keyboardWillDisappear() {
    //Do something here
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

Свіфт 3 і 4

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: Notification.Name.UIKeyboardWillHide, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear), name: Notification.Name.UIKeyboardWillShow, object: nil)
}

@objc func keyboardWillAppear() {
    //Do something here
}

@objc func keyboardWillDisappear() {
    //Do something here
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

Старший Свіфт

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillAppear:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyboardWillDisappear:", name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWillAppear(notification: NSNotification){
    // Do something here
}

func keyboardWillDisappear(notification: NSNotification){
    // Do something here
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

9
Якщо ви видалите свого спостерігача на viewWillDisappear ... вам слід додати його до viewWillAppear замість viewDidLoad.
FouZ

Це правда, сміливо редагуйте відповідь. Я прийму це
Ескаррут

@FouZ, чи краще прибрати таких спостерігачів deinit:deinit { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) }
Крашалот,

У Swift 3, вищезазначений блок коду деініт виглядає так:deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) }
Мд. Наджмул Хасан

@Crashalot deinit не запускається, поки ви не відхилите vc. отже, якщо ви подасте ще один vc поверх цього, він все одно отримуватиме сповіщення. Я вважаю, що мета полягає в тому, щоб слухати лише ці сповіщення, поки цей vc видно, тому додавання його на viewdidappear та видалення на viewdiddissapear мені здається кращим.
Почі

19

Свіфт 3:

NotificationCenter.default.addObserver(self, selector: #selector(viewController.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(viewController.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

func keyboardWillShow(_ notification: NSNotification){
    // Do something here
}

func keyboardWillHide(_ notification: NSNotification){
    // Do something here
}

9

Свіфт 4:

  NotificationCenter.default.addObserver( self, selector: #selector(ControllerClassName.keyboardWillShow(_:)),
  name: Notification.Name.UIKeyboardWillShow,
  object: nil)
  NotificationCenter.default.addObserver(self, selector: #selector(ControllerClassName.keyboardWillHide(_:)),
  name: Notification.Name.UIKeyboardWillHide,
  object: nil)

Далі, додавання методу, щоб припинити прослуховування сповіщень, коли закінчується життя об’єкта: -

Then add the promised methods from above to the view controller:
deinit {
  NotificationCenter.default.removeObserver(self)
}
func adjustKeyboardShow(_ open: Bool, notification: Notification) {
  let userInfo = notification.userInfo ?? [:]
  let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
  let height = (keyboardFrame.height + 20) * (open ? 1 : -1)
  scrollView.contentInset.bottom += height
  scrollView.scrollIndicatorInsets.bottom += height
}

@objc func keyboardWillShow(_ notification: Notification) {
  adjustKeyboardShow(true, notification: notification)
}
@objc func keyboardWillHide(_ notification: Notification) {
  adjustKeyboardShow(false, notification: notification)
}

+=, Як представляється , зробити вставки отримати більше і більше.
Вез

Я думаю, що функція AdjuKeyboardShow - це дуже добре зроблена функція. Дякую.
розробник

станом на Swift 5 ім’я сповіщення - UIResponder.keyboardWillShowNotificationі UIResponder.keyboardWillHideNotification, а інформаційна клавіша клавіатури - UIResponder.keyboardFrameBeginUserInfoKey.
CodeBrew

5

Свіфт - 4

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

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self) //remove observer
}

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

@objc func keyboardWillShow(_ notification: Notification) {

}

@objc func keyboardWillHide(_ notification: Notification) {

}

4

Ознайомтеся з розділом Керування клавіатурою в "Посібнику з програмування тексту, Інтернету та редагування", щоб отримати інформацію про відстеження показаної або прихованої клавіатури та про те, як відобразити / відхилити її вручну.


4

Ви хочете зареєструватися для отримання 2 сповіщень із клавіатури:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name: UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardDidHide:) name: UIKeyboardDidHideNotification object:nil];

Чудовий допис про те, як налаштувати TextField на клавіатуру - http://iosdevelopertips.com/user-interface/adjust-textfield-hidden-by-keyboard.html


4

У Swift 4.2 імена сповіщень переміщено в інший простір імен. Отже, зараз

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


override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}


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

@objc private extension WhateverTheClassNameIs {

    func keyboardWillShow(_ notification: Notification) {
        // Do something here.
    }

    func keyboardWillHide(_ notification: Notification) {
        // Do something here.
    }
}

3

Стрімкий 5

Там відповіді вище є правильними. Хоча я волів би створити помічника для завершення notification's observers.

Перевага:

  1. Вам не потрібно повторювати кожен раз, коли ви обробляєте поведінку клавіатури.
  2. Ви можете продовжити інше сповіщення, застосувавши інше значення перерахування
  3. Це корисно, коли доводиться мати справу з клавіатурою в декількох контролерах.

Зразок коду:

extension KeyboardHelper {
    enum Animation {
        case keyboardWillShow
        case keyboardWillHide
    }

    typealias HandleBlock = (_ animation: Animation, _ keyboardFrame: CGRect, _ duration: TimeInterval) -> Void
}

final class KeyboardHelper {
    private let handleBlock: HandleBlock

    init(handleBlock: @escaping HandleBlock) {
        self.handleBlock = handleBlock
        setupNotification()
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    private func setupNotification() {
        _ = NotificationCenter.default
            .addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { [weak self] notification in
                self?.handle(animation: .keyboardWillShow, notification: notification)
            }

        _ = NotificationCenter.default
            .addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { [weak self] notification in
                self?.handle(animation: .keyboardWillHide, notification: notification)
            }
    }

    private func handle(animation: Animation, notification: Notification) {
        guard let userInfo = notification.userInfo,
            let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
            let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double
        else { return }

        handleBlock(animation, keyboardFrame, duration)
    }
}

Як використовувати:

private var keyboardHelper: KeyboardHelper?
...

override func viewDidLoad() {
   ...
   keyboardHelper = KeyboardHelper { [unowned self] animation, keyboardFrame, duration in
        switch animation {
        case .keyboardWillShow:
            print("keyboard will show")
        case .keyboardWillHide:
            print("keyboard will hide")
        }
    }

}


2

Свіфт 4 -dd 20 october 2017

override func viewDidLoad() {
    [..]

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(_:)), name: Notification.Name.UIKeyboardWillHide, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(_:)), name: Notification.Name.UIKeyboardWillShow, object: nil)
}

@objc func keyboardWillAppear(_ notification: NSNotification) {
    if let userInfo = notification.userInfo, 
       let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue).cgRectValue {
           let inset = keyboardFrame.height // if scrollView is not aligned to bottom of screen, subtract offset
           scrollView.contentInset.bottom = inset
           scrollView.scrollIndicatorInsets.bottom = inset
    }
}

@objc func keyboardWillDisappear(_ notification: NSNotification) {
    scrollView.contentInset.bottom = 0
    scrollView.scrollIndicatorInsets.bottom = 0
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

1

Якщо у вас більше одного UITextField, і вам потрібно щось зробити, коли (або раніше) клавіатура з’являється або зникає, ви можете застосувати цей підхід.

Додайте UITextFieldDelegateдо свого класу. Призначте цілочисельний лічильник, скажімо:

NSInteger editCounter; 

Встановіть для цього лічильника нуль десь у viewDidLoad. Потім впроваджуйте textFieldShouldBeginEditingта textFieldShouldEndEditingделегуйте методи.

У першому додайте 1 до editCounter. Якщо значення editCounter стає 1 - це означає, що з'явиться клавіатура (у випадку, якщо ви повернете ТАК). Якщо editCounter> 1 - це означає, що клавіатура вже видна, а інший UITextField утримує фокус.

У textFieldShouldEndEditingвіднімати 1 з editCounter. Якщо ви отримаєте нуль - клавіатура буде відхилена, інакше вона залишиться на екрані.


0

Ви можете використовувати бібліотеку KBKeyboardObserver . Він містить кілька прикладів та забезпечує простий інтерфейс.



0

Отже, це справжня відповідь зараз.

import Combine


class MrEnvironmentObject {
    /// Bind into yr SwiftUI views
    @Published public var isKeyboardShowing: Bool = false

    /// Keep 'em from deallocatin'
    var subscribers: [AnyCancellable]? = nil

    /// Adds certain Combine subscribers that will handle updating the
    ///  `isKeyboardShowing` property 
    ///
    /// - Parameter host: the UIHostingController of your views. 
    func setupSubscribers<V: View>(
        host: inout UIHostingController<V>
    ) {
        subscribers = [
            NotificationCenter
                .default
                .publisher(for: UIResponder.keyboardWillShowNotification)
                .sink { [weak self] _ in
                    self?.isKeyboardShowing = true
                },
            NotificationCenter
                .default
                .publisher(for: UIResponder.keyboardWillHideNotification)
                .sink { [weak self, weak host] _ in
                    self?.isKeyboardShowing = false
                    // Hidden gem, ask me how I know:
                    UIAccessibility.post(
                        notification: .layoutChanged, 
                        argument: host
                    )
                },
            // ...
            Profit
                .sink { [weak self] profit in profit() },
        ]
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.