1792 Stimmen

Wie kann ich ein UITextField nach oben bewegen, wenn die Tastatur vorhanden ist - beim Start der Bearbeitung?

Mit dem iOS SDK:

Ich habe eine UIView con UITextField s, die eine Tastatur aufrufen. Ich brauche es in der Lage zu sein:

  1. Erlaubt das Scrollen des Inhalts der UIScrollView um die anderen Textfelder zu sehen, sobald die Tastatur eingeblendet wird

  2. Automatisches "Springen" (durch Scrollen nach oben) oder Verkürzen

Ich weiß, dass ich eine UIScrollView . Ich habe versucht, die Klasse meiner UIView を、その UIScrollView aber ich kann die Textfelder immer noch nicht nach oben oder unten verschieben.

Benötige ich sowohl eine UIView und eine UIScrollView ? Passt das eine in das andere?

Was muss implementiert werden, um automatisch zum aktiven Textfeld zu blättern?

Idealerweise wird die Einrichtung der Komponenten so weit wie möglich im Interface Builder vorgenommen. Ich möchte nur Code für das schreiben, was ich brauche.

Anmerkung: Die UIView (o UIScrollView ), mit dem ich arbeite, wird über eine Registerkartenleiste angezeigt ( UITabBar ), die wie gewohnt funktionieren muss.


Ich füge die Bildlaufleiste nur dann hinzu, wenn die Tastatur angezeigt wird. Auch wenn es nicht benötigt wird, habe ich das Gefühl, dass es eine bessere Schnittstelle bietet, weil der Benutzer dann scrollen und Textfelder ändern kann, zum Beispiel.

Ich habe es so hinbekommen, dass ich die Rahmengröße der 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
}

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

0 Stimmen

Sie können das Textfeld animieren, so dass sich das Textfeld bewegt, wenn die Tastatur hochkommt

7 Stimmen

Sehen Sie sich das an. Kein Ärger für Sie. TPKeyboardVermeiden

24 Stimmen

Das ist von Apple dokumentiert, und ich denke, das ist der beste Weg: developer.apple.com/library/ios/#documentation/StringsTextFonts/

1073voto

RPDP Punkte 1713
  1. Sie benötigen nur eine ScrollView wenn die Inhalte, die Sie jetzt haben, nicht auf das iPhone-Display passen. (Wenn Sie die ScrollView als Übersicht über die Komponenten, um die TextField nach oben scrollen, wenn die Tastatur erscheint, dann ist es nicht nötig).

  2. Die Standardmethode zur Verhinderung der TextField s nicht durch die Tastatur verdeckt werden, ist die Ansicht nach oben/unten zu verschieben, 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];
}

3 Stimmen

Was bedeutet _textField? Ich habe es in meinen Code kopiert, es sagt _textField ist nicht deklariert.

0 Stimmen

Es ist das Feld, das Sie verwenden, um zu sagen, "wenn der Benutzer hier bearbeitet, sollte die Ansicht nach oben gleiten" oder so etwas... Allerdings können Sie das entfernen, wenn Sie mehr Felder.

0 Stimmen

Ist es nicht ein Schlag, -(void)setViewMovedUp:(BOOL)movedUp in keyBoardWillSHow und KeyBoardWillHide Ereignissen aufzurufen!!

450voto

Shiun Punkte 2677

Ich hatte auch eine Menge Probleme mit einer UIScrollView Zusammenstellung von mehreren UITextFields Die meisten davon werden bei der Bearbeitung von der Tastatur verdeckt.

Hier sind einige Dinge zu beachten, wenn Ihr UIScrollView wird nicht richtig gescrollt.

1) Stellen Sie sicher, dass Ihre contentSize größer ist als die UIScrollView Rahmengröße. Der Weg zum Verständnis UIScrollViews ist, dass die UIScrollView ist wie ein Sichtfenster auf den in contentSize definierten Inhalt. Wenn Sie also für die UIScrollview um irgendwo zu scrollen, muss die contentSize größer sein als die UIScrollView . Andernfalls ist kein Bildlauf erforderlich, da alles, was in contentSize definiert ist, bereits sichtbar ist. Übrigens, Standard contentSize = CGSizeZero .

2) Da Sie nun wissen, dass die UIScrollView ist in Wirklichkeit ein Fenster zu Ihrem "Inhalt", ein Weg, um sicherzustellen, dass die Tastatur nicht Ihren Blick verdeckt. UIScrollView's Ansichtsfenster" wäre, die Größe des UIScrollView so dass Sie, wenn die Tastatur vorhanden ist, die UIScrollView Fenster nur auf die Originalgröße verkleinert UIScrollView frame.size.height abzüglich der Höhe der Tastatur. Dadurch wird sichergestellt, dass Ihr Fenster nur diesen kleinen sichtbaren Bereich einnimmt.

3) Hier ist der Haken: Als ich dies zum ersten Mal implementierte, dachte ich, ich müsste die CGRect des bearbeiteten Textfeldes und rufen UIScrollView's scrollRecToVisible-Methode. Ich habe die Methode UITextFieldDelegate Methode textFieldDidBeginEditing mit dem Aufruf der scrollRecToVisible Methode. Dies funktionierte tatsächlich mit einem seltsamen Nebeneffekt, dass der Bildlauf schnappen le site UITextField in Position. Die längste Zeit konnte ich nicht herausfinden, was es war. Dann kommentierte ich die textFieldDidBeginEditing Delegate-Methode und alles funktioniert!!!(???). Wie sich herausstellte, glaube ich, dass die UIScrollView bringt eigentlich implizit die aktuell bearbeitete UITextField implizit in das sichtbare Fenster. Meine Implementierung des UITextFieldDelegate Methode und dem anschließenden Aufruf der scrollRecToVisible überflüssig war und die Ursache für die seltsame Nebenwirkung war.

Hier sind also die Schritte, um Ihre UITextField in einem UIScrollView ein, 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. Heben Sie die Registrierung für die Tastatureinstellungen unter viewDidUnload
  3. Stellen Sie sicher, dass die contentSize gesetzt und größer als Ihr UIScrollView unter viewDidLoad
  4. Schrumpfen le site UIScrollView wenn die Tastatur vorhanden ist
  5. Zurückkehren le site UIScrollView wenn die Tastatur verschwindet.
  6. Verwenden Sie einen Ivar, um zu erkennen, ob die Tastatur bereits auf dem Bildschirm angezeigt wird, da die Tastaturbenachrichtigungen jedes Mal gesendet werden, wenn eine UITextField wird auch dann mit einem Tabulator versehen, wenn die Tastatur bereits vorhanden ist, um zu vermeiden, dass Schrumpfung le site UIScrollView wenn es bereits geschrumpft

Es ist zu beachten, dass die UIKeyboardWillShowNotification wird auch dann ausgelöst, wenn die Tastatur bereits auf dem Bildschirm ist, wenn Sie mit der Tabulatortaste auf eine andere UITextField . Ich habe dafür gesorgt, indem ich ein Ivar verwendet habe, um eine Größenänderung der UIScrollView wenn die Tastatur bereits auf dem Bildschirm angezeigt wird. Versehentliches Ändern der Größe der UIScrollView wenn die Tastatur schon da ist, wäre das katastrophal!

Ich hoffe, dieser Code erspart einigen von Ihnen eine Menge Kopfschmerzen.

3 Stimmen

Großartig, aber zwei Probleme: 1. UIKeyboardBoundsUserInfoKey ist veraltet. 2. keyboardSize ist in "Bildschirmkoordinaten", so dass Ihre viewFrame Berechnungen fehlschlagen, wenn der Rahmen gedreht oder skaliert wird.

22 Stimmen

@Martin Wickman - Verwendung CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; anstelle des veralteten UIKeyboardBoundsUserInfoKey

0 Stimmen

Tolle Antwort, aber was soll ich tun, wenn ich die Größe der Ansicht nur ändern möchte, wenn einige der Steuerelemente aktiv sind. Nehmen wir an, ich habe ein Textfeld am oberen Rand der Ansicht und eines am unteren Rand, und ich möchte die Größe der Ansicht nur für das Textfeld am unteren Rand ändern.

275voto

DK_ Punkte 2640

Am besten ist es, die Implementierung von Apple zu verwenden, wie sie in der docs . Der von ihnen bereitgestellte Code ist jedoch fehlerhaft. Ersetzen Sie den Teil, der in keyboardWasShown: direkt unter den Kommentaren zum 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 dem Code von Apple sind folgende: (1) Es wird immer berechnet, ob der Punkt innerhalb des Rahmens der Ansicht liegt, aber es ist eine ScrollView Es kann also sein, dass sie bereits gescrollt hat und Sie diesen Versatz berücksichtigen müssen:

origin.y -= scrollView.contentOffset.y

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

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

0 Stimmen

Wäre es nicht eine bessere Lösung, die Größe der Bildlaufleiste so anzupassen, dass ihre Höhe mit der Oberkante der Tastatur übereinstimmt?

0 Stimmen

Bei mir funktioniert das nicht, meine Ansicht scrollt nach unten und nicht nach oben, sie versteckt sich komplett hinter meiner Tastatur.

0 Stimmen

@8vius Vergewissern Sie sich, dass Sie den Ursprung der Ansicht nicht invertiert haben? Je nachdem, was als Ursprung (0,0) definiert ist, ändert sich die Logik.

253voto

sumanthkodi Punkte 196

Unter textFieldDidBeginEditting und in textFieldDidEndEditing die Funktion aufrufen [self animateTextField:textField up:YES] etwa 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 Ihnen helfen.

Mauersegler 5

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.animate(withDuration: movementDuration, delay: 0, options: [.beginFromCurrentState], animations: {
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
    }, completion: nil)
}

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

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

1 Stimmen

Warum nicht [UIView animateWithDuration: animations:^{ }]; ?

2 Stimmen

Dies funktioniert gut, obwohl const int movementDistance = -130; // nach Bedarf angepasst werden muss, um flexibler zu sein

0 Stimmen

@UserDev Das funktioniert sowohl unter iOS 7 als auch unter iOS 8 einwandfrei. Die Navigationsleiste ist nicht Teil der Ansicht, die im Code animiert wird.

136voto

DAS Punkte 1941

Nur mit TextFields:

1a) Verwendung Interface Builder : Alle Textfelder auswählen => Bearbeiten => Einbetten in => ScrollView

1b) Manuelles Einbetten von TextFields in UIScrollView namens scrollView

2) Festlegen UITextFieldDelegate

3) Setzen Sie jeweils textField.delegate = self; (oder stellen Sie 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];
}

8 Stimmen

Es wird aber auch die Ansicht erweitert, wenn textField ist bereits sichtbar.

1 Stimmen

Notwendigkeit der Änderung CGPointMake(0, textField.frame.origin.y); a CGPointMake(0, textField.frame.origin.y + scrollView.contentInset.top);

0 Stimmen

@Egor Auch nach Ihrem Kommentar funktioniert es nicht. Wie "TheTiger" erwähnt hat, wird die Ansicht nach oben verschoben, auch wenn das Textfeld sichtbar ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X