Verschieben Sie eine Ansicht nur nach oben, wenn die Tastatur ein Eingabefeld abdeckt

148

Ich versuche, einen Eingabebildschirm für das iPhone zu erstellen. Der Bildschirm verfügt über eine Reihe von Eingabefeldern. Die meisten davon befinden sich oben auf dem Bildschirm, aber zwei Felder befinden sich unten. Wenn der Benutzer versucht, den Text am unteren Bildschirmrand zu bearbeiten, wird die Tastatur eingeblendet und der Bildschirm abgedeckt. Ich habe eine einfache Lösung gefunden, um den Bildschirm nach oben zu verschieben, aber das Ergebnis ist, dass der Bildschirm immer nach oben bewegt wird und die Felder oben auf dem Bildschirm außer Reichweite sind, wenn der Benutzer versucht, diese zu bearbeiten.

Gibt es eine Möglichkeit, den Bildschirm nur zu verschieben, wenn die unteren Felder bearbeitet werden?

Ich habe diesen Code verwendet, den ich hier gefunden habe :

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(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}

func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}
John Allijn
quelle
Möglicherweise können Sie func textFieldDidBeginEditing (textField: UITextField!) {} verwenden, um festzustellen, welches Textfeld mit der Bearbeitung begonnen hat, und um das Ausblenden /
Anzeigen der
Ich habe vergessen zu erwähnen, dass ich neu bei Swift bin :( Was wäre die richtige Syntax, um dies zu überprüfen? (Wie erhalte ich den Feldnamen in dieser Funktion?)
John Allijn

Antworten:

211

Ihr Problem wird in diesem Dokument von Apple ausführlich erläutert . Der Beispielcode auf dieser Seite (at Listing 4-1) macht genau das, was Sie brauchen. Er scrollt nur dann durch Ihre Ansicht, wenn sich die aktuelle Bearbeitung unter der Tastatur befinden soll. Sie müssen nur die erforderlichen Steuerelemente in eine scrollViiew einfügen. Das einzige Problem ist, dass dies Objective-C ist und ich denke, Sie brauchen es in Swift ... also ... hier ist es:

Deklarieren Sie eine Variable

var activeField: UITextField?

Fügen Sie dann diese Methoden hinzu

 func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.scrollEnabled = true
    var info : NSDictionary = notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeFieldPresent = activeField
    {
        if (!CGRectContainsPoint(aRect, activeField!.frame.origin))
        {
            self.scrollView.scrollRectToVisible(activeField!.frame, animated: true)
        }
    }


}


func keyboardWillBeHidden(notification: NSNotification)
{
    //Once keyboard disappears, restore original positions
    var info : NSDictionary = notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.scrollEnabled = false

}

func textFieldDidBeginEditing(textField: UITextField!)
{
    activeField = textField
}

func textFieldDidEndEditing(textField: UITextField!)
{
    activeField = nil
}

Stellen Sie sicher, dass Sie Ihren ViewController als deklarieren UITextFieldDelegateund in Ihren Initialisierungsmethoden die richtigen Delegaten festlegen : Beispiel:

self.you_text_field.delegate = self

Und denken Sie daran, registerForKeyboardNotificationsviewInit und deregisterFromKeyboardNotificationsExit aufzurufen .

Bearbeiten / Aktualisieren: Swift 4.2 Syntax

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeField = self.activeField {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

@objc func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}
Nerkyator
quelle
3
Sie müssen registerForKeyboardNotifications unter viewDidLoad aufrufen, damit Sie dem Benachrichtigungscenter einen Beobachter hinzufügen können, wenn die Tastatur angezeigt oder vom Bildschirm verschwindet. Wenn diese Benachrichtigung ausgelöst wird, werden die Methoden KeyboardWasShown und KeyboardWillBeHidden aufgerufen, und die Bildlaufansicht wird entsprechend der Tastaturgröße verschoben. Weitere Informationen zu NotificationCenter finden Sie hier: developer.apple.com/library/mac/documentation/Cocoa/Reference/…
Nerkyator
12
Danke, genau das habe ich gesucht - eine von Apple empfohlene Lösung. In meinem Fall hatte ich jedoch bereits eine Bildlaufansicht, die sich außerhalb des sichtbaren Bereichs erstreckte. Dieser Code würde das Scrollen deaktivieren, nachdem sich die Tastatur ausgeblendet hat. Ich habe "self.scrollView.scrollEnabled = false" entfernt und es wurde immer noch nicht gescrollt. Was für mich funktioniert hat, war "self.scrollView.contentInset = UIEdgeInsetsZero;" Diese einzelne Zeile im KeyboardWillHide-Ereignis
F Yaqoob
5
Perfekter Code. Aber ich muss UIKeyboardFrameEndUserInfoKeystattdessen verwenden UIKeyboardFrameBeginUserInfoKey, weil letztere Höhe 0 zurückgeben. Und den schärfsten Punkt nach unten ändern, nicht Ursprung. if let activeField = self.activeField { var point = activeField.frame.origin point.y += activeField.frame.size.height if (!aRect.contains(point)){ self.scrollView.scrollRectToVisible(activeField.frame, animated: true) } }
Victor Choy
3
@ MaX: Es sollte funktionieren, aber wenn Sie eine Swift4-Lösung wollen, können Sie dieses iOS-Beispiel aus Matt Neuburgs Buch überprüfen , das ich allen iOS-Entwicklern vorschlage :)
Nerkyator
1
@MaX Ich bin mir nicht sicher, ob dies ausschließlich eine schnelle 4 Sache ist, aber was zu passieren scheint, ist, dass die textField's didBeginEditingMethode NACH dem Aufruf der keyboardWillShowMethode aufgerufen wird. Infolgedessen ist die activeFieldVariable immer noch Null, was bedeutet, dass kein automatisches Scrollen stattfindet. Meine Lösung bestand darin, den activeField = textFieldAufruf in die shouldBeginEditingMethode von textField einzufügen . Dies behebt das Problem mit der Reihenfolge der Anrufe.
HirdayGupta
150

Hier sind meine 2 Cent:

Haben Sie versucht: https://github.com/hackiftekhar/IQKeyboardManager

Sehr einfach zu installierende Swift oder Objective-C.

Hier, wie es funktioniert:

IQKeyboardManager (Swift): - IQKeyboardManagerSwift ist über CocoaPods verfügbar. Um es zu installieren, fügen Sie einfach die folgende Zeile zu Ihrem Podfile hinzu: (# 236)

pod 'IQKeyboardManagerSwift'

Importieren Sie in AppDelegate.swift einfach das IQKeyboardManagerSwift-Framework und aktivieren Sie IQKeyboardManager.

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    IQKeyboardManager.sharedManager().enable = true
    // For Swift 4, use this instead
    // IQKeyboardManager.shared.enable = true


    return true
    }
}

Und das ist alles. Einfach!

Herr H.
quelle
17
Perfekt. Dies sollte standardmäßig eingebaut sein. Scheint lächerlich, dass es nicht ist.
NathofGod
1
Dies ist eigentlich lächerlich, es ist so einfach zu implementieren und funktioniert einfach, und Sie erhalten eine einfache Möglichkeit, durch mehrere Textfelder zu wechseln
Khoury
Das Umschalten in mehrere Textfelder würde nicht funktionieren? Keine Pfeilanzeige auf der Tastatur zum Wechseln zwischen Textfeldern.
Arsal
1
Dies war eine erstaunliche Lösung, danke! Ich brauchte ein wenig Arbeit, um die CocoaPods richtig einzurichten, da diese für mich völlig neu waren. Nachdem ich das eingerichtet hatte, waren es buchstäblich 2 Codezeilen, um dies zu implementieren, und es funktionierte sofort perfekt. Vielen Dank!
IcyBlueRose
5
Dies funktionierte nicht für mich in Swift 4.1 IQKeyboardManager.sharedManager (). Enable = true Wurde umgestellt IQKeyboardManager.shared.enable = true
Rmalmoe
20

Ich fand, dass es perfekt für mich funktioniert:

func textFieldDidBeginEditing(textField: UITextField) {
    if textField == email || textField == password {
        animateViewMoving(true, moveValue: 100)
    }
}

func textFieldDidEndEditing(textField: UITextField) {
    if textField == email || textField == password {
        animateViewMoving(false, moveValue: 100)
    }
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)

    UIView.beginAnimations("animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)

    self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    UIView.commitAnimations()
}

Sie können auch die Höhenwerte ändern. Entfernen Sie die "if-Anweisung", wenn Sie sie für alle Textfelder verwenden möchten.

Sie können dies sogar für alle Steuerelemente verwenden, für die Benutzereingaben erforderlich sind, z. B. TextView.

Edward
quelle
5
Das direkte Verschieben eines UIView-Frames ist keine gute Lösung. Dazu gehören auch fest codierte Werte, die für diesen Anwendungsfall spezifisch sind. Ich würde die Leute ermutigen, eine solche Lösung nicht zu implementieren und stattdessen etwas zu tun, das den in der akzeptierten Antwort beschriebenen Best Practices näher kommt.
MobileVet
@ MobileVet verstanden, aber das ist das, was funktioniert.
Tarvo Mäesepp
erstaunliche separate Logik, ohne in unseren Code zu wechseln
Dilip Jangid
6

Gibt es eine Möglichkeit, den Bildschirm nur zu verschieben, wenn die unteren Felder bearbeitet werden?

Ich hatte ein ähnliches Problem und fand eine ziemlich einfache Lösung, ohne eine scrollView zu verwenden und stattdessen if-Anweisungen innerhalb der keyboardWillShow / Hide-Methoden zu verwenden.

func keyboardWillShow(notification: NSNotification) {
    if bottomText.editing{
        self.view.window?.frame.origin.y = -1 * getKeyboardHeight(notification)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if self.view.window?.frame.origin.y != 0 {
        self.view.window?.frame.origin.y += getKeyboardHeight(notification)
    }
}

Dies war eine gute Lösung für mich, da ich nur zwei Textfelder hatte.

Verschiebt die gesamte Ansicht nach oben: Nur wenn bestimmte Textfelder (bottomText) bearbeitet werden

Verschiebt die gesamte Ansicht nach unten: Nur wenn sich die Ansicht nicht am ursprünglichen Ort befindet

villejacob
quelle
5

Verwenden Sie einfach diese Erweiterung, um UIView zu verschieben, wenn die Tastatur angezeigt wird.

extension UIView {
    func bindToKeyboard(){
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    @objc func keyboardWillChange(_ notification: NSNotification){
        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let beginningFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

        let deltaY = endFrame.origin.y - beginningFrame.origin.y

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
        }, completion: nil)
    }
}

Binden Sie dann in Ihrem viewdidload Ihre Ansicht an die Tastatur

UiView.bindToKeyboard()
Bilal Mustafa
quelle
Dadurch wird die Ansicht nach oben verschoben, auch wenn sie nicht benötigt wird. Wenn sich das Textfeld oben in der Ansicht befindet, wird es nach oben verschoben und ist nicht sichtbar. Dies ist keine gute Lösung.
Shivam Pokhriyal
4

Warum implementieren Sie dies nicht stattdessen in einem UITableViewController? Die Tastatur versteckt keine Textfelder, wenn sie angezeigt wird.

RJiryes
quelle
Dies ist tatsächlich der einfachste und robusteste Weg. Und es funktioniert sogar mit Steuerelementen, die eine benutzerdefinierte Eingabeansicht anstelle der Standardtastatur verwenden (UIKeyboard-Benachrichtigungen funktionieren für diese nicht)
Radu Simionescu
1
Es gibt das Problem, dass Sie vorsichtig sein müssen, wenn die Tabellenansicht eingebettet ist (anstatt "die ganze Seite" zu sein). Für alle, die davon betroffen sind, wird die Lösung in Beiträgen wie diesem und diesem erklärt . Hoffe, es hilft jemandem, der sich mit dem "absolut dümmsten Problem in ganz Apple" befasst!
Fattie
3

Swift 4 (** aktualisiert ) mit Erweiterung **

  1. Fügen Sie die Schaltflächen in einem Container hinzu
  2. Verbinden Sie die untere Einschränkung des Containers mit IBOutlet containerBtmConstrain
  3. inViewDidLoad

    self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain
    self.watchForKeyboard() 
  4. Fügen Sie die folgende Erweiterung hinzu

    import UIKit
    
    private var xoAssociationKeyForBottomConstrainInVC: UInt8 = 0
    
    extension UIViewController {
    
        var containerDependOnKeyboardBottomConstrain :NSLayoutConstraint! {
            get {
                return objc_getAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC) as? NSLayoutConstraint
            }
            set(newValue) {
                objc_setAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
    
        func watchForKeyboard() {
            NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown(notification:)), name:UIResponder.keyboardWillShowNotification, object: nil);
            NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name:UIResponder.keyboardWillHideNotification, object: nil);
        }
    
        @objc func keyboardWasShown(notification: NSNotification) {
            let info = notification.userInfo!
            guard let keyboardFrame: CGRect = (info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
              return
            }
    
            UIView.animate(withDuration: 0.3, animations: { () -> Void in
                self.containerDependOnKeyboardBottomConstrain.constant = -keyboardFrame.height
                self.view.layoutIfNeeded()
            })
        }
    
        @objc func keyboardWillHide(notification: NSNotification) {
            UIView.animate(withDuration: 0.3, animations: { () -> Void in
                self.containerDependOnKeyboardBottomConstrain.constant = 0
                self.view.layoutIfNeeded()
            })
        }
    }
iluvatar_GR
quelle
1
Danke, Kumpel. Es geht nur um den richtigen Schlüssel. Ich habe UIKeyboardFrameBeginUserInfoKey verwendet und jetzt wird UIKeyboardFrameEndUserInfoKey ordnungsgemäß verwendet.
Felipe
2

Ich verwende SwiftLint, das einige Probleme mit der Formatierung der akzeptierten Antwort hatte. Speziell:

Kein Leerzeichen vor dem Doppelpunkt, kein Force Casting, bevorzugen Sie UIEdgeInset (oben: etc ... anstelle von UIEdgeInsetMake.

Hier sind die Updates für Swift 3

func registerForKeyboardNotifications() {
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func deregisterFromKeyboardNotifications() {
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func keyboardWasShown(notification: NSNotification) {
    //Need to calculate keyboard exact size due to Apple suggestions
    scrollView?.isScrollEnabled = true
    var info = notification.userInfo!
    if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
        let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)

        scrollView?.contentInset = contentInsets
        scrollView?.scrollIndicatorInsets = contentInsets

        var aRect: CGRect = self.view.frame
        aRect.size.height -= keyboardSize.height
        if let activeField = self.activeField {
            if !aRect.contains(activeField.frame.origin) {
                self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
            }
        }
    }
}

func keyboardWillBeHidden(notification: NSNotification) {
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
        let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize.height, right: 0.0)
        scrollView?.contentInset = contentInsets
        scrollView?.scrollIndicatorInsets = contentInsets
    }

    view.endEditing(true)
    scrollView?.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField) {
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField) {
    activeField = nil
}
Joe Hoffman
quelle
1

Ich denke, diese Klausel ist falsch:

if (!CGRectContainsPoint(aRect, activeField!.frame.origin))

Während der Ursprung des activeField möglicherweise über der Tastatur liegt, kann es sein, dass das maxY nicht ...

Ich würde einen 'max'-Punkt für das activeField erstellen und prüfen, ob dies in der Tastatur Rect ist.

zevij
quelle
0

Hier ist meine Version, nachdem ich die Dokumentation von Apple und die vorherigen Beiträge gelesen habe. Eine Sache, die mir aufgefallen ist, ist, dass die Textansicht nicht verarbeitet wurde, wenn sie von der Tastatur abgedeckt wurde. Leider funktioniert die Dokumentation von Apple nicht, da die Tastatur aus irgendeinem Grund NACH dem Aufruf von textViewDidBeginEditing aufgerufen wird. Ich habe dies durch den Aufruf einer zentralen Methode behandelt, die prüft, ob die Tastatur angezeigt wird UND ob eine Textansicht oder ein Textfeld bearbeitet wird. Auf diese Weise wird der Prozess nur ausgelöst, wenn BEIDE Bedingungen vorliegen.

Ein weiterer Punkt bei textViews ist, dass ihre Höhe so sein kann, dass die Tastatur den unteren Rand der textView abschneidet und sich nicht anpasst, wenn der obere linke Punkt der Ansicht angezeigt wird. Der Code, den ich geschrieben habe, verwendet also den bildschirmbezogenen unteren linken Punkt einer Textansicht oder eines Textfelds und prüft, ob er in die bildschirmbezogenen Koordinaten der dargestellten Tastatur fällt, was bedeutet, dass die Tastatur einen Teil davon abdeckt.

let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
    if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY))) {
        // scroll textView/textField into view
    }

Wenn Sie einen Navigationscontroller verwenden, setzt die Unterklasse auch die automatische Anpassung der Bildlaufansicht für Einfügungen auf false.

self.automaticallyAdjustsScrollViewInsets = false

Es geht durch jede textView und jedes textField, um Delegaten für die Behandlung festzulegen

    for view in self.view.subviews {
        if view is UITextView {
            let tv = view as! UITextView
            tv.delegate = self
        } else if view is UITextField {
            let tf = view as! UITextField
            tf.delegate = self
        }
    }

Setzen Sie Ihre Basisklasse einfach auf die hier erstellte Unterklasse, um Ergebnisse zu erzielen.

import UIKit

class ScrollingFormViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {

var activeFieldRect: CGRect?
var keyboardRect: CGRect?
var scrollView: UIScrollView!

override func viewDidLoad() {

    self.automaticallyAdjustsScrollViewInsets = false

    super.viewDidLoad()

    // Do any additional setup after loading the view.
    self.registerForKeyboardNotifications()
    for view in self.view.subviews {
        if view is UITextView {
            let tv = view as! UITextView
            tv.delegate = self
        } else if view is UITextField {
            let tf = view as! UITextField
            tf.delegate = self
        }
    }
    scrollView = UIScrollView(frame: self.view.frame)
    scrollView.scrollEnabled = false
    scrollView.showsVerticalScrollIndicator = false
    scrollView.showsHorizontalScrollIndicator = false
    scrollView.addSubview(self.view)
    self.view = scrollView
}

override func viewDidLayoutSubviews() {
    scrollView.sizeToFit()
    scrollView.contentSize = scrollView.frame.size
    super.viewDidLayoutSubviews()
}

deinit {
    self.deregisterFromKeyboardNotifications()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWasShown), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    let info : NSDictionary = notification.userInfo!
    keyboardRect = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
    adjustForKeyboard()
}


func keyboardWillBeHidden(notification: NSNotification)
{
    keyboardRect = nil
    adjustForKeyboard()
}

func adjustForKeyboard() {
    if keyboardRect != nil && activeFieldRect != nil {
        let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
        if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY)))
        {
            scrollView.scrollEnabled = true
            let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardRect!.size.height, 0.0)
            scrollView.contentInset = contentInsets
            scrollView.scrollIndicatorInsets = contentInsets
            scrollView.scrollRectToVisible(activeFieldRect!, animated: true)
        }
    } else {
        let contentInsets : UIEdgeInsets = UIEdgeInsetsZero
        scrollView.contentInset = contentInsets
        scrollView.scrollIndicatorInsets = contentInsets
        scrollView.scrollEnabled = false
    }
}

func textViewDidBeginEditing(textView: UITextView) {
    activeFieldRect = textView.frame
    adjustForKeyboard()
}

func textViewDidEndEditing(textView: UITextView) {
    activeFieldRect = nil
    adjustForKeyboard()
}

func textFieldDidBeginEditing(textField: UITextField)
{
    activeFieldRect = textField.frame
    adjustForKeyboard()
}

func textFieldDidEndEditing(textField: UITextField)
{
    activeFieldRect = nil
    adjustForKeyboard()
}

}
user2690492
quelle
0

Es gibt bereits großartige Antworten, aber dies ist eine andere Art, mit dieser Situation umzugehen (mit Swift 3x ):

Rufen Sie zunächst die folgende Methode in auf viewWillAppear()

func registerForKeyboardNotifications() {

NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

}

Nun nehmen Sie eine IBOutletvon UIViewden Top Einschränkungen Ihres UIViewcontrollerwie folgt aus : (hier UIViewist die Subview , UIScrollViewdass Mittel sollten Sie eine haben UIScrollViewfür alle subViews)

@IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint!

Und eine andere Variable wie die folgende und fügen Sie einen Delegaten hinzu, dh UITextFieldDelegate:

var activeTextField = UITextField() //This is to keep the reference of UITextField currently active

Danach ist hier der magische Teil, fügen Sie einfach diesen folgenden Ausschnitt ein :

func keyboardWasShown(_ notification: Notification) {

let keyboardInfo  = notification.userInfo as NSDictionary?

//print(keyboardInfo!)

let keyboardFrameEnd: NSValue? = (keyboardInfo?.value(forKey: UIKeyboardFrameEndUserInfoKey) as? NSValue)

let keyboardFrameEndRect: CGRect? = keyboardFrameEnd?.cgRectValue


if activeTextField.frame.origin.y + activeTextField.frame.size.height + 10 > (keyboardFrameEndRect?.origin.y)! {

    UIView.animate(withDuration: 0.3, delay: 0, options: .transitionFlipFromTop, animations: {() -> Void in

        //code with animation

        //Print some stuff to know what is actually happening
        //print(self.activeTextField.frame.origin.y)
        //print(self.activeTextField.frame.size.height)
        //print(self.activeTextField.frame.size.height)

        self.loginViewTopConstraint.constant = -(self.activeTextField.frame.origin.y + self.activeTextField.frame.size.height - (keyboardFrameEndRect?.origin.y)!) - 30.0

        self.view.layoutIfNeeded()

    }, completion: {(_ finished: Bool) -> Void in
        //code for completion

    })
}
}

func keyboardWillBeHidden(_ notification: Notification) {

UIView.animate(withDuration: 0.3, animations: {() -> Void in

    self.loginViewTopConstraint.constant = self.view.frame.origin.y
    self.view.layoutIfNeeded()

})
}

//MARK: textfield delegates
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    activeTextField = textField
    return true
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

           switch textField {
    case YOUR_TEXTFIELD_ONE:
        YOUR_TEXTFIELD_TWO.becomeFirstResponder()
        break
    case YOUR_TEXTFIELD_TWO:
        YOUR_TEXTFIELD_THREE.becomeFirstResponder()
        break
    default:
        textField.resignFirstResponder()
        break
    }
    return true
}

Nun der letzte Ausschnitt:

//Remove Keyboard Observers
override func viewWillDisappear(_ animated: Bool) {

NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)

NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

Vergessen Sie nicht, assign Delegierten auf alle Ihre UITextFields inUIStoryboard

Viel Glück!

Anurag Sharma
quelle
0

Swift 3-Syntax:

func textFieldDidBeginEditing(_ textField: UITextField) {
    // add if for some desired textfields
        animateViewMoving(up: true, moveValue: 100)
}

func textFieldDidEndEditing(_ textField: UITextField) {
    // add if for some desired textfields
        animateViewMoving(up: false, moveValue: 100)
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
     textFieldDidEndEditing(_ textField: UITextField) {

    let movementDuration:TimeInterval = 0.5

    let movement:CGFloat = ( up ? -moveValue : moveValue)

    UIView.beginAnimations("animateView", context: nil)

    UIView.setAnimationBeginsFromCurrentState(true)

    UIView.setAnimationDuration(movementDuration)

    self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)

    UIView.commitAnimations()
}

Dies ist eine nette Methode, um das zu bekommen, was Sie wollen. Sie können "if" -Bedingungen für bestimmte Textfelder hinzufügen, aber dieser Typ funktioniert für alle ... Ich hoffe, er kann für alle nützlich sein

Atrin Noori
quelle
0

Deklarieren Sie zunächst eine Variable, um Ihr aktives UITextField zu identifizieren.

Schritt 1:-

Wie als var activeTextField: UITextField ?

Schritt 2: - Fügen Sie anschließend diese beiden Zeilen in viewDidLoad hinzu.

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)

Schritt 3:-

Definieren Sie nun diese beiden Methoden in Ihrer Controller-Klasse.

func keyboardWillShow(_ notification: NSNotification) {

    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeField = self.activeField {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}


func keyboardWillHide(_ notification: NSNotification) {

    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = true
}


func textFieldDidBeginEditing(_ textField: UITextField){

    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){

    activeField = nil
}
Hemendra Singh
quelle
0

für schnelle 4.2.

Dies gilt für jede Form. Keine Bildlaufansicht erforderlich. Vergessen Sie nicht, den Delegaten festzulegen.

Machen Sie eine Var von uitextfield

var clickedTextField = UITextField()

In Ihrer Ansicht wurde geladen

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);

Kennen Sie das angeklickte Textfeld. Wahrscheinlich haben Sie Textfelder auf dem gesamten Bildschirm.

func textFieldDidBeginEditing(_ textField: UITextField) {
    clickedTextField = textField
}

Überprüfen Sie, ob die Tastatur ein Textfeld abdeckt oder nicht.

@objc func keyboardWillShow(sender: NSNotification,_ textField : UITextField) {
    if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

        if clickedTextField.frame.origin.y > keyboardSize.origin.y {
            self.view.frame.origin.y = keyboardSize.origin.y - clickedTextField.center.y - 20
        }
    }
}

@objc func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y = 0
}

Zurück zum Schließen der Tastatur

func textFieldShouldReturn(_ textField: UITextField) -> Bool {   //delegate method
    textField.resignFirstResponder()
    return true
}

UPDATE: NSNotification.Name.UIKeyboardWillShow und NSNotification.Name.UIKeyboardWillHide werden in UIResponder.keyboardWillShowNotification bzw. UIResponder.keyboardWillHideNotification umbenannt.

Rupesh45
quelle
0

Swift : Sie können dies tun, indem Sie überprüfen, welches Textfeld angezeigt wird.

@objc func keyboardWillShow(notification: NSNotification) {
    if self.textField.isFirstResponder == true {
        self.view.frame.origin.y -= 150
     }
}

@objc func keyboardWillHide(notification: NSNotification){
    if self.textField.isFirstResponder == true {
       self.view.frame.origin.y += 150
    }
}
ZAFAR007
quelle
-1

Dieser Code verschiebt das Textfeld, das Sie bearbeiten, nach oben, damit Sie es in Swift 3 anzeigen können. Für diese Antwort müssen Sie Ihre Ansicht auch zu einem UITextFieldDelegate machen:

var moveValue: CGFloat!
var moved: Bool = false
var activeTextField = UITextField()

func textFieldDidBeginEditing(_ textField: UITextField) {
    self.activeTextField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
    if moved == true{
    self.animateViewMoving(up: false, moveValue: moveValue )
        moved = false
    }
}
func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:TimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)

    UIView.beginAnimations("animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration)

    self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
    UIView.commitAnimations()
}

Und dann in viewDidLoad:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)

Welche Aufrufe (außerhalb von viewDidLoad):

func keyboardWillShow(notification: Notification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardHeight = keyboardSize.height
        if (view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height < keyboardHeight{
            moveValue = keyboardHeight - ((view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height)
            self.animateViewMoving(up: true, moveValue: moveValue )
            moved = true
        }
    }
}
joshLor
quelle
-1

Swift 3

@IBOutlet var scrollView: UIScrollView!
@IBOutlet var edtEmail: UITextField!
@IBOutlet var bottomTextfieldConstrain: NSLayoutConstraint! // <- this guy is the constrain that connect the bottom of textField to lower object or bottom of page!

 @IBAction func edtEmailEditingDidBegin(_ sender: Any) { 
        self.bottomTextfieldConstrain.constant = 200
        let point = CGPoint(x: 0, y: 200)
        scrollView.contentOffset = point
    }

@IBAction func edtEmailEditingDidEnd(_ sender: Any) { 
    self.bottomTextfieldConstrain.constant = 50
}
Alfi
quelle
-1

Die akzeptierte Antwort ist fast perfekt. Aber ich muss UIKeyboardFrameEndUserInfoKeystattdessen verwenden, UIKeyboardFrameBeginUserInfoKey,weil letztere die Keyborad-Höhe 0 zurückgeben. Und den schärfsten Punkt nach unten ändern, nicht den Ursprung.

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeField = self.activeField {
        var point = activeField.frame.origin
        point.y += activeField.frame.size.height
        if (!aRect.contains(point)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
Victor Choy
quelle
-1

Swift 4 Meine Lösung wurde aktualisiert

Mit Constraint-Animation auf der Tastatur ein- / ausblenden, viel Spaß.

import Foundation
import UIKit

class PhoneController: UIViewController, UITextFieldDelegate{

    var phoneLayoutYConstraint: NSLayoutConstraint?

    override func viewDidLoad() {

        super.viewDidLoad()

        view.backgroundColor = .white

        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        phoneField.delegate = self

        view.addSubview(phoneField)

        NSLayoutConstraint.activate([phoneField.heightAnchor.constraint(equalToConstant: 50),
                                     phoneField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                                     phoneField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
                                     phoneField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)])

        phoneLayoutYConstraint = NSLayoutConstraint(item: phoneField, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
        phoneLayoutYConstraint?.isActive = true

    }

    let phoneField: UITextField = {
        let text = UITextField()
        text.translatesAutoresizingMaskIntoConstraints = false
        text.keyboardType = .numberPad
        text.font = UIFont.systemFont(ofSize: 30)
        text.layer.cornerRadius = 5.0
        text.layer.masksToBounds = true
        text.layer.borderColor = UIColor.darkGray.cgColor
        text.layer.borderWidth = 2.0

        return text
    }()


    override func viewDidDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self)
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {

    }


    func textFieldDidEndEditing(_ textField: UITextField) {

    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }


   @objc func handleKeyBoardNotification(_ notification: NSNotification) {

        if let info = notification.userInfo {

            let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
            let isKeyBoardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow

            var aRect : CGRect = self.phoneField.frame
            aRect.size.height -= keyboardSize!.height


            phoneLayoutYConstraint?.constant = isKeyBoardShowing ? -keyboardSize!.height : 0

            UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
                self.view.layoutIfNeeded()
            }, completion: { (boo) in

            })

        }
    }

}
Hattori Hanzō
quelle
-1

Swift 4

Sie können leicht UITextFieldmit der Tastatur mit Animation auf und ab bewegen

Geben Sie hier die Bildbeschreibung ein

import UIKit

class ViewController: UIViewController {

    @IBOutlet var textField: UITextField!

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

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }

    @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)
    }
ZAFAR007
quelle
Wieder eine Lösung, die die Ansicht unnötig nach oben drückt, selbst wenn sie nicht benötigt wird. Bitte verbessern Sie Ihre Antwort, es ist irreführend
Shivam Pokhriyal
-1

Swift 4.2

Meine Lösung zentriert die Ansicht (vertikal) auf a UITextField wenn sich ihre Position unter der Tastatur befindet.

Schritt 1: Erstellen Sie eine neue schnelle Datei und kopieren Sie die Einfügeklasse UIViewWithKeyboard.
Schritt 2: Legen Sie im Interface Builder eine benutzerdefinierte Klasse für Ihre Top-Klasse fest UIView.

import UIKit

class UIViewWithKeyboard: UIView {
    @IBInspectable var offsetMultiplier: CGFloat = 0.75
    private var keyboardHeight = 0 as CGFloat
    private weak var activeTextField: UITextField?
    override func awakeFromNib() {
        super.awakeFromNib()
        NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.textDidBeginEditing),
                                               name: UITextField.textDidBeginEditingNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillShow),
                                               name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillHide),
                                               name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc func textDidBeginEditing(_ notification: NSNotification) {
        self.activeTextField = notification.object as? UITextField
    }

    @objc func keyboardWillShow(_ notification: Notification) {
        if let frameValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
            keyboardHeight = frameValue.cgRectValue.size.height
            if let textField = self.activeTextField {
                let offset = textField.frame.maxY < frame.maxY - keyboardHeight ? 0
                           : textField.frame.maxY - (frame.maxY - keyboardHeight) * offsetMultiplier
                self.setView(offset: offset)
            }
        }
    }

    @objc func keyboardWillHide(_ notification: NSNotification) {
        self.setView(offset: 0)
    }

    func setView(offset: CGFloat) {
        UIView.animate(withDuration: 0.25) {
            self.bounds.origin.y = offset
        }
    }
}
Umfang
quelle
-1

Für schnell umgeschrieben 4.2

In ViewDidLoad ..

 NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWasShown), name: UIResponder.keyboardWillShowNotification, object: nil)
 NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWillBeHidden), name: UIResponder.keyboardWillHideNotification, object: nil)

Verbleibende Funktionen

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeField = self.activeField {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

@objc func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}
VarunRaj
quelle
-2

"Ich habe vergessen zu erwähnen, dass ich neu bei Swift bin :( Was wäre die richtige Syntax, um dies zu überprüfen? (Wie erhalte ich den Feldnamen in dieser Funktion?)"

OK . Bestätigen Sie zuerst das UITextFieldDelegate-Protokoll

class YourClass:UITextFieldDelegate

Dann implementieren Sie die Funktion

func textFieldDidBeginEditing(textField: UITextField!) {

    if textField == txtOne
    {
        println("TextOne")
    }
    if textField == txtTwo
    {
        println("TextTwo")
    }
}

Sie sollten beachten, dass der richtige Ansatz darin besteht, eine Bildlaufansicht zu verwenden und die Ansicht, die nach oben / unten verschoben werden soll, in der Bildlaufansicht zu platzieren und Tastaturereignisse entsprechend zu behandeln

bescheidenPilgrim
quelle
-3

Für Swift 4.2

Mit diesem Code können Sie das Moment der Y-Achse des Rahmens für eine bestimmte Bildschirmgröße des Geräts steuern.

PS: Dieser Code verschiebt den Frame basierend auf der Position von TextField nicht intelligent.

Erstellen Sie eine Erweiterung für UIDevice

extension UIDevice {
    enum ScreenType: String {
        case iPhone4_4S = "iPhone 4 or iPhone 4s"
        case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE"
        case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6s, iPhone 7 or iPhone 8"
        case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6s Plus, iPhone 7 Plus or iPhone 8 Plus"
        case iPhoneX_Xs = "iPhone X, iPhone Xs"
        case iPhoneXR = "iPhone XR"
        case iPhoneXSMax = "iPhone Xs Max"
        case unknown
    }
    var screenType: ScreenType {
        switch UIScreen.main.nativeBounds.height {
        case 960:
            return .iPhone4_4S
        case 1136:
            return .iPhones_5_5s_5c_SE
        case 1334:
            return .iPhones_6_6s_7_8
        case 1920, 2208:
            return .iPhones_6Plus_6sPlus_7Plus_8Plus
        case 1792:
            return .iPhoneXR
        case 2436:
            return .iPhoneX_Xs
        case 2688:
            return .iPhoneXSMax
        default:
            return .unknown
        }
    }
}

Fügen Sie NotificationObserver in viewDidLoad hinzu

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)

Wähler

@objc func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        if self.view.frame.origin.y == 0 {
            switch (UIDevice.current.screenType.rawValue) {
            case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
                self.view.frame.origin.y -= 210
            case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
                self.view.frame.origin.y -= 110
            case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
                self.view.frame.origin.y -= 80
            case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
                self.view.frame.origin.y -= 70
            case (UIDevice.ScreenType.iPhoneXR.rawValue):
                self.view.frame.origin.y -= 70
            case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
                self.view.frame.origin.y -= 70
            default:
                self.view.frame.origin.y -= 150
            }
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        if self.view.frame.origin.y != 0 {
            switch (UIDevice.current.screenType.rawValue) {
            case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
                self.view.frame.origin.y += 210
            case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
                self.view.frame.origin.y += 110
            case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
                self.view.frame.origin.y += 80
            case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
                self.view.frame.origin.y += 70
            case (UIDevice.ScreenType.iPhoneXR.rawValue):
                self.view.frame.origin.y += 70
            case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
                self.view.frame.origin.y += 70
            default:
                self.view.frame.origin.y += 150
            }
        }
    }
}
Kavin Varnan
quelle
1
Im Allgemeinen würde ich sagen, dass es ein schlechter und ziemlich kostspieliger Ansatz ist, gerätespezifische Typen und Hardcode-Layout-bezogene Abmessungen zu verwenden, da sie sich ständig ändern.
Johan