Próbowałem dodać kod, aby przesunąć widok w górę, gdy pojawia się klawiatura, jednak mam problemy z próbą przetłumaczenia przykładów Objective-C na Swift. Zrobiłem pewne postępy, ale utknąłem na jednej konkretnej linii.
Oto dwa samouczki / pytania, które obserwowałem:
Jak przenieść zawartość UIViewController w górę, gdy klawiatura pojawia się za pomocą Swift http://www.ioscreator.com/tutorials/move-view-when-keyboard-appears
Oto kod, który obecnie mam:
override func viewWillAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillShow(notification: NSNotification) {
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
let frame = self.budgetEntryView.frame
frame.origin.y = frame.origin.y - keyboardSize
self.budgetEntryView.frame = frame
}
func keyboardWillHide(notification: NSNotification) {
//
}
W tej chwili otrzymuję błąd w tej linii:
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
Gdyby ktoś mógł mi powiedzieć, jaki powinien być ten wiersz kodu, resztę powinienem sam wymyślić.
źródło
Aby uzyskać jeszcze mniej kodu, rozważ spojrzenie na TO
To było dla mnie bardzo pomocne. Musisz po prostu uwzględnić ograniczenie widoku w kontrolerze widoku i użyć dwóch dodanych obserwatorów. Następnie użyj następujących metod (przypuszcza się, że tutaj przenosisz tableView)
func keyboardWillShow(sender: NSNotification) { if let userInfo = sender.userInfo { if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size.height { tableViewBottomConstraint.constant = keyboardHeight UIView.animateWithDuration(0.25, animations: { () -> Void in self.view.layoutIfNeeded() }) } } }
i
func keyboardWillHide(sender: NSNotification) { if let userInfo = sender.userInfo { if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size.height { tableViewBottomConstraint.constant = 0.0 UIView.animateWithDuration(0.25, animations: { () -> Void in self.view.layoutIfNeeded() }) } } }
źródło
Jeśli używasz scenorysu, zamiast manipulować samym widokiem, możesz skorzystać z automatycznego układu.
(To jest oczyszczona wersja odpowiedzi Nicholasa)
Skonfiguruj centrum powiadomień, aby powiadamiało Cię o pojawieniu się i zniknięciu klawiatury:
override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil) }
I upewnij się, że usuwasz obserwatory, gdy ich już nie potrzebujesz:
override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window) }
W serii ujęć ustaw dolne ograniczenie. Utwórz ujście tego ograniczenia:
i ustaw stałą właściwość ograniczenia, gdy klawiatura jest pokazywana lub ukrywana:
func keyboardWillShow(notification: NSNotification) { guard let keyboardHeight = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue.size.height else { return } nameOfOutlet.constant = keyboardHeight view.layoutIfNeeded() } func keyboardWillHide(notification: NSNotification) { nameOfOutlet.constant = 0.0 view.layoutIfNeeded() }
Teraz, gdy klawiatura pojawi się lub zniknie, autoukład zajmie się wszystkim.
źródło
Szybki 2
func keyboardWasShown(notification:NSNotification) { guard let info:[NSObject:AnyObject] = notification.userInfo, let keyboardSize:CGSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size else { return } let insets:UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0.0, keyboardSize.height, 0.0) self.scrollView.contentInset = insets self.scrollView.scrollIndicatorInsets = insets }
Szybki 3
func keyboardWasShown(notification:NSNotification) { guard let info:[AnyHashable:Any] = notification.userInfo, let keyboardSize:CGSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size else { return } let insets:UIEdgeInsets = UIEdgeInsets(top: self.scrollView.contentInset.top, left: 0.0, bottom: keyboardSize.height, right: 0.0) self.scrollView.contentInset = insets self.scrollView.scrollIndicatorInsets = insets }
źródło
Pomogło mi to: https://developer.apple.com/library/ios/samplecode/UICatalog/Listings/Swift_UICatalog_TextViewController_swift.html
let userInfo = notification.userInfo! let animationDuration: NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as NSNumber).doubleValue let keyboardScreenBeginFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as NSValue).CGRectValue() let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue()
źródło
Możesz użyć tej jednej linii dla swojej linii
var keyboardSize:CGSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue().size
źródło
Swift 3: AKTUALIZACJA
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window) }
źródło
Swift - wysokość klawiatury z keyboardWillShowNotification
Możesz zwiększyć lub zmniejszyć ograniczenie lub dowolną inną wartość do rozmiaru klawiatury, używając danych z klawiatury. Pokaż / ukryje powiadomienia.
Z ograniczeniem układu
Ten minimalny kod rejestruje się w celu powiadomienia, że klawiatura pokaże i zaktualizuje ograniczenie w oparciu o jego rozmiar.
@IBOutlet weak var keyboardConstraint: NSLayoutConstraint! let keyboardConstraintMargin:CGFloat = 20 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { (notification) in if let keyboardSize = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? CGRect { self.keyboardConstraint.constant = keyboardSize.height + self.keyboardConstraintMargin } } NotificationCenter.default.addObserver(forName: UIResponder.keyboardDidHideNotification, object: nil, queue: nil) { (notification) in self.keyboardConstraint.constant = self.keyboardConstraintMargin } }
Z ScrollView
W ten sam sposób aktualizuje wstawkę zawartości widoku przewijania na podstawie rozmiaru klawiatury.
@IBOutlet weak var scrollView: UIScrollView! override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { (notification) in if let keyboardSize = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? CGRect { let insets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0) self.scrollView.contentInset = insets self.scrollView.scrollIndicatorInsets = insets } } NotificationCenter.default.addObserver(forName: UIResponder.keyboardDidHideNotification, object: nil, queue: nil) { (notification) in let insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) self.scrollView.contentInset = insets self.scrollView.scrollIndicatorInsets = insets } }
źródło
Detale
Rozwiązanie
import UIKit protocol KeyboardNotificationsDelegate: class { func keyboardWillShow(notification: NSNotification) func keyboardWillHide(notification: NSNotification) func keyboardDidShow(notification: NSNotification) func keyboardDidHide(notification: NSNotification) } extension KeyboardNotificationsDelegate { func keyboardWillShow(notification: NSNotification) {} func keyboardWillHide(notification: NSNotification) {} func keyboardDidShow(notification: NSNotification) {} func keyboardDidHide(notification: NSNotification) {} } class KeyboardNotifications { fileprivate var _isEnabled: Bool fileprivate var notifications: [KeyboardNotificationsType] fileprivate weak var delegate: KeyboardNotificationsDelegate? init(notifications: [KeyboardNotificationsType], delegate: KeyboardNotificationsDelegate) { _isEnabled = false self.notifications = notifications self.delegate = delegate } deinit { if isEnabled { isEnabled = false } } } // MARK: - enums extension KeyboardNotifications { enum KeyboardNotificationsType { case willShow, willHide, didShow, didHide var selector: Selector { switch self { case .willShow: return #selector(keyboardWillShow(notification:)) case .willHide: return #selector(keyboardWillHide(notification:)) case .didShow: return #selector(keyboardDidShow(notification:)) case .didHide: return #selector(keyboardDidHide(notification:)) } } var notificationName: NSNotification.Name { switch self { case .willShow: return UIResponder.keyboardWillShowNotification case .willHide: return UIResponder.keyboardWillHideNotification case .didShow: return UIResponder.keyboardDidShowNotification case .didHide: return UIResponder.keyboardDidHideNotification } } } } // MARK: - isEnabled extension KeyboardNotifications { private func addObserver(type: KeyboardNotificationsType) { NotificationCenter.default.addObserver(self, selector: type.selector, name: type.notificationName, object: nil) } var isEnabled: Bool { set { if newValue { for notificaton in notifications { addObserver(type: notificaton) } } else { NotificationCenter.default.removeObserver(self) } _isEnabled = newValue } get { return _isEnabled } } } // MARK: - Notification functions extension KeyboardNotifications { @objc func keyboardWillShow(notification: NSNotification) { delegate?.keyboardWillShow(notification: notification) } @objc func keyboardWillHide(notification: NSNotification) { delegate?.keyboardWillHide(notification: notification) } @objc func keyboardDidShow(notification: NSNotification) { delegate?.keyboardDidShow(notification: notification) } @objc func keyboardDidHide(notification: NSNotification) { delegate?.keyboardDidHide(notification: notification) } }
Stosowanie
class ViewController: UIViewController { private lazy var keyboardNotifications: KeyboardNotifications! = { return KeyboardNotifications(notifications: [.willShow, .willHide, .didShow, .didHide], delegate: self) }() override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) keyboardNotifications.isEnabled = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) keyboardNotifications.isEnabled = false } } extension ViewController: KeyboardNotificationsDelegate { // If you don't need this func you can remove it func keyboardWillShow(notification: NSNotification) { print("keyboardWillShow") guard let userInfo = notification.userInfo as? [String: NSObject], let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } print("keyboardFrame: \(keyboardFrame)") } // If you don't need this func you can remove it func keyboardWillHide(notification: NSNotification) { print("keyboardWillHide") } // If you don't need this func you can remove it func keyboardDidShow(notification: NSNotification) { print("keyboardDidShow") } // If you don't need this func you can remove it func keyboardDidHide(notification: NSNotification) { print("keyboardDidHide") } }
Pełna próbka
import UIKit class ViewController: UIViewController { private lazy var keyboardNotifications: KeyboardNotifications! = { return KeyboardNotifications(notifications: [.willShow, .willHide, .didShow, .didHide], delegate: self) }() override func viewDidLoad() { super.viewDidLoad() let textField = UITextField(frame: CGRect(x: 40, y: 40, width: 200, height: 30)) textField.borderStyle = .roundedRect view.addSubview(textField) let gesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))) view.addGestureRecognizer(gesture) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) keyboardNotifications.isEnabled = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) keyboardNotifications.isEnabled = false } } extension ViewController: KeyboardNotificationsDelegate { // If you don't need this func you can remove it func keyboardWillShow(notification: NSNotification) { print("keyboardWillShow") guard let userInfo = notification.userInfo as? [String: NSObject], let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return } print("keyboardFrame: \(keyboardFrame)") } // If you don't need this func you can remove it func keyboardWillHide(notification: NSNotification) { print("keyboardWillHide") } // If you don't need this func you can remove it func keyboardDidShow(notification: NSNotification) { print("keyboardDidShow") } // If you don't need this func you can remove it func keyboardDidHide(notification: NSNotification) { print("keyboardDidHide") } }
Wynik
Log
źródło
Swift 3.0
Oto przykład pobierania rozmiaru klawiatury i używania go do animowania widoku w górę. W moim przypadku przesuwam UIView zawierający moje UITextFields w górę, gdy użytkownik zaczyna pisać, aby mógł wypełnić formularz i nadal widzieć przycisk przesyłania u dołu.
Dodałem wylot do ograniczenia dolnej przestrzeni widoku, który chciałem animować i nazwałam go
myViewsBottomSpaceConstraint
:@IBOutlet weak var myViewsBottomSpaceConstraint: NSLayoutConstraint!
Następnie dodałem następujący kod do mojej klasy Swift:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window) } func keyboardWillShow(notification: NSNotification) { let userInfo = notification.userInfo as! [String: NSObject] as NSDictionary let keyboardFrame = userInfo.value(forKey: UIKeyboardFrameEndUserInfoKey) as! CGRect let keyboardHeight = keyboardFrame.height myViewsBottomSpaceConstraint.constant = keyboardHeight view.layoutIfNeeded() } func keyboardWillHide(notification: NSNotification) { myViewsBottomSpaceConstraint.constant = 0.0 view.layoutIfNeeded() }
źródło
W przypadku platformy Xamarin można użyć języka C # 6
private void KeyboardWillChangeFrame(NSNotification notification) { var keyboardSize = notification.UserInfo.ValueForKey(UIKeyboard.FrameEndUserInfoKey) as NSValue; if (keyboardSize != null) { var rect= keyboardSize.CGRectValue; //do your stuff here } }
c # 7
private void KeyboardWillChangeFrame(NSNotification notification) { if (!(notification.UserInfo.ValueForKey(UIKeyboard.FrameEndUserInfoKey) is NSValue keyboardSize)) return; var rect= keyboardSize.CGRectValue; }
źródło
w Swift 4.2 możesz użyć UIResponder.keyboardFrameEndUserInfoKey
guard let userInfo = notification.userInfo , let keyboardFrame:CGRect = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }```
źródło