web-dev-qa-db-ja.com

Swiftを使ってキーボードでビューを移動する

ビューの下半分にテキストフィールドを持つアプリがあります。つまり、テキストフィールドに入力すると、キーボードがテキストフィールドを覆います。

入力中にビューを上に移動して、入力した内容を確認し、キーボードが消えたら元の位置に戻す方法を説明します。

私はいたるところを見ましたが、すべての解決策はObj-Cにあるように見えますが、まだ変換することはできません。

任意の助けは大歓迎です。

240
Alex Catchpole

これは、ある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
    }
}

Swift 3.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
    }
}

Swift 4.2用の編集:

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
    }
}
607
Boris

コードを必要としない最も簡単な方法:

  1. まだSpringアニメーションフレームワークを使用していない場合は、 KeyboardLayoutConstraint.Swift をダウンロードしてファイルをプロジェクトに追加(ドラッグ&ドロップ)します。
  2. ストーリーボードで、ビューまたはテキストフィールドに下側の拘束を作成し、その拘束を選択(ダブルクリック)して、Identity InspectorでそのクラスをNSLayoutConstraintからKeyboardLayoutConstraintに変更します。
  3. 完了しました。

オブジェクトはキーボードと同期して自動的に上に移動します。

66
gammachill

このスレッドに関する一般的な回答の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)
}
65
Dan Beaulieu

これをあなたのビューコントローラに追加してください。魅力のように働きます。値を調整するだけです。

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
}
30
user3677173

私はそれが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)
}
22
scipianne

黒画面エラー時 (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
    }
}
14
codeByThey

私はすべての答えがキーボードの高さの値によってビュー自体を動かしているのを見ます。 autolayoutname__という制約を使用している場合、ビューの制約値(たとえば、下部または上部の制約)を定義済みの値で変更するか、キーボードサイズの値を使用すると便利です。

この例では、テキストフィールドから下部レイアウトビューへの下部拘束を、初期値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()
    }
}
12
Amro Shafie

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

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)
  }
}
6
Pavle Mijatovic

私は他の答えはビューからトップの一部をカットすることを含むことに気づきました。コンテンツを切り取らずに単純にビューのサイズを変更する場合は、次の方法を試してください。

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)
    }
}
5
Grant Park

検証された答えは テキストフィールドの位置を考慮に入れません そしていくらかのバグを持っています(二重移動、最初の位置に戻らない、texfieldがビューの上にあったとしても移動...)

アイデアは:

  • textFieldの絶対Y位置をフォーカスする
  • キーボードの高さを取得する
  • screenHeightを取得する
  • 次にキーボードの位置とテキストフィールドの間の距離を計算します(<0 - >の場合)
  • uIView.frame.Origin.y - = ..の代わりにUIView.transformを使用すると、UIView.transform = .identityで元の位置に戻るのが簡単になります。

それから、必要な場合にのみ、そして特定のディスプレイスメントを変更した場合にのみ、フォーカスされた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
}

}

3
Quentin N

スイフト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
Rbar

初心者のための私の2セント:上記のサンプルでは、​​誰かが座標を変更し、他のものを「自動サイズ変更マスク」、その他の制約を使用しています。

Appleが言っているように、これら3つのタイプのロジックを混在させないでください。ストーリーボードに制約がある場合は、x/yを変更しないでください。それは決定的には機能しません。

2
ingconti

スイフト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()
}
2
Celil Bozkurt

それで、他の答えのどれもそれを正しくするようには思えません。

IOSのGood Behaviored Keyboardは、次のようになります。

  • キーボードのサイズが変わったときに自動的にサイズ変更する(YES IT CAN)
  • キーボードと同じ速度でアニメートする
  • キーボードと同じ曲線を使ってアニメートする
  • 関連する場合は安全な場所を尊重してください。
  • IPad/Undockedモードでも動作します

私のコードは@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
    }
}
2
Antzi

キーボードを開いたときのすべての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
Maulik Patel

これが私の解決策です(実際には、このコードはビュー内にテキストフィールドがほとんどない場合のものです。テキストフィールドが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
        }
    }
}
1
Vah.Sah

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()
    }
1
Gene Loparco

同じ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
        }
    }
}
1
Mr. Xcoder

@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 
    }
} }
1
Eray Alparslan

私はこの質問には約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という行を追加します。
この解決策は、あなたがプロダクションに行くのであれば必須です。それはすべての問題を解決し、何らかの入力を持つすべてのアプリケーションにとって必須です。

1
weegee
 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)
 }
0
Himali Shah
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
        }
    }
}
0
Puji Wahono

キーボードの開閉時に 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()クラスの先頭にフィールドとして定義します。

0
MHSFisher
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

    }
0
Kamalkumar.E

スイフト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
    }
}
0
Tlzdeveloper786

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)でこの通知の登録を解除します

0
Saifan Nadaf

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
}
0
Rohit Sharma

このビデオチュートリアルは最高です。 7分の長さです。複数のテキストフィールドがあり、その特定のテキストフィールドがタップされたときにスクロールビューに "x"量のピクセルを移動させたい場合のためのこのような単純な解決策。

https://youtu.be/VuiPGJOEBH4

ちょうどこれらのステップ:

- ビューの端に制限されているスクロールビュー内にすべてのテキストフィールドを配置します。

- すべてのテキストフィールドとスクロールビューを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位置に基づいています)。最後は、キーボードからタップするとスクロールビューが元の位置に戻ることを示しています。

私は自分の視野ピクセルをこのように完璧にしました!

0
bme003

この実装(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
  }
}
0
ravindu1024

あなたが上記のすべての解決策を試したがそれでもあなたの問題が解決されない私のようであるならば、私は魅力のように働くあなたのための素晴らしい解決策を得ました。最初に、上記の解決策のいくつかについていくつか明確にしたいと思います。

  1. 私の場合、IQkeyboardmanagerは、要素に自動レイアウトが適用されていない場合にのみ機能していました。適用されている場合、IQkeyboardマネージャは、私たちが考えているように機能しません。
  2. self.viewの上向きの動きと同じこと。
  3. 私はユーザーがそれをクリックしたときにUITexfieldを上に押すためのSwiftサポート付きのObjective Cヘッダーを書いて、UITextfieldをカバーするキーボードの問題を解決しました: https://github.com/coolvasanth/smart_keyboard
  4. IOSアプリ開発の中級以上のレベルを持っている人は、リポジトリを容易に理解してそれを実装することができます。 ではごきげんよう
0
Vasanth

Swift 4のSimpelstメソッドenter image description here

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

私は答えを読み、このコード行によって私の問題を解決しました:

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がタップされたかによってビューの表示が異なるように移動したいと思います。

0
Fedya Grab

この機能は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)
0
Sujay U N

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

}

0
Anton Russia
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
}

もっと安定している必要があります

0
Hadevs Play

次のコードを使用して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()
}
0
Jugal K Balara

私は問題を単純化するためにカカオポッドを作りました:

https://github.com/xtrinch/KeyboardLayoutHelper

どうやって使うのですか:

自動レイアウト下部制約を作成し、それをKeyboardLayoutConstraint モジュールKeyboardLayoutHelperに指定すると、ポッドはキーボードの表示/非表示に対応するために必要な作業を行います。使い方の例については、サンプルプロジェクトを参照してください(私は2つ作成しました:scrollView内のtextFieldと、2つの基本ビューを持つ垂直方向の中央揃えのtextField - ログインと登録)。

一番下のレイアウト制約は、コンテナビュー、textField自体、その他何でもかまいません。

0
xtrinch