ビューの下半分にテキストフィールドを持つアプリがあります。つまり、テキストフィールドに入力すると、キーボードがテキストフィールドを覆います。
入力中にビューを上に移動して、入力した内容を確認し、キーボードが消えたら元の位置に戻す方法を説明します。
私はいたるところを見ましたが、すべての解決策はObj-Cにあるように見えますが、まだ変換することはできません。
任意の助けは大歓迎です。
これは、あるtextFieldから別のtextFieldへの切り替えを処理しない、解決策です。
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)
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.Origin.y -= keyboardSize.height
}
}
func keyboardWillHide(notification: NSNotification) {
self.view.frame.Origin.y = 0
}
これを解決するには、2つの関数keyboardWillShow/Hide
を次の関数に置き換えます。
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
if view.frame.Origin.y == 0 {
self.view.frame.Origin.y -= keyboardSize.height
}
}
}
func keyboardWillHide(notification: NSNotification) {
if view.frame.Origin.y != 0 {
self.view.frame.Origin.y = 0
}
}
override func viewDidLoad() {
super.viewDidLoad()
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)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0 {
self.view.frame.Origin.y -= keyboardSize.height
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.Origin.y != 0 {
self.view.frame.Origin.y = 0
}
}
Swift 4.0用の編集:
override func viewDidLoad() {
super.viewDidLoad()
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)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0 {
self.view.frame.Origin.y -= keyboardSize.height
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.Origin.y != 0 {
self.view.frame.Origin.y = 0
}
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0 {
self.view.frame.Origin.y -= keyboardSize.height
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.Origin.y != 0 {
self.view.frame.Origin.y = 0
}
}
コードを必要としない最も簡単な方法:
オブジェクトはキーボードと同期して自動的に上に移動します。
このスレッドに関する一般的な回答の1つは、次のコードを使用しています。
func keyboardWillShow(sender: NSNotification) {
self.view.frame.Origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
self.view.frame.Origin.y += 150
}
あなたの見解を静的な量だけオフセットすることには明らかな問題があります。あるデバイスでは見栄えがよくなりますが、それ以外のサイズの設定では見栄えが悪くなります。キーボードの高さを取得し、それをオフセット値として使用する必要があります。
これは すべてのデバイスで機能する そしてユーザーが入力中に予測テキストフィールドを隠すEdge-caseを処理する解決策です。
以下で注意することが重要です、我々は我々のオブジェクトパラメータとしてself.view.windowを渡しています。これにより、キーボードからの高さなどのデータが得られます。
@IBOutlet weak var messageField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)
}
func keyboardWillHide(sender: NSNotification) {
let userInfo: [NSObject : AnyObject] = sender.userInfo!
let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
self.view.frame.Origin.y += keyboardSize.height
}
すべてのデバイスで見栄えをよくし、ユーザーが予測テキストフィールドを追加または削除した場合を処理します。
func keyboardWillShow(sender: NSNotification) {
let userInfo: [NSObject : AnyObject] = sender.userInfo!
let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size
if keyboardSize.height == offset.height {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.Origin.y -= keyboardSize.height
})
} else {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.Origin.y += keyboardSize.height - offset.height
})
}
}
不要なメッセージが送信されるのを防ぐために、ビューから出る前にオブザーバを削除することを忘れないでください。
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}
コメントからの質問に基づいて更新する:
2つ以上のテキストフィールドがある場合は、view.frame.Origin.yがゼロになっているかどうかを確認できます。
func keyboardWillShow(sender: NSNotification) {
let userInfo: [NSObject : AnyObject] = sender.userInfo!
let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size
if keyboardSize.height == offset.height {
if self.view.frame.Origin.y == 0 {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.Origin.y -= keyboardSize.height
})
}
} else {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.Origin.y += keyboardSize.height - offset.height
})
}
print(self.view.frame.Origin.y)
}
これをあなたのビューコントローラに追加してください。魅力のように働きます。値を調整するだけです。
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
}
@objc func keyboardWillShow(sender: NSNotification) {
self.view.frame.Origin.y -= 150
}
@objc func keyboardWillHide(sender: NSNotification) {
self.view.frame.Origin.y += 150
}
私はそれが1つのページの異なるキーボードと異なるテキストビュー/フィールドで動作するように答えの1つを少し改善しました:
オブザーバを追加します。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
func keyboardWillHide() {
self.view.frame.Origin.y = 0
}
func keyboardWillChange(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if YOURTEXTVIEW.isFirstResponder {
self.view.frame.Origin.y = -keyboardSize.height
}
}
}
オブザーバを削除します。
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
黒画面エラー時 (Swift 4&4.2) 。
私は黒い画面の問題を修正しました。検証済みの解決策でタップ後にキーボードの高さが変わり、これが黒い画面を引き起こしています。
UIKeyboardFrameBeginUserInfoKeyの代わりに UIKeyboardFrameEndUserInfoKey を使用する必要があります
var isKeyboardAppear = false
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if !isKeyboardAppear {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0{
self.view.frame.Origin.y -= keyboardSize.height
}
}
isKeyboardAppear = true
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if isKeyboardAppear {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y != 0{
self.view.frame.Origin.y += keyboardSize.height
}
}
isKeyboardAppear = false
}
}
私はすべての答えがキーボードの高さの値によってビュー自体を動かしているのを見ます。 autolayout
name__という制約を使用している場合、ビューの制約値(たとえば、下部または上部の制約)を定義済みの値で変更するか、キーボードサイズの値を使用すると便利です。
この例では、テキストフィールドから下部レイアウトビューへの下部拘束を、初期値175で使用します。
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
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);
}
func keyboardWillShow(notification: NSNotification) {
//To retrieve keyboard size, uncomment following line
//let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
bottomConstraint.constant = 260
UIView.animateWithDuration(0.3) {
self.view.layoutIfNeeded()
}
}
func keyboardWillHide(notification: NSNotification) {
//To retrieve keyboard size, uncomment following line
//let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
bottomConstraint.constant = 175
UIView.animateWithDuration(0.3) {
self.view.layoutIfNeeded()
}
}
KeyboardWillHideNotificationの定義方法がいくつか変更されました。
この解決策は Swift 4.2 :で動作します。
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
@objc func keyboardWillShow(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.view.frame.Origin.y -= keyboardSize.height
}
}
@objc func keyboardWillHide(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.view.frame.Origin.y += keyboardSize.height
}
}
Swift 3では、すべてのView Controllerで一定の動作を必要とするため、UIViewControllerサブクラスを作成しました。
class SomeClassVC: UIViewController {
//MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
addKeyboardObservers()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
removeKeyboardObservers()
}
//MARK: - Overrides
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}
//MARK: - Help
func addKeyboardObservers() {
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)
}
func removeKeyboardObservers() {
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 keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.window?.frame.Origin.y = -1 * keyboardHeight!
self.view.layoutIfNeeded()
})
}
func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.window?.frame.Origin.y = 0
self.view.layoutIfNeeded()
})
}
func resignTextFieldFirstResponders() {
for textField in self.view.subviews where textField is UITextField {
textField.resignFirstResponder()
}
}
func resignAllFirstResponders() {
view.endEditing(true)
}
}
私は他の答えはビューからトップの一部をカットすることを含むことに気づきました。コンテンツを切り取らずに単純にビューのサイズを変更する場合は、次の方法を試してください。
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.setTranslatesAutoresizingMaskIntoConstraints(true)
self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y, self.view.frame.size.width, self.view.frame.height - keyboardSize.height)
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y, self.view.frame.size.width, self.view.frame.height + keyboardSize.height)
}
}
検証された答えは テキストフィールドの位置を考慮に入れません そしていくらかのバグを持っています(二重移動、最初の位置に戻らない、texfieldがビューの上にあったとしても移動...)
アイデアは:
それから、必要な場合にのみ、そして特定のディスプレイスメントを変更した場合にのみ、フォーカスされたtexFieldをキーボードの真上に移動させることができます。
これがコードです:
スイフト4
class ViewController: UIViewController, UITextFieldDelegate {
var textFieldRealYPosition: CGFloat = 0.0
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
// Delegate all textfields
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let distanceBetweenTextfielAndKeyboard = self.view.frame.height - textFieldRealYPosition - keyboardSize.height
if distanceBetweenTextfielAndKeyboard < 0 {
UIView.animate(withDuration: 0.4) {
self.view.transform = CGAffineTransform(translationX: 0.0, y: distanceBetweenTextfielAndKeyboard)
}
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.4) {
self.view.transform = .identity
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
textFieldRealYPosition = textField.frame.Origin.y + textField.frame.height
//take in account all superviews from textfield and potential contentOffset if you are using tableview to calculate the real position
}
}
スイフト4:
キーボードを隠してもビューがページの一番下まで表示されない(部分的にしか表示されない)という最も一般的な回答で問題がありました。これは私にとってはうまくいきました(+ Swift 4用に更新)。
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0{
self.view.frame.Origin.y -= keyboardSize.height
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y != 0{
self.view.frame.Origin.y = 0
}
}
}
初心者のための私の2セント:上記のサンプルでは、誰かが座標を変更し、他のものを「自動サイズ変更マスク」、その他の制約を使用しています。
Appleが言っているように、これら3つのタイプのロジックを混在させないでください。ストーリーボードに制約がある場合は、x/yを変更しないでください。それは決定的には機能しません。
スイフト3 の場合
func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder
//move textfields up
let myScreenRect: CGRect = UIScreen.main.bounds
let keyboardHeight : CGFloat = 216
UIView.beginAnimations( "animateView", context: nil)
var movementDuration:TimeInterval = 0.35
var needToMove: CGFloat = 0
var frame : CGRect = self.view.frame
if (textField.frame.Origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
needToMove = (textField.frame.Origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
}
frame.Origin.y = -needToMove
self.view.frame = frame
UIView.commitAnimations()
}
func textFieldDidEndEditing(_ textField: UITextField) {
//move textfields back down
UIView.beginAnimations( "animateView", context: nil)
var movementDuration:TimeInterval = 0.35
var frame : CGRect = self.view.frame
frame.Origin.y = 0
self.view.frame = frame
UIView.commitAnimations()
}
それで、他の答えのどれもそれを正しくするようには思えません。
IOSのGood Behaviored Keyboardは、次のようになります。
私のコードは@IBOutlet
として宣言されたNSLayoutConstraint
を使用しています
@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!
また、変換やビューオフセットなどを使うこともできます。これは、一番下に制約を設定することで機能します。定数が0 /一番下にない場合は、コードを変更する必要があります。
これがコードです:
// In ViewDidLoad
NotificationCenter.default.addObserver(self, selector: #selector(?MyViewController.keyboardDidChange), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
@objc func keyboardDidChange(notification: Notification) {
let userInfo = notification.userInfo! as [AnyHashable: Any]
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber
bottomLayoutConstraint.constant = view.frame.height - endFrame.Origin.y - view.safeAreaInsets.bottom // If your constraint is not defined as a safeArea constraint you might want to skip the last part.
// Prevents iPad undocked keyboard.
guard endFrame.height != 0, view.frame.height == endFrame.height + endFrame.Origin.y else {
bottomLayoutConstraint.constant = 0
return
}
UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
UIView.animate(withDuration: animationDuration.doubleValue) {
self.view.layoutIfNeeded()
// Do additional tasks such as scrolling in a UICollectionView
}
}
キーボードを開いたときのすべてのGuyの最新のTableview Heightに対するその100%完全回答
Swift4.2の場合
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.tbl.contentInset
contentInset.bottom = keyboardFrame.size.height
self.tbl.contentInset = contentInset
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.tbl.contentInset = contentInset
}
}
Swift3.2
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
//self.view.frame.Origin.y -= keyboardSize.height
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.tbl.contentInset
contentInset.bottom = keyboardFrame.size.height
self.tbl.contentInset = contentInset
}
}
func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.tbl.contentInset = contentInset
}
}
これが私の解決策です(実際には、このコードはビュー内にテキストフィールドがほとんどない場合のものです。テキストフィールドが1つある場合にも有効です)。
class MyViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!
var activeTextField: UITextField!
var viewWasMoved: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func textFieldDidBeginEditing(textField: UITextField) {
self.activeTextField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
self.activeTextField = nil
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func keyboardWillShow(notification: NSNotification) {
let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
let activeTextFieldRect: CGRect? = activeTextField?.frame
let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.Origin
if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
self.viewWasMoved = true
self.view.frame.Origin.y -= keyboardSize!.height
} else {
self.viewWasMoved = false
}
}
func keyboardWillHide(notification: NSNotification) {
if (self.viewWasMoved) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.Origin.y += keyboardSize.height
}
}
}
Swift 3用に更新...
他の人が言っているように、あなたはあなたのコントローラのviewDidLoad()メソッドに通知オブザーバを追加する必要があります。
NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil)
{ notification in
self.keyboardWillShow(notification)
}
NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil)
{ notification in
self.keyboardWillHide(notification)
}
NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil)
{ _ in
self.enableUserInteraction()
}
NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil)
{ _ in
self.enableUserInteraction()
}
必要に応じてオブザーバを削除することを忘れないでください(私はviewWillDisappear()メソッドでそれを行います)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: nil)
次に、showメソッドとhideメソッドを実装します - インタラクションイベントを無視するようにアプリに指示する行に注目してください(beginIgnoringInteractionEvents)。これがないと、ユーザーがフィールドまたはスクロールビューをタップして、もう一度シフトを実行し、ひどいUIグリッチが発生する可能性があるため、これは重要です。キーボードの表示と非表示の前にインタラクションイベントを無視すると、これを防ぐことができます。
func keyboardWillShow(notification: Notification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
{
UIApplication.shared.beginIgnoringInteractionEvents()
self.view.frame.Origin.y -= keyboardSize.height
// add this line if you are shifting a scrollView, as in a chat application
self.timelineCollectionView.contentInset.top += keyboardSize.height
}
}
func keyboardWillHide(notification: Notification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
{
UIApplication.shared.beginIgnoringInteractionEvents()
self.view.frame.Origin.y += keyboardSize.height
// add this line if you are shifting a scrollView, as in a chat application
self.timelineCollectionView.contentInset.top -= keyboardSize.height
}
}
最後に、ユーザー操作を再度有効にします(このメソッドはキーボードのdidShowまたはdidHideの後に起動します)。
func enableUserInteraction()
{
UIApplication.shared.endIgnoringInteractionEvents()
}
同じVC上に2つ以上のテキストフィールドがあり、ユーザーがそれらの1つをタップしてから関数keyboardWillHideを呼び出さずにもう1つをタップすると、ビューはもう1度上に移動します。私が編集した答えのコードを使用して、キーボード、キーボードの高さを持つ空白のスペース、そしてビューを作成します。
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)
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.Origin.y -= keyboardSize.height
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.Origin.y += keyboardSize.height
}
}
これを解決するには、 "KeyboardWillShow/Hide"という2つの関数をこれらに置き換えます。
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
if view.frame.Origin.y == 0{
self.view.frame.Origin.y -= keyboardSize.height
}
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
if view.frame.Origin.y != 0 {
self.view.frame.Origin.y += keyboardSize.height
}
}
}
@Borisのソリューションは非常に優れていますが、ビューが壊れることがあります。
完璧な配置のために、以下のコードを使用してください
override func viewDidLoad() {
super.viewDidLoad()
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)}
関数:
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0{
self.view.frame.Origin.y -= keyboardSize.height
}
}}
そして、
@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y != 0{
self.view.frame.Origin.y = 0
}
} }
私はこの質問には約30の答えがあることを知っています、そして誰も一度も この美しいGitHubプロジェクトについて言及しなかったことにとてもショックを受けました すべての答えはビューを上に移動させるだけですが、キーボードの高さがUITextFieldを覆っていない場合はどうなりますか。私はこのIQKeyboardManagerを使ってすべての問題を解決しました。それは13000+の星を持っています。
Swiftを使っているのであれば、これをpodfileに追加するだけです。
pod 'IQKeyboardManagerSwift'
そしてAppDelegate.Swiftの中にIQKeyboardManagerSwiftをインポートして
import IQKeyboardManagerSwift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
IQKeyboardManager.shared.enable = true // just add this line
return true
}
}
有効にするためにIQKeyboardManager.shared.enable = true
という行を追加します。
この解決策は、あなたがプロダクションに行くのであれば必須です。それはすべての問題を解決し、何らかの入力を持つすべてのアプリケーションにとって必須です。
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
// MARK: - keyboard
func keyboardWillShow(notification: NSNotification)
{
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: keyboardSize.height, right:contentInsets.right)
// ...
} else {
// no UIKeyboardFrameBeginUserInfoKey entry in userInfo
}
} else {
// no userInfo dictionary in notification
}
}
func keyboardWillHide(notification: NSNotification)
{
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: 0, right:contentInsets.right)
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y != 0{
// self.view.frame.Origin.y += keyboardSize.height
self.view.frame.Origin.y = 0
}
}
}
キーボードの開閉時に Swift 4 でUIView
を動かす必要があります。そしてすべての答えが私を助けることができなかった。キーボードの高さは emojis openのときに変わるからです。だから私のコードは次のとおりです。
@objc func keyboardWillShow(sender: NSNotification) {
if let keyboardFrame: NSValue = sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
if(self.oldHeight == keyboardHeight){
self.sendingView.frame.Origin.y -= keyboardHeight
self.oldHeight = keyboardHeight
}
else{
self.sendingView.frame.Origin.y += self.oldHeight
self.sendingView.frame.Origin.y -= keyboardHeight
self.oldHeight = keyboardHeight
}
}
}
@objc func keyboardWillHide(sender: NSNotification) {
if let keyboardFrame: NSValue = sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
self.sendingView.frame.Origin.y += keyboardHeight
}
}
そしてviewDidLoad()
:に
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
self.oldHeight = CGFloat()
クラスの先頭にフィールドとして定義します。
func registerForKeyboardNotifications()
{
//Keyboard
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardDidHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications(){
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification){
let userInfo: NSDictionary = notification.userInfo!
let keyboardInfoFrame = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue()
let windowFrame:CGRect = (UIApplication.sharedApplication().keyWindow!.convertRect(self.view.frame, fromView:self.view))
let keyboardFrame = CGRectIntersection(windowFrame, keyboardInfoFrame!)
let coveredFrame = UIApplication.sharedApplication().keyWindow!.convertRect(keyboardFrame, toView:self.view)
let contentInsets = UIEdgeInsetsMake(0, 0, (coveredFrame.size.height), 0.0)
self.scrollViewInAddCase .contentInset = contentInsets;
self.scrollViewInAddCase.scrollIndicatorInsets = contentInsets;
self.scrollViewInAddCase.contentSize = CGSizeMake((self.scrollViewInAddCase.contentSize.width), (self.scrollViewInAddCase.contentSize.height))
}
/**
this method will fire when keyboard was hidden
- parameter notification: contains keyboard details
*/
func keyboardWillBeHidden (notification: NSNotification) {
self.scrollViewInAddCase.contentInset = UIEdgeInsetsZero
self.scrollViewInAddCase.scrollIndicatorInsets = UIEdgeInsetsZero
}
スイフト4.1
override func viewDidLoad() {
super.viewDidLoad()
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)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.Origin.y == 0 {
self.view.frame.Origin.y -= keyboardSize.height //can adjust as keyboardSize.height-(any number 30 or 40)
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.Origin.y != 0 {
self.view.frame.Origin.y = 0
}
}
Swift 5.0:
4-5時間の戦いの後、私はUIViewControllerのシンプルな拡張機能と、チャームのように機能するシンプルなコードが付属しました
* TextFieldがキーボードの上にある場合、ビューは移動しません。
*定数値をNSLayoutConstraintに設定する必要はありません
*サードパーティのライブラリは不要
*アニメーションコードは不要
* TableViewでも動作します
*これは自動レイアウト/自動サイズ変更で動作します
extension UIViewController {
func addKeyboardObserver() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotifications(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}
func removeKeyboardObserver(){
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
// This method will notify when keyboard appears/ dissapears
@objc func keyboardNotifications(notification: NSNotification) {
var accurateY = 0.0 //Using this we will calculate the selected textFields Y Position
if let activeTextField = UIResponder.currentFirst() as? UITextField {
// Here we will get accurate frame of which textField is selected if there are multiple textfields
let frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
accurateY = Double(frame.Origin.y) + Double(frame.size.height)
}
if let userInfo = notification.userInfo {
// here we will get frame of keyBoard (i.e. x, y, width, height)
let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let keyBoardFrameY = keyBoardFrame!.Origin.y
var newHeight: CGFloat = 0.0
//Check keyboards Y position and according to that move view up and down
if keyBoardFrameY >= UIScreen.main.bounds.size.height {
newHeight = 0.0
} else {
if accurateY >= Double(keyBoardFrameY) { // if textfields y is greater than keyboards y then only move View to up
if #available(iOS 11.0, *) {
newHeight = -CGFloat(accurateY - Double(keyBoardFrameY)) - self.view.safeAreaInsets.bottom
} else {
newHeight = -CGFloat(accurateY - Double(keyBoardFrameY)) - 5
}
}
}
//set the Y position of view
self.view.frame.Origin.y = newHeight
}
}
}
このUIResponderの拡張機能を追加して、選択されているTextFieldを取得します
public extension UIResponder {
private struct Static {
static weak var responder: UIResponder?
}
static func currentFirst() -> UIResponder? {
Static.responder = nil
UIApplication.shared.sendAction(#selector(UIResponder._trap), to: nil, from: nil, for: nil)
return Static.responder
}
@objc private func _trap() {
Static.responder = self
}
}
次に、これを任意のViewControllerで使用します
override func viewWillAppear(_ animated: Bool) {
self.addKeyboardObserver()
}
override func viewWillDisappear(_ animated: Bool) {
self.removeKeyboardObserver()
}
この通知をfunc viewWillAppear(_ animated: Bool)
に登録します
func viewWillDisappear(_ animated:Bool)
でこの通知の登録を解除します
Swift 3コード
var activeField: UITextField?
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func textFieldDidBeginEditing(_ textField: UITextField){
activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField){
activeField = nil
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if (self.activeField?.frame.Origin.y)! >= keyboardSize.height {
self.view.frame.Origin.y = keyboardSize.height - (self.activeField?.frame.Origin.y)!
} else {
self.view.frame.Origin.y = 0
}
}
}
func keyboardWillHide(notification: NSNotification) {
self.view.frame.Origin.y = 0
}
このビデオチュートリアルは最高です。 7分の長さです。複数のテキストフィールドがあり、その特定のテキストフィールドがタップされたときにスクロールビューに "x"量のピクセルを移動させたい場合のためのこのような単純な解決策。
ちょうどこれらのステップ:
- ビューの端に制限されているスクロールビュー内にすべてのテキストフィールドを配置します。
- すべてのテキストフィールドとスクロールビューをView Controllerへのデリゲートとして接続します。
- すべてのテキストフィールドとスクロールビューをIBOutletで接続します。
class ViewController: UIViewController, UITextFieldDelegate {
あなたのクラスにUITextFieldDelegateプロトコルを追加
@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!
@IBOutlet weak var scrollView: UIScrollView!
あなたのSwiftファイルにUITextFieldDelegateメソッドを追加します。
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
if (textField == self.stateAddress) {
scrollView.setContentOffset(CGPointMake(0, 25), animated: true)
}
else if (textField == self.zipAddress) {
scrollView.setContentOffset(CGPointMake(0, 57), animated: true)
}
else if (textField == self.phoneNumber) {
scrollView.setContentOffset(CGPointMake(0, 112), animated: true)
}
else if (textField == self.vetEmailAddress) {
scrollView.setContentOffset(CGPointMake(0, 142), animated: true)
}
}
func textFieldDidEndEditing(textField: UITextField) {
scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}
最初の方法は、キーボードを閉じるためにキーボードの戻るボタンをアクティブにするだけです。 2つ目は、特定のテキストフィールドをタップしてから、スクロールビューがスクロールする距離のyオフセットを設定することです(私のビューコントローラでは、25、57、112、142のy位置に基づいています)。最後は、キーボードからタップするとスクロールビューが元の位置に戻ることを示しています。
私は自分の視野ピクセルをこのように完璧にしました!
この実装(Swift 4)は、Androidのデフォルトの動作に最も近い動作を提供します。つまり、アクティブなテキストフィールドがキーボードの下にあるときにビューを上に移動し、ユーザーがキーボードを閉じずに別のビューに切り替えるとそれに応じて移動します。 setTextFieldDelegates()を呼び出すことを忘れないでください。
public class DelegateProxy: NSObject, UITextFieldDelegate {
private static let instance = DelegateProxies()
weak var activeTextField: UITextField?
var offset: CGFloat = 0
weak var vc: UIViewController?
var keyboardHeight: CGFloat = 0
public static func getDelegate(root: UIViewController) -> DelegateProxies {
instance.vc = root
return instance
}
public static func getDelegate() -> DelegateProxies {
return instance
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeTextField = textField
let globalPointY: CGFloat = (textField.superview?.convert(textField.frame.Origin, to: nil).y ?? CGFloat(0)) + textField.frame.height
offset = UIScreen.main.bounds.height - globalPointY
if keyboardHeight > 0 {
vc?.moveViewUp(offsetFromKeyboard: keyboardHeight - offset)
}
return true
}
}
extension UIViewController {
private func setTextFieldDelegates(parentView: UIView) {
for child in parentView.subviews {
setTextFieldDelegates(parentView: child)
(child as? UITextField)?.delegate = DelegateProxies.getDelegate(root: self)
}
}
func registerAutoResizeOnKeyboardAppear(){
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func unregisterAutoResizeOnKeyboard(){
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let offsetFromKeyboard = keyboardSize.height - DelegateProxies.getDelegate().offset
DelegateProxies.getDelegate().keyboardHeight = keyboardSize.height
moveViewUp(offsetFromKeyboard: offsetFromKeyboard)
}
}
func moveViewUp(offsetFromKeyboard: CGFloat){
print("offset from keyboard: \(offsetFromKeyboard)")
let moveOffset = offsetFromKeyboard + 8
if offsetFromKeyboard > 0 {
self.view.frame.Origin.y = -moveOffset
}
if offsetFromKeyboard < 0 && view.frame.Origin.y < 0 {
self.view.frame.Origin.y += -moveOffset
if self.view.frame.Origin.y > 0{
self.view.frame.Origin.y = 0
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
self.view.frame.Origin.y = 0
}
}
あなたが上記のすべての解決策を試したがそれでもあなたの問題が解決されない私のようであるならば、私は魅力のように働くあなたのための素晴らしい解決策を得ました。最初に、上記の解決策のいくつかについていくつか明確にしたいと思います。
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
myTextField.resignFirstResponder()
}
func keyboardWillShow(notification: NSNotification) {
// let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]
// print("duration",duration)
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardHeight : Int = Int(keyboardSize.height)
print("keyboardWillShow",keyboardHeight)
if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.43, up: true)
}else{
UserDefaults.standard.set(keyboardHeight, forKey: "keyboardHeight")
moveTextField(myTextField, moveDistance: -keyboardHeight, moveDuration: 0.43, up: true)
}
}
}
func keyboardWillHide(notification: NSNotification){
if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.25, up: false)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func moveTextField(_ textField: UITextField, moveDistance: Int, moveDuration: Double, up: Bool) {
let movement: CGFloat = CGFloat(up ? moveDistance : -moveDistance)
UIView.beginAnimations("animateTextField", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(moveDuration)
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
}
画面全体ではなくUITextFiled
だけ上下に移動することもできます(UIView)。
この方法を使って。
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
そして
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.Origin.y - curFrame.Origin.y
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.textField.frame.Origin.y+=deltaY
},completion: nil)
}
私は答えを読み、このコード行によって私の問題を解決しました:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var titleField: UITextField!
@IBOutlet weak var priceField: UITextField!
@IBOutlet weak var detailsField: UTtextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do not to forget to set the delegate otherwise the textFieldShouldReturn(_:)
// won't work and the keyboard will never be hidden.
priceField.delegate = self
titleField.delegate = self
detailsField.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow),
name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide),
name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
func keyboardWillShow(notification: NSNotification) {
var translation:CGFloat = 0
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if detailsField.isEditing{
translation = CGFloat(-keyboardSize.height)
}else if priceField.isEditing{
translation = CGFloat(-keyboardSize.height / 3.8)
}
}
UIView.animate(withDuration: 0.2) {
self.view.transform = CGAffineTransform(translationX: 0, y: translation)
}
}
func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.2) {
self.view.transform = CGAffineTransform(translationX: 0, y: 0)
}
}
}
私はいくつかのUITextFieldを持っていて、どのtextFieldがタップされたかによってビューの表示が異なるように移動したいと思います。
この機能はIosに組み込まれていますが、外部で行う必要があります。
以下のコードを挿入してください
* textFieldがキーボードの下にあるときにビューを移動するには、
* textFieldがキーボードの上にあるときはビューを移動しません
*必要に応じてキーボードの高さに基づいてビューを移動します。
これはすべての場合に機能し、テストされました。
import UIKit
class NamVcc: UIViewController, UITextFieldDelegate
{
@IBOutlet weak var NamTxtBoxVid: UITextField!
var VydTxtBoxVar: UITextField!
var ChkKeyPadDspVar: Bool = false
var KeyPadHytVal: CGFloat!
override func viewDidLoad()
{
super.viewDidLoad()
NamTxtBoxVid.delegate = self
}
override func viewWillAppear(animated: Bool)
{
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(TdoWenKeyPadVyd(_:)),
name:UIKeyboardWillShowNotification,
object: nil);
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(TdoWenKeyPadHyd(_:)),
name:UIKeyboardWillHideNotification,
object: nil);
}
func textFieldDidBeginEditing(TxtBoxPsgVar: UITextField)
{
self.VydTxtBoxVar = TxtBoxPsgVar
}
func textFieldDidEndEditing(TxtBoxPsgVar: UITextField)
{
self.VydTxtBoxVar = nil
}
func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
{
self.VydTxtBoxVar.resignFirstResponder()
return true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}
func TdoWenKeyPadVyd(NfnPsgVar: NSNotification)
{
if(!self.ChkKeyPadDspVar)
{
self.KeyPadHytVal = (NfnPsgVar.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height
var NonKeyPadAraVar: CGRect = self.view.frame
NonKeyPadAraVar.size.height -= self.KeyPadHytVal
let VydTxtBoxCenVal: CGPoint? = VydTxtBoxVar?.frame.Origin
if (!CGRectContainsPoint(NonKeyPadAraVar, VydTxtBoxCenVal!))
{
self.ChkKeyPadDspVar = true
UIView.animateWithDuration(1.0,
animations:
{ self.view.frame.Origin.y -= (self.KeyPadHytVal)},
completion: nil)
}
else
{
self.ChkKeyPadDspVar = false
}
}
}
func TdoWenKeyPadHyd(NfnPsgVar: NSNotification)
{
if (self.ChkKeyPadDspVar)
{
self.ChkKeyPadDspVar = false
UIView.animateWithDuration(1.0,
animations:
{ self.view.frame.Origin.y += (self.KeyPadHytVal)},
completion: nil)
}
}
override func viewDidDisappear(animated: Bool)
{
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
view.endEditing(true)
ChkKeyPadDspVar = false
}
}
| :: |時々Viewが下がってしまいます。その場合はheight +/- 150を使ってください。
NonKeyPadAraVar.size.height -= self.KeyPadHytVal + 150
{ self.view.frame.Origin.y -= self.KeyPadHytVal - 150},
completion: nil)
{ self.view.frame.Origin.y += self.KeyPadHytVal - 150},
completion: nil)
ViewDidLoad()でのSwift 3.0の挿入、これ - >
{
view.addSubview(Your_messageInputConteinerView)
view.addConstraintWithFormat(format: "H:|[v0]|", views:Your_messageInputConteinerView)
view.addConstraintWithFormat(format: "V:[v0(48)]", views:Your_messageInputConteinerView)
NotificationCenter.default.addObserver(self、セレクター:#selector(handleKeyboardNotification(notification :))、名前:NSNotification.Name.UIKeyboardWillShow、オブジェクト:nil)
NotificationCenter.default.addObserver(self、セレクタ:#selector(handleKeyboardNotification(notification :))、名前:.UIKeyboardWillHide、オブジェクト:nil)
bottomConstraint = NSLayoutConstraint(item: Your_messageInputConteinerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomConstraint!)
}
func handleKeyboardNotification(notification:通知){
if let userInfo = notification.userInfo {
if let keyBoardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue{
print(keyBoardFrame)
if bottomConstraint?.constant != CGFloat(0) {
bottomConstraint?.constant = 0
return
}
bottomConstraint?.constant = -keyBoardFrame.height
or
self.view.frame.Origin.y = -keyBoardFrame.height
}
}
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.Origin.y = self.view.frame.height - (self.view.frame.height + keyboardSize.height)
}
}
func keyboardWillHide(notification: NSNotification) {
self.view.frame.Origin.y = 0
}
もっと安定している必要があります
次のコードを使用してUITextFieldで表示する
func textFieldDidBeginEditing(textField: UITextField) {
ViewUpanimateMoving(true, upValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
ViewUpanimateMoving(false, upValue: 100)
}
func ViewUpanimateMoving (up:Bool, upValue :CGFloat){
var durationMovement:NSTimeInterval = 0.3
var movement:CGFloat = ( up ? -upValue : upValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(durationMovement)
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
私は問題を単純化するためにカカオポッドを作りました:
https://github.com/xtrinch/KeyboardLayoutHelper
どうやって使うのですか:
自動レイアウト下部制約を作成し、それをKeyboardLayoutConstraint モジュールKeyboardLayoutHelperに指定すると、ポッドはキーボードの表示/非表示に対応するために必要な作業を行います。使い方の例については、サンプルプロジェクトを参照してください(私は2つ作成しました:scrollView内のtextFieldと、2つの基本ビューを持つ垂直方向の中央揃えのtextField - ログインと登録)。
一番下のレイアウト制約は、コンテナビュー、textField自体、その他何でもかまいません。