วิธีตรวจจับเมื่อแสดงและซ่อนแป้นพิมพ์


คำตอบ:


168

ในเมธอด 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 คุณหมายความว่าแป้นพิมพ์ไม่แสดงถ้าคุณแท็บ?
Matthew Frederick

หากยังมีฟิลด์ครอบคลุมโดยแป้นพิมพ์ด้านล่างอันที่มีโฟกัสมุมมองจะยังคงอยู่บนแท็บเนื่องจากมีการส่งการแจ้งเตือนในขณะที่แป้นพิมพ์เลื่อนขึ้นเท่านั้น
i--

3
@apprentice คุณต้องจัดการมันด้วยมือโดยเลื่อน scrollview ไปรอบ ๆ โดยขึ้นอยู่กับแต่ละช่องข้อความที่ใช้งานอยู่ซึ่งเป็นปัญหาที่แตกต่างจากการรู้ว่าคีย์บอร์ดปรากฏขึ้นเมื่อใด กำหนดตัวควบคุมมุมมองของคุณเป็นUITextFieldDelegate จากนั้นใช้textFieldShouldReturn:วิธีการ คุณจะได้รับtextFieldเพียงแค่ป้อนเป็นอาร์กิวเมนต์ซึ่งคุณสามารถเปรียบเทียบกับฟิลด์ข้อความของคุณเองและเลื่อนscrollViewเพื่อให้ฟิลด์ข้อความที่เหมาะสมแสดง
Matthew Frederick

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)
}

Swift 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)
}

Swift รุ่นเก่า

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

เป็นความจริงโปรดแก้ไขคำตอบ ฉันจะยอมรับมัน
Esqarrouth

@FouZ จะดีกว่าไหมถ้าจะเอาผู้สังเกตการณ์ออกจากdeinitแบบนี้:deinit { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) }
Crashalot

ใน Swift 3 บล็อกโค้ด deinit ข้างต้นเป็นดังนี้:deinit { NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) }
Md. Najmul Hasan

@Crashalot deinit ไม่ทำงานจนกว่าคุณจะยกเลิก vc ดังนั้นหากคุณนำเสนอ vc อื่นที่ด้านบนของอันนี้จะยังคงได้รับการแจ้งเตือน ฉันเชื่อว่าจุดประสงค์คือเพื่อฟังการแจ้งเตือนนี้เท่านั้นในขณะที่ vc นี้สามารถมองเห็นได้ดังนั้นการเพิ่มใน viewdidappear และการลบออกใน viewdiddissapear ดูเหมือนจะดีกว่าสำหรับฉัน
Pochi

19

Swift 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

Swift 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)
}

+=ปรากฏขึ้นเพื่อให้ขุ่นได้รับมีขนาดใหญ่และมีขนาดใหญ่
Wez

ฉันคิดว่าฟังก์ชัน adjustKeyboardShow เป็นฟังก์ชันที่ทำออกมาได้ดีมาก ขอขอบคุณ.
นักพัฒนาชาวฮ่องกง

เป็นของสวิฟท์ 5 ชื่อแจ้งเตือนUIResponder.keyboardWillShowNotificationและและคีย์ข้อมูลแป้นพิมพ์เป็นUIResponder.keyboardWillHideNotification UIResponder.keyboardFrameBeginUserInfoKey
CodeBrew

7

สวิฟต์ 5

มีคำตอบด้านบนที่ถูกต้อง แม้ว่าฉันต้องการสร้างตัวช่วยในการสรุปไฟล์notification's observers.

ผลประโยชน์:

  1. คุณไม่จำเป็นต้องทำซ้ำทุกครั้งที่จัดการกับลักษณะการทำงานของแป้นพิมพ์
  2. คุณสามารถขยายการแจ้งเตือนอื่น ๆ ได้โดยใช้ค่า enum อื่น ๆ
  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")
        }
    }

}


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) {

}

5

ใน 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.
    }
}

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


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 - หมายความว่าคีย์บอร์ดจะปรากฏขึ้น (ในกรณีที่คุณส่งคืน YES) หาก editCounter> 1 - หมายความว่าแป้นพิมพ์สามารถมองเห็นได้แล้วและ UITextField อื่นจะจับโฟกัส

ในการtextFieldShouldEndEditingลบ 1 จาก editCounter หากคุณได้ศูนย์ - แป้นพิมพ์จะถูกปิดมิฉะนั้นจะยังคงอยู่บนหน้าจอ




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() },
        ]
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.