Verschieben Sie die Ansicht mit der Tastatur mit Swift


278

Ich habe eine App mit einem Textfeld in der unteren Hälfte der Ansicht. Dies bedeutet, dass beim Eingeben des Textfelds die Tastatur das Textfeld abdeckt.

Wie würde ich vorgehen, um die Ansicht beim Tippen nach oben zu verschieben, damit ich sehen kann, was ich tippe, und sie dann wieder an ihren ursprünglichen Platz zurückzuschieben, wenn die Tastatur verschwindet?

Ich habe überall gesucht, aber alle Lösungen scheinen in Obj-C zu sein, die ich noch nicht ganz konvertieren kann.

Jede Hilfe wäre sehr dankbar.


Der beste Weg, dies zu tun, besteht darin, Ihren Inhalt in einer UIScrollView zu platzieren und dann die contentInset- Eigenschaft der Bildlaufansicht an die Höhe der Tastatur anzupassen, wenn sie angezeigt wird. Nehmen Sie auf keinen Fall die Tastaturhöhe an - verwenden Sie den Wert aus der Benachrichtigung "Tastatur wird angezeigt".
Nielsbot

1
In den Apple-Dokumenten erfahren Sie unter "Verwalten der Tastatur", wie dies zu tun ist: developer.apple.com/library/ios/documentation/StringsTextFonts/…
nielsbot

11
Ich denke, alle Antworten unten berücksichtigen nicht einen Fall: Was ist, wenn Sie mehrere Textfelder haben und einige davon sich oben auf dem Bildschirm befinden? Jedes Mal, wenn der Benutzer auf dieses Textfeld tippt, geht es über den Bildschirm hinaus. Ich bin mir ziemlich sicher, dass die richtige Antwort erkennen sollte, obit is actually needed to scroll view up when keyboard appears
theDC

Diese Antwort kann erkennen, ob es tatsächlich erforderlich ist, die Ansicht nach oben zu scrollen, wenn die Tastatur angezeigt wird, indem überprüft wird, ob das aktuell bearbeitete Textfeld denselben Platz wie die Tastatur einnimmt
HirdayGupta

Antworten:


709

Hier ist eine Lösung, ohne den Wechsel von einem Textfeld zu einem anderen zu handhaben:

 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?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y -= keyboardSize.height
    }            
}

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

Um dies zu lösen, ersetzen Sie die beiden Funktionen keyboardWillShow/Hidedurch folgende:

func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] 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
    }
}

BEARBEITEN FÜR 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?[UIKeyboardFrameEndUserInfoKey] 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
    }
}

BEARBEITEN FÜR 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?[UIKeyboardFrameEndUserInfoKey] 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
    }
}

BEARBEITEN FÜR 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.keyboardFrameEndUserInfoKey] 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
    }
}

56
Wenn der Benutzer ein anderes Textfeld berührt, während die Tastatur vorhanden ist, wird die Ansicht weiter nach oben verschoben, wodurch ein schwarzer Bereich (die Größe der Tastatur) entsteht. Wir müssen dies beheben, indem wir eine Variable haben, die verfolgt, ob die Tastatur vorhanden ist oder nicht . zB wenn keyboardPresent == true, dann verschieben Sie nicht den Ansichtsursprung usw. usw.
jonprasetyo

3
@ Matthew Lin verwenden einen Booleschen Wert, so dass die Funktionen KeyboardWillShow und Hide nur einmal funktionieren
iluvatar_GR

11
Nur ein Vorschlag, damit Sie nicht so viel debuggen müssen wie ich. Wenn Sie mehrere Uitextfelder auf demselben Bildschirm haben, kann die Tastaturgröße variieren (es werden keine Vorschläge für einige Eingaben basierend auf Ihren Einstellungen angezeigt). Es ist daher ratsam, jedes Mal self.view.frame.origin.y = 0 festzulegen Sie schließen die Tastatur. Beispielsweise werden Sugeestions für Ihr E-Mail-Textfeld angezeigt, sodass die Tastaturgröße zunimmt, und es werden keine Vorschläge für das Kennwortfeld angezeigt, sodass die Tastaturgröße abnimmt.
Vandan Patel

36
Sie müssen verwenden, UIKeyboardFrameEndUserInfoKeyanstatt UIKeyboardFrameBeginUserInfoKeydie Tastaturgröße zu erhalten. Ich bin mir im Moment nicht sicher, warum, aber erstere werden konsistentere Ergebnisse liefern.
Jshapy8

3
Bitte ersetzen Sie UIKeyboardFrameBeginUserInfoKeymit UIKeyboardFrameEndUserInfoKey. Der erste gibt den Startrahmen der Tastatur an, der manchmal Null ist, während der zweite den Endrahmen der Tastatur angibt.
Arnab

90

Der einfachste Weg, der nicht einmal Code erfordert:

  1. Laden Sie KeyboardLayoutConstraint.swift herunter und fügen Sie die Datei per Drag & Drop zu Ihrem Projekt hinzu, wenn Sie das Spring-Animationsframework noch nicht verwenden.
  2. Erstellen Sie in Ihrem Storyboard eine untere Einschränkung für die Ansicht oder das Textfeld, wählen Sie die Einschränkung aus (doppelklicken Sie darauf) und ändern Sie im Identitätsinspektor die Klasse von NSLayoutConstraint in KeyboardLayoutConstraint.
  3. Getan!

Das Objekt bewegt sich synchron mit der Tastatur automatisch nach oben.


4
Um die unterste Einschränkung auszuwählen, können Sie auch zum Größeninspektor
raywenderlich.com/wp-content/uploads/2015/09/…

3
Das hat perfekt für mich funktioniert. Es ist buchstäblich ein 2-Schritt-Prozess. 1. Fügen Sie KeyboardLayoutConstraint.swift hinzu. 2. Erstellen Sie im Storyboard eine untere Einschränkung für die Ansicht oder das Textfeld. HINWEIS: Ich habe meine Einschränkungen gelöscht und nur eine Einschränkung am unteren Rand der Ansicht oder des Textfelds hinzugefügt und deren Klasse von NSLayoutConstraint in KeyboardLayoutConstraint geändert. Dann alle Ansichten / Textfelder usw. oben Ich habe nur Einschränkungen von diesem Element mit dem Element mit einer einzigen KeyboardLayoutConstraint verbunden und das Ergebnis war, dass alle Elemente in der Ansicht nach oben / UNTEN verschoben wurden, wenn die Tastatur erscheint / verschwindet
Brian

4
Dies ist die beste Lösung. Der bereitgestellte Code codiert keine Werte wie die Länge oder Kurve der Animation oder die Größe der Tastatur fest. Es ist auch leicht zu verstehen.
Miguel Santirso

3
Dies funktioniert für mich, aber ich bekomme einen zusätzlichen Abstand von 50 Pixel zwischen der Oberseite der Tastatur und der Unterseite meiner scrollView. Ich frage mich, ob dies an der von mir verwendeten unteren Einschränkung für den sicheren Bereich liegt. Ist jemand darauf gestoßen?
Clifton Labrum

1
Dies war eine großartige Antwort. Sehr cooles Design. Ein Vorschlag: Wenn sich Ihre Textansichten / Textfelder in Zellen der Tabellenansicht befinden, werden Sie möglicherweise feststellen, dass die Ansichten mit dieser Einschränkung jedes Mal, wenn der Benutzer auf die Eingabetaste klickt, ungeschickt springen und zum nächsten Textfeld wechseln. Sie können die Animationen einpacken, um das Problem DispatchQueue.main.async {}zu beheben. Gute Arbeit! Daumen hoch!
ScottyBlades

68

Eine der beliebtesten Antworten in diesem Thread verwendet den folgenden Code:

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

Es gibt ein offensichtliches Problem beim Versetzen Ihrer Ansicht um einen statischen Betrag. Auf einem Gerät sieht es gut aus, auf jeder anderen Größenkonfiguration jedoch schlecht. Sie müssen die Höhe der Tastatur ermitteln und diese als Versatzwert verwenden.

Hier ist eine Lösung, die auf allen Geräten funktioniert und den Randfall behandelt, bei dem der Benutzer das Textfeld für die Vorhersage während der Eingabe ausblendet.

Lösung

Es ist wichtig zu beachten, dass wir self.view.window als unseren Objektparameter übergeben. Dadurch erhalten wir Daten von unserer Tastatur, wie z. B. die Höhe!

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

Wir sorgen dafür, dass es auf allen Geräten gut aussieht, und behandeln den Fall, in dem der Benutzer das Textfeld für die Vorhersage hinzufügt oder entfernt.

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

Beobachter entfernen

Vergessen Sie nicht, Ihre Beobachter zu entfernen, bevor Sie die Ansicht verlassen, um zu verhindern, dass unnötige Nachrichten übertragen werden.

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

Update basierend auf Frage aus Kommentaren:

Wenn Sie zwei oder mehr Textfelder haben, können Sie überprüfen, ob Ihre view.frame.origin.y auf Null steht.

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

1
Wenn Sie mit mehreren Textfeldern arbeiten, bewegt sich die Ansicht weiter nach oben und nicht nach unten
Mugunthan Balakrishnan

Sie müssen Ihre Bedingungen ändern, um die Textfelder zu berücksichtigen
Dan Beaulieu


@ MugunthanBalakrishnan, danke, dass du das angesprochen hast. Ich habe eine Lösung hinzugefügt.
Dan Beaulieu

Hallo Leute, es gibt einen Fehler. Die Beobachter werden nach dem Aufruf von viewWillDisappear nicht aus der Ansicht entfernt. Ersetzen Sie diese Zeile "NSNotificationCenter.defaultCenter (). RemoveObserver (self, Name: UIKeyboardWillHideNotification, Objekt: self.view.window)" durch "NSNotificationCenter.defaultCenter (). RemoveObserver (self, Name: UIKeyboardWillHideNotification, Objekt: nil)" und dann Beobachter wird entfernt
Rudald

29

Fügen Sie dies Ihrem Viewcontroller hinzu. Klappt wunderbar. Passen Sie einfach die Werte an.

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
}

Das funktioniert bei mir. Es ist jedoch ein wenig ruckelig. Wie kann ich das dazu bringen, glatt zu werden? Es gibt auch eine Möglichkeit, es nur auf eines der Textfelder anzuwenden, da dies derzeit für alle gilt. :(
DannieCoderBoi

2
Es funktioniert möglicherweise nicht mit "Auto-Layout". Deaktivieren Sie es daher, wenn dies der Fall ist.
Teodor Ciuraru

1
Es verursacht ein unkonventionelles Verhalten mit Autolayout @Josh, Sie irren sich
Mike

5
Tu das nicht! Sie können nicht davon ausgehen, dass die Tastatur eine bestimmte Größe hat.
Nielsbot

2
Sollte Tastaturgröße verwenden. Was passiert, wenn Sie Zubehöransichten und unterschiedliche Tastaturhöhen auf Geräten haben? Freistehende Tastatur?
Xtrinch

25

Ich habe eine der Antworten ein wenig verbessert, damit sie mit verschiedenen Tastaturen und verschiedenen Textansichten / Feldern auf einer Seite funktioniert:

Beobachter hinzufügen:

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

Beobachter entfernen:

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

3
Diese Lösung funktioniert besser als die akzeptierte Antwort. Akzeptierte Antwort zeigt die Tastatur nur einmal, was für mich ein Fehler ist :)
Masih

Dies funktioniert für Xcode 10.1 und iOS 12. Die akzeptierte Antwort ist nicht mehr gültig.
Zeeshan

Dies ist eine ausgezeichnete Antwort. Das einzige, was ich hinzufügen möchte, ist, den unteren Sicherheitsbereich in den neueren Geräten (X, XS usw.) zu verfolgen, damit dies berücksichtigt wird.
Munib

@Munib Siehe stackoverflow.com/a/54993623/1485230 Weitere Probleme sind, dass die Ansicht nicht animiert wird und die Änderung der Tastaturhöhe nicht befolgt wird.
Antzi

Was ist, wenn mein Textfeld ganz oben in der Ansicht ist? Ich meine, wenn es ein Textfeld mit Ursprung Y = 0 gibt. dann steigt textField und ich kann es nicht sehen
Saifan Nadaf

18

Keine Werbung, Promotion oder Spam , nur eine gute Lösung. Ich weiß, dass diese Frage fast 30 Antworten hat und ich bin so schockiert, dass niemand einmal von diesem wunderschönen GitHub-Projekt gesprochen hat , das alles für Sie und noch besser macht. Alle Antworten verschieben nur die Ansicht nach oben. Ich habe gerade alle meine Probleme mit diesem IQKeyboardManager gelöst. Es hat mehr als 13000 Sterne.
Fügen Sie dies einfach in Ihre Poddatei ein, wenn Sie Swift verwenden

pod 'IQKeyboardManagerSwift'

und dann in Ihrem AppDelegate.swift tun import 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
    }
}

Fügen Sie die Zeile hinzu IQKeyboardManager.shared.enable = true, um sie zu aktivieren.
Diese Lösung ist ein Muss, wenn Sie in Produktion gehen möchten.


Das ist wirklich gut, aber die neueste Version funktioniert nicht für mich, ich habe 6.2.1 verwendet und als AppDelegate importiert import IQKeyboardManagerund verwendetIQKeyboardManager.shared().isEnabled = true
Dhanu K

2
Und dies funktioniert hervorragend, wenn mehrere Bearbeitungstexte verwendet werden. Dies hat mir Zeit gespart
Dhanu K

1
Ich kann nicht genug dafür danken, dass ich auf diese wundervolle Bibliothek hingewiesen habe. Diese Bibliothek ist endlich DIE ENDGÜLTIGE ANTWORT auf alle Tastaturprobleme, für die Apple nie eine Lösung bereitgestellt hat. Jetzt werde ich es für alle meine neuen und alten Projekte verwenden und Zeit und Kopfschmerzen sparen, die durch das Erscheinen, Verschwinden oder Nicht-Verschwinden dieser Tastatur oder durch das Ausblenden und warum sie sich überschneiden, verursacht werden Tag programmiere ich für iPhones.
Zeeshan

1
Ich hatte meinen eigenen Code geschrieben, um das Textfeld zu verschieben, ähnlich wie die anderen Lösungen hier. Ich fand, dass IQKeyboardManager sehr gut ist und ich werde es von nun an integrieren. Hält meinen Code für den Fall bereit, dass das Framework nicht auf dem neuesten Stand gehalten wird.
TM Lynch

@DhanuK, habe gerade diese Bibliothek gefunden und funktioniert perfekt und es ist mühelos. Der App-Delegatencode wurde auf IQKeyboardManager.shared.enable = true aktualisiert
adougies

15

Für Black Screen Error (Swift 4 & 4.2) .

Ich habe das Problem mit dem schwarzen Bildschirm behoben. In der verifizierten Lösung Die Tastaturhöhe ändert sich nach dem Tippen und dies führt zu einem schwarzen Bildschirm.

Haben Sie verwenden UIKeyboardFrameEndUserInfoKey statt UIKeyboardFrameBeginUserInfoKey

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

Funktioniert nicht, wenn eine Registerkarte vorhanden ist. Sie müssen die Höhe der Registerkartenleiste berechnen, da sonst zwischen Tastatur und Ansicht eine schwarze Bildschirmlücke besteht.
Ankur Lahiry

Dadurch wird der schwarze Bereich, in dem sich die Tastatur auf dem iPhone X und höher befand, nicht behoben. Und jedes Mal, wenn die Tastatur erscheint und verschwindet, rutscht die Hauptansicht nach unten.
Edison

14

Ich sehe, dass alle Antworten die Ansicht selbst um den Wert der Tastaturhöhe verschieben. Nun, ich habe eine ausführliche Antwort, die nützlich sein kann, wenn Sie Einschränkungen verwenden, dh autolayouteine Ansicht verschieben, indem Sie den Einschränkungswert (z. B. untere oder obere Einschränkungen) um einen vordefinierten Wert ändern oder den Tastaturgrößenwert verwenden.

In diesem Beispiel verwende ich die untere Einschränkung vom Textfeld zur unteren Layoutansicht mit dem Anfangswert 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()
    }
}

Hallo Herr, können Sie mir bitte sagen, warum dies nicht funktioniert, wenn es in einer Ansicht platziert wird, die auch eine Tabellenansicht enthält? Es funktioniert im selben Szenario einwandfrei, wenn es eine CollectionView enthält.
Elarcoiris

9

Es wurden einige Änderungen an der Definition der KeyboardWillHideNotification vorgenommen.

Diese Lösung funktioniert mit 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
    }
}

2
Was ist, wenn mein Textfeld ganz oben in der Ansicht ist? Ich meine, wenn es ein Textfeld mit Ursprung Y = 0 gibt. dann steigt textField und ich kann es nicht sehen
Saifan Nadaf

7

Swift 5.0:

Nach 4-5 Stunden Kampf kam ich mit einer einfachen Erweiterung von UIViewController mit einfachem Code, der wie Charme funktioniert

* Die Ansicht sollte sich nicht bewegen, wenn sich TextField über der Tastatur befindet

* Es ist nicht erforderlich, einen konstanten Wert auf NSLayoutConstraint festzulegen

* Keine Bibliothek von Drittanbietern erforderlich

* Kein Animationscode erforderlich

* Funktioniert auch in der Tabellenansicht

* Dies funktioniert bei automatischem Layout / automatischer Größenänderung

extension UIViewController {
    func addKeyboardObserver() {
        NotificationCenter.default.addObserver(self, selector: #selector(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 txtFieldY : CGFloat = 0.0  //Using this we will calculate the selected textFields Y Position
        let spaceBetweenTxtFieldAndKeyboard : CGFloat = 5.0 //Specify the space between textfield and keyboard


        var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        if let activeTextField = UIResponder.currentFirst() as? UITextField ?? UIResponder.currentFirst() as? UITextView {
            // Here we will get accurate frame of textField which is selected if there are multiple textfields
            frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
            txtFieldY = frame.origin.y + 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
            let keyBoardFrameHeight = keyBoardFrame!.size.height

            var viewOriginY: CGFloat = 0.0
            //Check keyboards Y position and according to that move view up and down
            if keyBoardFrameY >= UIScreen.main.bounds.size.height {
                viewOriginY = 0.0
            } else {
                // if textfields y is greater than keyboards y then only move View to up
                if txtFieldY >= keyBoardFrameY {

                    viewOriginY = (txtFieldY - keyBoardFrameY) + spaceBetweenTxtFieldAndKeyboard

                    //This condition is just to check viewOriginY should not be greator than keyboard height
                    // if its more than keyboard height then there will be black space on the top of keyboard.
                    if viewOriginY > keyBoardFrameHeight { viewOriginY = keyBoardFrameHeight }
                }
            }

            //set the Y position of view
            self.view.frame.origin.y = -viewOriginY
        }
    }
}

Fügen Sie diese UIResponder-Erweiterung hinzu, um zu ermitteln, welches TextField ausgewählt ist

extension UIResponder {

    static weak var responder: UIResponder?

    static func currentFirst() -> UIResponder? {
        responder = nil
        UIApplication.shared.sendAction(#selector(trap), to: nil, from: nil, for: nil)
        return responder
    }

    @objc private func trap() {
        UIResponder.responder = self
    }
}

Verwenden Sie dies dann in einem beliebigen ViewController

   override func viewWillAppear(_ animated: Bool) {
        self.addKeyboardObserver()
    }

    override func viewWillDisappear(_ animated: Bool) {
        self.removeKeyboardObserver()
    }

  • Registrieren Sie diese Benachrichtigung in func viewWillAppear(_ animated: Bool)

  • Melden Sie diese Benachrichtigung in ab func viewWillDisappear(_ animated:Bool)

    Demo hier herunterladen


Dies schien die beste Lösung zu sein, es gibt jedoch einige Fehler. 1, das Textfeld wird nach oben verschoben, aber wenn ich anfange, es einzugeben, springt es etwas weiter nach oben. 2, Im Querformat springt das Textfeld beim Eingeben manchmal nach links.
Darren

@Darren Ich versuche diese Fehler herauszufinden, aber ich habe sie nicht gefunden. Kannst du bitte sagen, woher du diese Fehler hast? Ich meine für welche Version / welches Gerät ... ??
Saifan Nadaf

6

Für Swift 3 habe ich eine UIViewController-Unterklasse erstellt, da ich in allen View Controllern ein konstantes Verhalten benötigte.

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

Inspiriert von der Lösung von Pavle habe ich sie aktualisiert, um die Tastatur automatisch um einen bestimmten Prozentsatz des verbleibenden verfügbaren Speicherplatzes anzuheben und das fokussierte Feld rekursiv für ein korrektes Layout zu finden. Schnapp es dir
Noor Dawod

Meine Tab-Leiste bewegt sich auch mit dem Fenster nach oben! :(
Alfi

6

Die validierte Antwort berücksichtigt nicht die Position des Textfelds und weist einen Fehler auf (doppelte Verschiebung, nie wieder an die primäre Position zurückkehren, Verschiebung, selbst wenn sich das Texfeld oben in der Ansicht befindet ...)

Die Idee ist:

  • um den Fokus zu erhalten TextField absolute Y-Position
  • um die Tastaturhöhe zu erhalten
  • um die ScreenHeight zu bekommen
  • Berechnen Sie dann den Abstand zwischen Tastaturposition und Textfeld (wenn <0 -> die Ansicht nach oben verschieben)
  • Wenn Sie UIView.transform anstelle von UIView.frame.origin.y - = .. verwenden, ist es einfacher, mit UIView.transform = .identity zur ursprünglichen Position zurückzukehren

dann können wir die Ansicht nur bei Bedarf und der spezifischen Verschiebung verschieben, um das fokussierte texField direkt über der Tastatur zu haben

Hier ist der Code:

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

}}


Sehr gut! (In viewDidLoad haben Sie "VehiculeViewController" anstelle von "ViewController").
Ren

Eine viel vollständigere und nützlichere Antwort. Danke dir! Ich schlage vor, dass die Tastaturprüfung wie folgt aufgerufen wird, da sie eine konsistente Größe der Tastatur ergibt .size
Ben

4

Ich bemerkte, dass die anderen Antworten darin bestanden, einen Teil der Oberseite aus der Ansicht herauszuschneiden. Wenn Sie einfach die Größe der Ansicht ändern möchten, ohne Inhalte zu schneiden, versuchen Sie einfach diese Methode :)

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

4

Meine zwei Cent für Anfänger: In den obigen Beispielen ändert jemand die Koordinaten, andere verwenden "Autoresizing-Maske" und andere Einschränkungen:

Mischen Sie diese drei Arten von Logik nicht, wie Apple sagt. Wenn Sie Einschränkungen im Storyboard haben, versuchen Sie nicht, x / y zu ändern. Es funktioniert definitiv nicht.


4

Keine der anderen Antworten scheint es richtig zu machen.

Die gut benommene Tastatur unter iOS sollte:

  • Ändern Sie die Größe automatisch, wenn die Tastatur ihre Größe ändert (JA, ES KANN)
  • Animieren Sie mit der gleichen Geschwindigkeit wie die Tastatur
  • Animieren Sie mit derselben Kurve wie die Tastatur
  • Respektieren Sie gegebenenfalls sichere Bereiche.
  • Funktioniert auch im iPad / Undocked-Modus

Mein Code verwendet eine NSLayoutConstraintals deklarierte@IBOutlet

@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!

Sie können auch Transformationen verwenden, Offsets anzeigen, ... Ich denke, es ist einfacher mit der Einschränkung tho. Es funktioniert, indem eine Einschränkung nach unten gesetzt wird. Möglicherweise müssen Sie den Code ändern, wenn Ihre Konstante nicht 0 / Nicht nach unten ist.

Hier ist der Code:

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

3

seine 100% perfekte Antwort für alle Guy's Table Tableview Höhe beim Öffnen der Tastatur

Für 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
         }
    }

Dies ist die beste Antwort. tbl sollte tableView sein und ich habe einige Auffüllungen hinzugefügt: contentInset.bottom = keyboardFrame.size.height + 10
iphaaw

2

Für Swift 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

Swift 4:

Ich hatte ein Problem mit der am meisten akzeptierten Antwort, bei dem das Ausblenden der Tastatur die Ansicht nicht bis zum Ende der Seite (nur teilweise) zurückbrachte. Dies hat bei mir funktioniert (+ aktualisiert für 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
        }
    }
}

Was ist, wenn mein Textfeld ganz oben in der Ansicht ist? Ich meine, wenn es ein Textfeld mit Ursprung Y = 0 gibt. dann steigt textField und ich kann es nicht sehen
Saifan Nadaf

2

Ähnlich wie bei @Boris, aber in Swift 5 :

override func 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)
}

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

@IBAction func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

1

Hier ist meine Lösung (tatsächlich ist dieser Code für den Fall gedacht, dass Sie nur wenige Textfelder in Ihrer Ansicht haben, dies funktioniert auch für den Fall, dass Sie ein Textfeld haben).

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

Vergessen Sie nicht, den Delegaten auf die textFields
SwingerDinger

Ändern Sie die Bedingung in der Tastatur wird angezeigt als, wenn (! CGRectContainsPoint (aRect, newOrgin!) &&! Self.viewWasMoved)
KingofBliss

add self.viewWasMoved = false, wenn Sie den Frame zurücksetzen
KingofBliss

1

Aktualisiert für Swift 3 ...

Wie bereits erwähnt, müssen Sie der viewDidLoad () -Methode Ihres Controllers Benachrichtigungsbeobachter wie folgt hinzufügen:

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

Denken Sie daran, Ihre Beobachter gegebenenfalls zu entfernen (ich mache das in der viewWillDisappear () -Methode).

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)

Implementieren Sie dann Ihre Methoden zum Ein- und Ausblenden. Beachten Sie die Zeile, in der die App aufgefordert wird, Interaktionsereignisse zu ignorieren (beginIgnoringInteractionEvents). Dies ist wichtig, da der Benutzer ohne dieses Feld auf ein Feld oder sogar eine Bildlaufansicht tippen und die Verschiebung ein zweites Mal durchführen kann, was zu einem schrecklichen Fehler in der Benutzeroberfläche führt. Das Ignorieren von Interaktionsereignissen vor dem Ein- und Ausblenden der Tastatur verhindert Folgendes:

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

Zuletzt aktivieren Sie die Benutzerinteraktionen erneut (denken Sie daran, dass diese Methode ausgelöst wird, nachdem die Tastatur didShow oder didHide ausgeführt wurde):

func enableUserInteraction()
    {
    UIApplication.shared.endIgnoringInteractionEvents()
    }

1

Swift 3 Code

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
}

1

Wenn Sie zwei oder mehr Textfelder in derselben VC haben und der Benutzer auf eines von ihnen tippt und dann auf das andere tippt, ohne die Funktion keyboardWillHide aufzurufen, wird die Ansicht noch einmal nach oben verschoben, was nicht erforderlich ist, da Sie haben die Tastatur, ein Leerzeichen mit der Höhe der Tastatur und dann die Ansicht. Verwenden Sie dazu den Code in der Antwort, die ich bearbeitet 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(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
    }
}

Um dies zu lösen, ersetzen Sie die beiden Funktionen "KeyboardWillShow / Hide" durch folgende:

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

Was ist, wenn mein Textfeld ganz oben in der Ansicht ist? Ich meine, wenn es ein Textfeld mit Ursprung Y = 0 gibt. dann steigt textField und ich kann es nicht sehen
Saifan Nadaf

1

@ Boris 'Lösung ist SEHR gut, aber die Ansicht kann manchmal beschädigt sein.

Verwenden Sie für die perfekte Ausrichtung den folgenden Code

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

Funktionen:

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

Und,

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

0

Dieses Video-Tutorial ist das Beste. 7 Minuten lang und es wird einfach so viel Sinn machen. Eine so einfache Lösung, wenn Sie mehrere Textfelder haben und möchten, dass die Bildlaufansicht die Anzahl der Pixel um "x" verschiebt, wenn auf dieses bestimmte Textfeld getippt wird.

https://youtu.be/VuiPGJOEBH4

Nur diese Schritte:

- Platzieren Sie alle Textfelder in einer Bildlaufansicht, die auf die Ränder der Ansicht beschränkt ist.

-Verbinden Sie alle Textfelder und die Bildlaufansicht als Delegierte an den Ansichtscontroller.

- Verbinden Sie alle Textfelder und die Bildlaufansicht mit einem IBOutlet.

class ViewController: UIViewController, UITextFieldDelegate {

- Fügen Sie Ihrer Klasse das UITextFieldDelegate-Protokoll hinzu

@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!    
@IBOutlet weak var scrollView: UIScrollView!

- Fügen Sie Ihrer schnellen Datei UITextFieldDelegate-Methoden hinzu:

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

Die erste Methode aktiviert nur die Eingabetaste auf der Tastatur, um die Tastatur zu schließen. Das zweite ist, wenn Sie auf ein bestimmtes Textfeld tippen und dann den y-Versatz festlegen, um wie weit Ihre Bildlaufansicht rollt (meiner basiert auf der y-Position auf meinen Ansichts-Controllern 25, 57, 112, 142). Der letzte sagt, wenn Sie von der Tastatur weg tippen, kehrt die Bildlaufansicht zum ursprünglichen Speicherort zurück.

Auf diese Weise habe ich mein Ansichtspixel perfekt gemacht!


0

Diese Funktion wurde in Ios integriert, wir müssen sie jedoch extern ausführen.
Fügen Sie den folgenden Code ein
* Verschieben der Ansicht, wenn sich textField unter der Tastatur befindet,
* Verschieben der Ansicht nicht, wenn sich textField über der Tastatur befindet
* Verschieben der Ansicht basierend auf der Höhe der Tastatur bei Bedarf.
Dies funktioniert und wird in allen Fällen getestet.

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

| :: | Manchmal ist die Ansicht nicht verfügbar. In diesem Fall verwenden Sie die Höhe +/- 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
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
}

es muss stabiler sein


0
 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

Verwenden Sie den folgenden Code für die Ansicht Nach oben auf 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

Ich habe einen Cocoapod gemacht, um die Sache zu vereinfachen:

https://github.com/xtrinch/KeyboardLayoutHelper

Wie man es benutzt:

Nehmen Sie eine untere Einschränkung für das automatische Layout vor, geben Sie ihr im Modul KeyboardLayoutHelper eine Klasse von KeyboardLayoutConstraint, und der Pod erledigt die erforderliche Arbeit, um sie zu vergrößern, um das Erscheinen und Verschwinden der Tastatur zu berücksichtigen. Im Beispielprojekt finden Sie Beispiele für die Verwendung (ich habe zwei erstellt: textFields in einer scrollView und vertikal zentrierte textFields mit zwei grundlegenden Ansichten - login & register).

Die unterste Layoutbeschränkung kann die Containeransicht, das Textfeld selbst oder alles sein, was Sie nennen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.