không thể nhận được giá trị chính xác của chiều cao bàn phím trong iOS8


83

Tôi đang sử dụng mã này để xác định kích thước của bàn phím:

- (void)keyboardWillChange:(NSNotification *)notification {
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

}

Tôi đang chạy điều này trong trình mô phỏng.

Vấn đề là kể từ iOS 8, điều này sẽ không cung cấp giá trị chính xác, nếu các đề xuất bàn phím được nâng lên hoặc nếu tôi đẩy chúng xuống, tôi sẽ nhận được các giá trị khác nhau (không đúng).

Làm cách nào để có được kích thước chính xác của bàn phím bao gồm các gợi ý bàn phím?


Nó có thể hữu ích nếu bạn chuyển đổi keyboardFrameBeginRectsang tọa độ địa phương.
rmaddy

@rmaddy nó không thực sự quan trọng, tôi chỉ cần chiều cao.
Eli Braginskiy

Điều này có thể sai tùy thuộc vào định hướng. Mặc dù đó có thể không còn là vấn đề trong iOS 8. Tuy nhiên, hãy thử và xem liệu nó có tạo ra sự khác biệt hay không.
rmaddy

@rmaddy Tôi đã thử nó nhưng đáng tiếc nó đã không giúp đỡ
Eli Braginskiy

Câu trả lời:


98

Sử dụng

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

Câu trả lời chính xác. Cảm ơn. Làm thế nào bạn thấy rằng bạn nên sử dụng khóa đó? @souvickcse
Julian Osorio

6
CGRect keyboardFrame = [keyboardFrameBegin CGRectValue];
Awesomeness

12
Không làm việc cho tôi, bàn phím vẫn còn 258, quá cao
marchinram

Cảm ơn bạn @trycatchfinally
souvickcse

1
đã học một bài học hôm nay. Có một sự khác biệt lớn trong UIKeyboardFrameEndUserInfoKey và UIKeyboardFrameBeginUserInfoKey. Cảm ơn bạn @souvickcse
jejernig 29/09/17

120

Với sự ra đời của bàn phím tùy chỉnh trong iOS, vấn đề này trở nên phức tạp hơn.

Tóm lại, UIKeyboardWillShowNotification có thể được gọi nhiều lần bằng cách triển khai bàn phím tùy chỉnh:

  1. Khi bàn phím hệ thống của Apple được mở (ở chế độ dọc )
    • UIKeyboardWillShowNotification được gửi với chiều cao bàn phím là 224
  2. Khi bàn phím Swype được mở (ở chế độ dọc ):
    • UIKeyboardWillShowNotification được gửi với độ cao bàn phím là 0
    • UIKeyboardWillShowNotification được gửi với chiều cao bàn phím là 216
    • UIKeyboardWillShowNotification được gửi với chiều cao bàn phím là 256
  3. Khi bàn phím SwiftKey được mở (ở chế độ dọc ):
    • UIKeyboardWillShowNotification được gửi với độ cao bàn phím là 0
    • UIKeyboardWillShowNotification được gửi với chiều cao bàn phím là 216
    • UIKeyboardWillShowNotification được gửi với chiều cao bàn phím là 259

Để xử lý các tình huống này đúng cách trong một dòng mã, bạn cần:

Đăng ký nhà quan sát so với UIKeyboardWillShowNotificationUIKeyboardWillHideNotification thông báo:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];    
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];

Tạo một biến toàn cục để theo dõi chiều cao bàn phím hiện tại:

CGFloat _currentKeyboardHeight = 0.0f;

Triển khai keyboardWillShow để phản ứng với sự thay đổi hiện tại về chiều cao bàn phím:

- (void)keyboardWillShow:(NSNotification*)notification {
   NSDictionary *info = [notification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
   CGFloat deltaHeight = kbSize.height - _currentKeyboardHeight; 
   // Write code to adjust views accordingly using deltaHeight
   _currentKeyboardHeight = kbSize.height;
}

LƯU Ý: Bạn có thể muốn tạo hoạt ảnh cho việc bù trừ các chế độ xem. Các thông tin từ điển chứa một giá trị keyed bởi UIKeyboardAnimationDurationUserInfoKey . Giá trị này có thể được sử dụng để tạo hoạt ảnh cho các thay đổi của bạn ở cùng tốc độ khi bàn phím được hiển thị.

Triển khai keyboardWillHide to the reset _currentKeyboardHeight và phản ứng với việc bàn phím bị loại bỏ:

- (void)keyboardWillHide:(NSNotification*)notification {
   NSDictionary *info = [notification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
   // Write code to adjust views accordingly using kbSize.height
   _currentKeyboardHeight = 0.0f;
}

dgangsta, nghiên cứu của bạn rất thú vị, nhưng vấn đề của câu hỏi chỉ là lấy FrameBegin thay vì thuộc tính FrameEnd. Theo câu trả lời của bạn, bạn đã cân nhắc sử dụng cờ UIViewAnimationOptionBeginFromCurrentState cho phương pháp xem hoạt ảnh thay vì delta chưa?
MikeR

Thay vì 259 cho chiều cao SwiftKey (v 1.2.3), tôi nhận được 271 trong iPhone6 ​​+ với iOS8.1.3.
Hemang

2
Nó vẫn là một giải pháp làm việc? Khi sử dụng SwiftKey tôi nhận được một chiều cao của 44 thay vì 259.
KIDdAe

Thật điên rồ, điều này đã giúp tôi, nhưng tôi cần chiều cao của bàn phím sau khi nó đã hiển thị, vì vậy tôi quan sát keyboardDidShow: thay vào đó. Tại sao các bàn phím tùy chỉnh này kích hoạt 3 thông báo trong khi Apple chỉ kích hoạt một thông báo? Có vẻ không nhất quán.
Liron Yahdav

Nếu bạn đang gặp sự cố với iPhone ở chế độ ngang như tôi đã từng gặp phải, đó là do phím KẾT THÚC trong khung có nguồn gốc sai (ít nhất là đối với bàn phím iOS 10 thông thường). KEYBOARD BEGIN RECT: (0.0, 375.0, 667.0, 162.0) ... KEYBOARD END RECT: (0.0, 213.0, 667.0, 162.0)
xaphod

18

Tôi cũng gặp sự cố này cho đến khi tôi xem qua bài viết StackOverflow này:

Chuyển đổi UIKeyboardFrameEndUserInfoKey

Điều này cho bạn thấy cách sử dụng convertRectchức năng, để chuyển đổi kích thước của bàn phím thành thứ gì đó có thể sử dụng được, nhưng trên hướng màn hình.

NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];

Trước đây, tôi có một ứng dụng iPad được sử dụng UIKeyboardFrameEndUserInfoKeynhưng không sử dụng convertRectvà nó hoạt động tốt.

Nhưng với iOS 8, nó không còn hoạt động bình thường nữa. Đột nhiên, nó sẽ báo cáo rằng bàn phím của tôi, đang chạy trên iPad ở chế độ ngang, cao 1024 pixel .

Vì vậy, bây giờ, với iOS 8, điều cần thiết là bạn phải sử dụng convertRectchức năng này .


Trước iOS8, bàn phím luôn ở tọa độ màn hình hướng dọc. Tôi đã thêm mã để hoán đổi chiều cao và chiều rộng theo cách thủ công khi ở chế độ ngang, nhưng điều đó đã xảy ra trên iOS 8. trong đó hướng trực tràng bàn phím khớp với hướng xem. Giải pháp convertRect đưa ra kết quả chính xác cho iOS 7 hoặc iOS 8.
user1055568

7

Tương tự như giải pháp của dgangsta được viết bằng Swift 2.0:

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    guard let kbSizeValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
    animateToKeyboardHeight(kbSizeValue.CGRectValue().height, duration: kbDurationNumber.doubleValue)
}

func keyboardWillHide(notification: NSNotification) {
    guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
    animateToKeyboardHeight(0, duration: kbDurationNumber.doubleValue)
}

func animateToKeyboardHeight(kbHeight: CGFloat, duration: Double) {
    // your custom code here
}

vấn đề khi bạn hiển thị / ẩn quickType, và cũng là cười
user3722523

Đây là nước sốt. Sự khác biệt nhỏ trong Swift 2.3 nhưng đó là một đề xuất tự động hoàn thành từ trình biên dịch nên không có vấn đề gì.
Ethan Parker

5

Tôi làm extensionchoUIViewController

extension UIViewController {
    func keyboardWillChangeFrameNotification(notification: NSNotification, scrollBottomConstant: NSLayoutConstraint) {
        let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
        let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
        let keyboardBeginFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
        let keyboardEndFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()

        let screenHeight = UIScreen.mainScreen().bounds.height
        let isBeginOrEnd = keyboardBeginFrame.origin.y == screenHeight || keyboardEndFrame.origin.y == screenHeight
        let heightOffset = keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0)

        UIView.animateWithDuration(duration.doubleValue,
            delay: 0,
            options: UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16)),
            animations: { () in
                scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset
                self.view.layoutIfNeeded()
            },
            completion: nil
        )
    }
}

Bạn có thể sử dụng như thế này:

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChangeFrameNotification:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}

...

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillChangeFrameNotification(notification: NSNotification) {
    self.keyboardWillChangeFrameNotification(notification, scrollBottomConstant: inputContainerBottom)
    // Write more to here if you want.
}

Wanbok Choi, các lượt xem được sử dụng để làm inputContainerBottomgì?
Nathaniel Blumer

@Nathaniel UITextField hoặc các ràng buộc về không gian dưới cùng của UITextView từ bottomLayout. ;) Tôi đã chỉnh sửa nó trong dự án của mình. Tôi sẽ đăng lại nó
Wanbok Choi

4

Đôi khi các nhà phát triển cần biết chiều cao bàn phím trước khi nó thực sự được hiển thị, cho phép họ bố trí trước giao diện một cách thích hợp.

Nếu đúng như vậy, đây là thông số kỹ thuật bao gồm:

nhập mô tả hình ảnh ở đây

Điều này bao gồm thanh gõ nhanh ở trên cùng, vì thanh này được bật theo mặc định trong tất cả các phiên bản iOS hiện tại.

Đây là thiết lập thông báo nhanh 3 mà tôi đã sử dụng để kiểm tra điều này, nếu có ai cần nó:

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

func keyboardWillShow(notification: NSNotification) {
    guard let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    print("\(keyboardSize)")
}

1

Chỉ một chuỗi cho nhanh:

let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size

UIKeyboardFrameEndUserInfoKeyluôn luôn các cửa hàng NSValue, vì vậy không cần phải kiểm tra nó.


0

Tôi nhận thấy sự cố hiển thị khi chuyển đổi giữa bàn phím mặc định và bàn phím tùy chỉnh ( UIPickerView) - bàn phím tùy chỉnh sẽ hiển thị chiều cao 253 thay vì 162, sau khi chuyển từ bàn phím mặc định.

Điều hoạt động trong trường hợp này là thiết lập autocorrectionType = UITextAutocorrectionTypeNo;trường nhập liệu bằng bàn phím tùy chỉnh.

Sự cố chỉ xảy ra trong iOS 8 (chỉ được thử nghiệm trên trình mô phỏng). Nó không xảy ra trong iOS 9 (trình mô phỏng hoặc thiết bị).


0

Trong Swift, không phải trong một dòng ...

self.keyboardDidShowObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { (notification) in
        if let userInfo = notification.userInfo, let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
            let keyboardRect = keyboardFrameValue.CGRectValue()
            // keyboardRect.height gives the height of the keyboard
            // your additional code here...
        }
    })

0
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {

    float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

}];
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.