キーボードが表示されたときにビューを上に移動するためのコードを追加しようとしましたが、Objective-Cの例をSwiftに変換しようとして問題があります。私はいくつかの進歩を遂げましたが、1つの特定の行に固執しています。
これらは、私がフォローしている2つのチュートリアル/質問です。
Swiftを使用してキーパッドが表示されるときにUIViewControllerのコンテンツを上に移動する方法http://www.ioscreator.com/tutorials/move-view-when-keyboard-appears
私が現在持っているコードは次のとおりです。
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) {
//
}
現時点では、この行でエラーが発生しています:
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
誰かがこのコード行がどうあるべきかを私に知らせることができたら、私は自分で残りを理解することができます。
あなたのラインにいくつかの問題があります
var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
notification.userInfo
はoptional辞書[NSObject : AnyObject]?
を返すため、値にアクセスする前にラップを解除する必要があります。NSDictionary
はSwiftネイティブ辞書にマップされるため、値にアクセスするには辞書添え字構文(dict[key]
)を使用する必要があります。NSValue
にキャストして、CGRectValue
を呼び出すことができるようにする必要があります。これはすべて、オプションの割り当て、オプションのチェーン、オプションのキャストの組み合わせで実現できます。
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
} else {
// no UIKeyboardFrameBeginUserInfoKey entry in userInfo
}
} else {
// no userInfo dictionary in notification
}
または1ステップで:
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
}
Swift 3.0.1(Xcode 8.1)のアップデート:
if let userInfo = notification.userInfo {
if let keyboardSize = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
} else {
// no UIKeyboardFrameBeginUserInfoKey entry in userInfo
}
} else {
// no userInfo dictionary in notification
}
または1ステップで:
if let keyboardSize = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
// ...
}
さらに少ないコードについては、 THIS を検討してください。
本当に助かりました。 View ControllerにView Constraintを追加し、追加した2つのオブザーバーを使用するだけです。次に、次のメソッドを使用します(ここでは、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()
})
}
}
}
そして
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() })
}
} }
ビュー自体を操作するのではなく、ストーリーボードを使用している場合は、自動レイアウトを利用できます。
(これは、ニコラスの回答のクリーンアップバージョンです)
キーボードの出現と消失を通知する通知センターをセットアップします。
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)
}
オブザーバーが不要になったら、必ず削除してください。
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)
}
ストーリーボード内で、下部の制約を設定します。その制約のアウトレットを作成します。
キーボードを表示または非表示にするときに制約の定数プロパティを設定します。
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()
}
これで、キーボードが表示または非表示になるたびに、自動レイアウトがすべてを処理します。
スイフト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
}
Swift
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
}
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()
Swift 3:UPDATE
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)
}
キーボードからのデータを使用して、制約またはその他の値をキーボードのサイズに拡大または縮小できます。通知の表示/非表示を切り替えました。
この最小限のコードは、キーボードがサイズに基づいて制約を表示および更新することを通知するために登録します。
@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
}
}
同様に、これはキーボードのサイズに基づいてスクロールビューのコンテンツインセットを更新します。
@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
}
}
この1行を自分の回線に使用できます
var keyboardSize:CGSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue().size
Xamarinの場合、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;
}
Swift 3.
キーボードサイズを取得し、それを使用してビューを上方向にアニメートする例を次に示します。私の場合、ユーザーが入力を開始したときにUITextFieldsを含むUIViewを上に移動して、フォームに入力し、下部にある送信ボタンが表示されるようにします。
アニメーション化したいビューのbottom space constraintにアウトレットを追加し、myViewsBottomSpaceConstraint
という名前を付けました。
@IBOutlet weak var myViewsBottomSpaceConstraint: NSLayoutConstraint!
次に、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()
}
xCode 8.2.1、Swift 3
KeyboardNotifications
import Foundation
class KeyboardNotifications {
fileprivate var _isEnabled: Bool
fileprivate var notifications: [KeyboardNotificationsType]
fileprivate 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(KeyboardNotifications.keyboardWillShow(notification:))
case .willHide:
return #selector(KeyboardNotifications.keyboardWillHide(notification:))
case .didShow:
return #selector(KeyboardNotifications.keyboardDidShow(notification:))
case .didHide:
return #selector(KeyboardNotifications.keyboardDidHide(notification:))
}
}
var notificationName: NSNotification.Name {
switch self {
case .willShow:
return .UIKeyboardWillShow
case .willHide:
return .UIKeyboardWillHide
case .didShow:
return .UIKeyboardDidShow
case .didHide:
return .UIKeyboardDidHide
}
}
}
}
// MARK: - isEnabled
extension KeyboardNotifications {
private func addObserver(type: KeyboardNotificationsType) {
NotificationCenter.default.addObserver(self, selector: type.selector, name: type.notificationName, object: nil)
print("\(type.notificationName.rawValue) inited")
}
var isEnabled: Bool {
set {
if newValue {
for notificaton in notifications {
addObserver(type: notificaton)
}
} else {
NotificationCenter.default.removeObserver(self)
print("Keyboard notifications deinited")
}
_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)
}
}
KeyboardNotificationsDelegate
import Foundation
@objc
protocol KeyboardNotificationsDelegate {
@objc optional func keyboardWillShow(notification: NSNotification)
@objc optional func keyboardWillHide(notification: NSNotification)
@objc optional func keyboardDidShow(notification: NSNotification)
@objc optional func keyboardDidHide(notification: NSNotification)
}
class ViewController: UIViewController {
private var keyboardNotifications: KeyboardNotifications!
override func viewDidLoad() {
super.viewDidLoad()
...
keyboardNotifications = 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) {
...
}
// If you don't need this func you can remove it
func keyboardWillHide(notification: NSNotification) {
...
}
// If you don't need this func you can remove it
func keyboardDidShow(notification: NSNotification) {
...
}
// If you don't need this func you can remove it
func keyboardDidHide(notification: NSNotification) {
...
}
}
import UIKit
class ViewController: UIViewController {
private var keyboardNotifications: KeyboardNotifications!
private var textField = UITextField(frame: CGRect(x: 40, y: 40, width: 200, height: 30))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textField)
// when you will tap on view (background) the keyboard will hide
// read about view.disableKeybordWhenTapped here: http://stackoverflow.com/a/42187286/4488252
view.disableKeybordWhenTapped = true
keyboardNotifications = 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")
let userInfo = notification.userInfo as! [String: NSObject]
let keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect
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")
}
}
in Swift 4.2 UIResponder.keyboardFrameEndUserInfoKeyを使用できます
guard let userInfo = notification.userInfo , let keyboardFrame:CGRect = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }```