Frage Wie kann ich ein UITextField nach oben bewegen, wenn die Tastatur vorhanden ist?


Mit dem iOS SDK:

Ich habe ein UIView mit UITextFields, die eine Tastatur aufrufen. Ich brauche es, um:

  1. Erlaube das Scrollen des Inhalts des UIScrollView um die anderen Textfelder zu sehen, sobald die Tastatur hochgefahren ist

  2. Automatisch "springen" (durch Scrollen nach oben) oder kürzen

Ich weiß, dass ich eine brauche UIScrollView. Ich habe versucht, meine Klasse zu ändern UIView zu einem UIScrollView aber ich kann immer noch nicht die Textfelder nach oben oder unten scrollen.

Brauche ich beide a UIView und ein UIScrollView? Geht man in den anderen?

Was muss implementiert werden, um automatisch zum aktiven Textfeld zu scrollen?

Idealerweise sollte der Aufbau der Komponenten im Interface Builder so weit wie möglich erfolgen. Ich möchte nur Code schreiben für was es braucht.

Beachten Sie das UIView (oder UIScrollView) mit denen ich arbeite, wird von einer Tabbar (UITabBar), die wie normal funktionieren muss.


Bearbeiten: Ich füge die Bildlaufleiste nur für die Tastatur hinzu. Obwohl es nicht benötigt wird, habe ich das Gefühl, dass es eine bessere Schnittstelle bietet, weil der Benutzer beispielsweise Textfelder scrollen und ändern kann.

Ich habe es funktioniert, wo ich die Rahmengröße der ändern UIScrollView wenn die Tastatur auf und ab geht. Ich benutze einfach:

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
                     scrollView.frame.origin.y, 
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
       scrollView.frame.origin.y, 
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}

Dabei werden die unteren Textfelder im sichtbaren Bereich nicht automatisch nach oben verschoben oder zentriert, was ich wirklich gerne hätte.


1556


Ursprung


Antworten:


  1. Du brauchst nur ein ScrollView wenn der Inhalt, den Sie jetzt haben, nicht in den iPhone-Bildschirm passt. (Wenn Sie das hinzufügen ScrollView als Superview der Komponenten. nur um das zu machen TextField Scrollen Sie nach oben, wenn die Tastatur auftaucht, dann wird es nicht benötigt.)

  2. Zum Zeigen der textfields ohne durch die Tastatur versteckt zu sein, ist der Standard Weg, die Ansicht mit Textfeldern nach oben oder unten zu bewegen, wenn die Tastatur angezeigt wird.

Hier ist ein Beispielcode:

#define kOFFSET_FOR_KEYBOARD 80.0

-(void)keyboardWillShow {
    // Animate the current view out of the way
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)keyboardWillHide {
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:mailTf])
    {
        //move the main view, so that the keyboard does not hide it.
        if  (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
    }
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view

    CGRect rect = self.view.frame;
    if (movedUp)
    {
        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.
        rect.origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
    }
    else
    {
        // revert back to the normal state.
        rect.origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
    }
    self.view.frame = rect;

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

970



Ich hatte auch eine Menge Probleme mit einem UIScrollView Komponieren von mehreren UITextFieldsvon denen eines oder mehrere von ihnen während der Bearbeitung durch die Tastatur verdeckt werden würden.

Hier sind einige Dinge zu beachten, wenn Sie UIScrollView scrollt nicht richtig.

1) Stellen Sie sicher, dass Ihre contentSize größer ist als die UIScrollView Rahmengröße. Der Weg zu verstehen UIScrollViews Ist das das UIScrollView ist wie ein Sichtfenster auf den in der contentSize definierten Inhalt. Also, wenn für die UIScrollview Um an einer beliebigen Stelle zu scrollen, muss die contentSize größer als die sein UIScrollView. Sonst ist kein Scrollen erforderlich, da alles, was in der contentSize definiert ist, bereits sichtbar ist. BTW, Standard contentSize = CGSizeZero.

2) Nun, da du verstehst, dass das UIScrollView ist wirklich ein Fenster in Ihren "Inhalt", der Weg, um sicherzustellen, dass die Tastatur nicht Ihre verdunkelt UIScrollView's "Fenster" zu sehen wäre, die Größe zu ändern UIScrollView so dass, wenn die Tastatur vorhanden ist, Sie haben UIScrollView Fenstergröße nur zum Original UIScrollView frame.size.height abzüglich der Höhe der Tastatur. Dadurch wird sichergestellt, dass Ihr Fenster nur diesen kleinen sichtbaren Bereich enthält.

3) Hier ist der Haken: Als ich das zum ersten Mal durchführte, dachte ich mir, ich müsste das bekommen CGRect des bearbeiteten Textfelds und Aufruf UIScrollView's scrollRecToVisible-Methode. Ich habe das implementiert UITextFieldDelegate Methode textFieldDidBeginEditing mit dem Ruf an die scrollRecToVisible Methode. Dies funktionierte tatsächlich mit einem seltsamen Nebeneffekt, den das Scrollen hätte schnappen das UITextField in Position bringen. Für die längste Zeit konnte ich nicht herausfinden, was es war. Dann habe ich das auskommentiert textFieldDidBeginEditing Delegiertenmethode und alles funktioniert !! (???). Wie sich herausstellte, glaube ich, dass UIScrollView Implizit bringt das aktuell bearbeitete UITextField in das sichtbare Fenster implizit. Meine Umsetzung der UITextFieldDelegate Methode und anschließender Aufruf an die scrollRecToVisible war überflüssig und war die Ursache für den seltsamen Nebeneffekt.

Also hier sind die Schritte, um richtig zu scrollen UITextField in einem UIScrollView an Ort und Stelle, wenn die Tastatur erscheint.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    CGSize scrollContentSize = CGSizeMake(320, 345);
    self.scrollView.contentSize = scrollContentSize;
}

- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. Registrieren Sie sich für die Tastaturbenachrichtigungen unter viewDidLoad
  2. Melden Sie sich für die Tastaturbelegung bei viewDidUnload
  3. Stellen Sie sicher, dass die contentSize ist festgelegt und größer als dein UIScrollView beim viewDidLoad
  4. Schrumpfen das UIScrollView wenn die Tastatur vorhanden ist
  5. Zurückkehren das UIScrollView wenn die Tastatur weggeht.
  6. Verwenden Sie einen ivar, um zu erkennen, ob die Tastatur bereits auf dem Bildschirm angezeigt wird, da die Tastaturbenachrichtigungen jedes Mal gesendet werden a UITextField ist tabbed, auch wenn die Tastatur bereits vorhanden ist, um zu vermeiden Schrumpfung das UIScrollView wenn es schon ist geschrumpft

Eine Sache zu beachten ist, dass die UIKeyboardWillShowNotification wird ausgelöst, auch wenn die Tastatur bereits auf dem Bildschirm angezeigt wird, wenn Sie auf einem anderen Tab klicken UITextField. Ich habe mich darum gekümmert, indem ich einen Ivar benutzt habe, um zu vermeiden, dass die Größe verändert wird UIScrollView wenn die Tastatur bereits auf dem Bildschirm ist. Ändern der Größe versehentlich UIScrollView wenn die Tastatur schon da wäre würde es katastrophal sein!

Hoffe, dass dieser Code einigen von euch Kopfschmerzen erspart.


437



Es ist eigentlich am besten, nur Apples Implementierung zu verwenden, wie in der Dokumente. Der von ihnen bereitgestellte Code ist jedoch fehlerhaft. Ersetzen Sie den Teil in keyboardWasShown: nur unter den Kommentaren zu den folgenden:

NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint origin =  activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
    CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}

Die Probleme mit Apples Code sind folgende: (1) Sie berechnen immer, ob der Punkt innerhalb des Rahmens der Ansicht liegt, aber es ist a ScrollView, so dass es möglicherweise bereits gescrollt wurde und Sie diesen Offset berücksichtigen müssen:

origin.y -= scrollView.contentOffset.y

(2) Sie verschieben das contentOffset um die Höhe der Tastatur, aber wir wollen das Gegenteil (wir wollen das verschieben contentOffset durch die Höhe, die auf dem Bildschirm sichtbar ist, nicht was nicht ist):

activeField.frame.origin.y-(aRect.size.height)

260



Im textFieldDidBeginEditting und in textFieldDidEndEditing Rufen Sie die Funktion auf [self animateTextField:textField up:YES] so:

-(void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    [self animateTextField:textField up:YES]; 
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField:textField up:NO];
}

-(void)animateTextField:(UITextField*)textField up:(BOOL)up
{
    const int movementDistance = -130; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

    int movement = (up ? movementDistance : -movementDistance); 

    [UIView beginAnimations: @"animateTextField" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}

Ich hoffe dieser Code wird dir helfen.

In Swift 2

func animateTextField(textField: UITextField, up: Bool) 
{
     let movementDistance:CGFloat = -130
     let movementDuration: Double = 0.3

     var movement:CGFloat = 0
     if up 
     {
         movement = movementDistance
     }
     else 
     {
         movement = -movementDistance
     }
     UIView.beginAnimations("animateTextField", context: nil)
     UIView.setAnimationBeginsFromCurrentState(true)
     UIView.setAnimationDuration(movementDuration)
     self.view.frame = CGRectOffset(self.view.frame, 0, movement)
     UIView.commitAnimations()
}


func textFieldDidBeginEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:true)
}

func textFieldDidEndEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:false)
}

SWIFT 3

 func animateTextField(textField: UITextField, up: Bool)
    {
        let movementDistance:CGFloat = -130
        let movementDuration: Double = 0.3

        var movement:CGFloat = 0
        if up
        {
            movement = movementDistance
        }
        else
        {
            movement = -movementDistance
        }
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(movementDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }


    func textFieldDidBeginEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:true)
    }

    func textFieldDidEndEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:false)
    }

238



Nur mit TextFields:

1a) Verwenden Interface Builder: Wählen Sie Alle Textfelder => Bearbeiten => Einbetten in => ScrollView

1b) Manuelles Einbetten von TextFields in UIScrollView mit der Bezeichnung scrollView

2) Set UITextFieldDelegate

3) Stellen Sie jedes ein textField.delegate = self; (oder knüpfen Verbindungen in Interface Builder)

4) Kopieren Einfügen:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [scrollView setContentOffset:CGPointZero animated:YES];
}

133



Zum Universelle Lösung, Hier war mein Ansatz für die Umsetzung IQKeyboardManager.

enter image description here

Schritt 1:- Ich habe globale Benachrichtigungen von hinzugefügt UITextField, UITextView, und UIKeyboard in einer Singleton-Klasse. I nenne es IQKeyboardManager.

Schritt 2:- Wenn gefunden UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification oder UITextViewTextDidBeginEditingNotification Benachrichtigungen, versuche ich zu bekommen topMostViewController Instanz von der UIWindow.rootViewController Hierarchie. Um richtig aufzudecken UITextField/UITextView darauf, topMostViewController.viewDer Rahmen muss angepasst werden.

Schritt 3:- Ich berechnete die erwartete Bewegungsentfernung von topMostViewController.view in Bezug auf zuerst geantwortet UITextField/UITextView.

Schritt 4:- bin umgezogen topMostViewController.view.frame up / down nach der erwarteten Bewegungsentfernung.

Schritt 5: - Wenn gefunden UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification oder UITextViewTextDidEndEditingNotification Benachrichtigung, versuche ich erneut zu bekommen topMostViewController Instanz von der UIWindow.rootViewController Hierarchie.

Schritt 6: - Ich berechnete gestörte Entfernung von topMostViewController.view das muss in seiner ursprünglichen Position wiederhergestellt werden.

Schritt 7: - Ich habe restauriert topMostViewController.view.frame entsprechend der gestörten Distanz.

Schritt8: - Ich habe Singleton instanziiert IQKeyboardManager Klasseninstanz auf App laden, also alle UITextField/UITextView in der App wird automatisch entsprechend der erwarteten Bewegungsdistanz anpassen.

Das ist alles IQKeyboardManager mach für dich mit KEINE CODE-LINIE Ja wirklich!! Sie müssen nur die zugehörige Quelldatei in das Projekt ziehen und dort ablegen. IQKeyboardManager auch Unterstützung Geräteausrichtung, Automatische UIToolbar-Verwaltung, KeybkeyboardDistanceFromTextField und viel mehr als du denkst.


106



Ich habe ein universelles Drop-In zusammengestellt UIScrollView, UITableView und selbst UICollectionView Unterklasse, die dafür sorgt, dass alle Textfelder innerhalb der Tastatur verschoben werden.

Wenn die Tastatur angezeigt wird, findet die Unterklasse die zu bearbeitende Unteransicht und passt den Rahmen und den Inhaltsoffset an, um sicherzustellen, dass die Ansicht sichtbar ist und eine Animation dem Tastatur-Popup entspricht. Wenn die Tastatur verschwindet, stellt sie ihre vorherige Größe wieder her.

Es sollte grundsätzlich mit jedem Setup funktionieren, entweder a UITableView-basierte Schnittstelle oder eine aus manuell platzierten Ansichten.

Hier ist es: Lösung für das Verschieben von Textfeldern aus dem Weg der Tastatur


99



Zum Schnell Programmierer:

Dies wird alles für Sie tun, setzen Sie diese einfach in Ihre View - Controller - Klasse und implementieren Sie die UITextFieldDelegate zu Ihrem View-Controller und legen Sie den delegierten TextField auf self 

textField.delegate = self // Setting delegate of your UITextField to self

Implementieren Sie die Delegat-Callback-Methoden:

func textFieldDidBeginEditing(textField: UITextField) {
    animateViewMoving(true, moveValue: 100)
}

func textFieldDidEndEditing(textField: UITextField) {
    animateViewMoving(false, moveValue: 100)
}

// Lifting the view up
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()
}

84