ios - Come posso far muovere UITextField quando è presente la tastiera?




objective-c uikeyboard (25)

Non richiede una vista di scorrimento per poter spostare la cornice della vista. È possibile modificare la cornice di una viewcontroller'svista in modo che l'intera vista si sollevi quanto basta per posizionare il campo di testo firstresponder sopra la tastiera. Quando mi sono imbattuto in questo problema, ho creato una sottoclasse di UIViewControllerquesto. Osserva che la tastiera apparirà come notifica e troverà la prima sottoview del risponditore e (se necessario) animerà la vista principale verso l'alto quel tanto che basta affinché il primo risponditore si trovi sopra la tastiera. Quando la tastiera si nasconde, anima la vista indietro dove si trovava.

Per utilizzare questa sottoclasse, crea il tuo controller di visualizzazione personalizzato come sottoclasse di GMKeyboardVC e eredita questa funzione (assicurati solo di implementare viewWillAppeare viewWillDisappeardevono chiamare super). La lezione è su github .

Con l'SDK iOS:

Ho un UIView con UITextField che fa apparire una tastiera. Ho bisogno che sia in grado di:

  1. Consentire lo scorrimento dei contenuti di UIScrollView per vedere gli altri campi di testo quando viene visualizzata la tastiera

  2. Automaticamente "salta" (scorrendo verso l'alto) o accorciando

So che ho bisogno di un UIScrollView . Ho provato a cambiare la classe del mio UIView su un UIScrollView ma non riesco ancora a scorrere le caselle di testo verso l'alto o verso il basso.

Ho bisogno sia di un UIView che di un UIScrollView ? Si va dentro l'altro?

Cosa deve essere implementato per scorrere automaticamente al campo di testo attivo?

Idealmente la maggior parte della configurazione dei componenti sarà eseguita in Interface Builder. Mi piacerebbe solo scrivere il codice per quello che serve.

Nota: l' UIView (o UIScrollView ) con cui sto lavorando viene visualizzato da una barra delle linguette ( UITabBar ), che deve funzionare normalmente.

Modifica: sto aggiungendo la barra di scorrimento solo per quando viene visualizzata la tastiera. Anche se non è necessario, mi sembra che fornisca un'interfaccia migliore perché, ad esempio, l'utente può scorrere e modificare le caselle di testo.

Ho funzionato dove cambio la dimensione del frame di UIScrollView quando la tastiera va su e giù. Sto semplicemente usando:

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

Tuttavia, questo non si sposta automaticamente verso l'alto o centra i campi di testo inferiori nell'area visibile, che è quello che mi piacerebbe davvero.


Quando UITextFieldè in uno UITableViewCellscorrimento dovrebbe essere impostato automaticamente.

Se non lo è probabilmente è a causa di codice errato / setup di tableview.

Ad esempio quando ho ricaricato il mio lungo tavolo con uno UITextFieldin basso come segue,

-(void) viewWillAppear:(BOOL)animated
{
   [self.tableview reloadData];
}

poi il mio campo di testo in fondo era oscurato dalla tastiera che appariva quando ho cliccato all'interno del campo di testo.

Per risolvere questo ho dovuto fare questo -

-(void) viewWillAppear:(BOOL)animated
{
    //add the following line to fix issue
    [super viewWillAppear:animated];
    [self.tableview reloadData];
}

Per la soluzione universale , ecco il mio approccio per l'implementazione di IQKeyboardManager .

Fase 1: - Ho aggiunto notifiche globali di UITextField , UITextView e UIKeyboard in una classe singleton. Lo chiamo IQKeyboardManager .

UIKeyboardWillShowNotification 2: - Se trovato UIKeyboardWillShowNotification , UITextFieldTextDidBeginEditingNotification o UITextViewTextDidBeginEditingNotification notifiche, cerco di ottenere topMostViewController istanza topMostViewController dalla gerarchia UIWindow.rootViewController . Per scoprire correttamente UITextField / UITextView su di esso, è necessario modificare la cornice di topMostViewController.view .

Fase 3: - Ho calcolato la distanza di spostamento prevista di topMostViewController.view rispetto al primo UITextField / UITextView risposto.

Step4: - Ho spostato la vista topMostViewController.view.frame su / giù in base alla distanza di spostamento prevista.

Fase 5: - Se viene trovata la UIKeyboardWillHideNotification , UITextFieldTextDidEndEditingNotification o UITextViewTextDidEndEditingNotification , provo nuovamente a ottenere topMostViewController istanza topMostViewController dalla gerarchia UIWindow.rootViewController .

Step6: - Ho calcolato la distanza disturbata di topMostViewController.view che deve essere ripristinata nella sua posizione originale.

Fase 7: - Ho ripristinato topMostViewController.view.frame in base alla distanza disturbata.

Step8: - Ho istanziato l'istanza della classe IQKeyboardManager singleton sul caricamento dell'app, quindi ogni UITextField / UITextView nell'app si regolerà automaticamente in base alla distanza di spostamento prevista.

Questo è tutto IQKeyboardManager che IQKeyboardManager fa per te con NO LINE OF CODE davvero !! solo bisogno di trascinare e rilasciare il file sorgente relativo al progetto. IQKeyboardManager supporta anche l' orientamento del dispositivo , la gestione automatica di UIToolbar , KeybkeyboardDistanceFromTextField e molto più di quanto si pensi.


State cercando un buon tutorial per i principianti sull'argomento, ho trovato il miglior tutorial here .

Nel MIScrollView.hesempio, al fondo del tutorial assicurarsi di inserire uno spazio a

@property (nonatomic, retain) id backgroundTapDelegate;

come vedi.


prova questo breve trucco ...

 - (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 = textField.frame.origin.y / 2; // tweak as needed
        const float movementDuration = 0.3f; // tweak as needed

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

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

Codifica felice:) ....


Ci sono già molte risposte, ma ancora nessuna delle soluzioni di cui sopra aveva tutte le fantasiose funzionalità di posizionamento richieste per un'animazione "perfetta" priva di errori, retrocompatibile e priva di sfarfallio. (bug durante l'animazione di frame / bounds e contentOffset insieme, diversi orientamenti di interfaccia, tastiera split di iPad, ...)
Lasciatemi condividere la mia soluzione:
(presumendo che tu abbia configurato UIKeyboardWill(Show|Hide)Notification )

// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = [notification userInfo];

    CGRect keyboardFrameInWindow;
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];

    // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
    CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];

    CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
    UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);

    // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    _scrollView.contentInset = newContentInsets;
    _scrollView.scrollIndicatorInsets = newContentInsets;

    /*
     * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
     * that should be visible, e.g. a purchase button below an amount text field
     * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
     */
    if (_focusedControl) {
        CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
        controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view.

        CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y;
        CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;

        // this is the visible part of the scroll view that is not hidden by the keyboard
        CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;

        if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
            // scroll up until the control is in place
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);

            // make sure we don't set an impossible offset caused by the "nice visual offset"
            // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
            newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        } else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) {
            // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y = controlFrameInScrollView.origin.y;

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        }
    }

    [UIView commitAnimations];
}


// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = notification.userInfo;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    // undo all that keyboardWillShow-magic
    // the scroll view will adjust its contentOffset apropriately
    _scrollView.contentInset = UIEdgeInsetsZero;
    _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;

    [UIView commitAnimations];
}

Per riportare allo stato di visualizzazione originale, aggiungere:

-(void)textFieldDidEndEditing:(UITextField *)sender

{
    //move the main view, so that the keyboard does not hide it.
    if  (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

developer.apple.com/library/ios/#documentation/StringsTextFonts/… documento descrive una soluzione a questo problema. Guarda il codice sorgente sotto "Spostamento del contenuto che si trova sotto la tastiera". È piuttosto semplice.

EDIT: notato che c'è un piccolo problema nell'esempio. Probabilmente vorrai ascoltare per UIKeyboardWillHideNotificationinvece di UIKeyboardDidHideNotification. In caso contrario, la vista di scorrimento dietro alla tastiera verrà ritagliata per la durata dell'animazione di chiusura della tastiera.


Ci sono così tante soluzioni, ma ho passato alcune ore prima che inizi a funzionare. Quindi, metto questo codice qui (basta incollare sul progetto, non è necessario apportare alcuna modifica):

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
    UITextField* activeField;
    UIScrollView *scrollView;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

    //scrool view must be under main view - swap it
    UIView* natView = self.view;
    [self setView:scrollView];
    [self.view addSubview:natView];

    CGSize scrollViewContentSize = self.view.frame.size;
    [scrollView setContentSize:scrollViewContentSize];

    [self registerForKeyboardNotifications];
}

- (void)viewDidUnload {
    activeField = nil;
    scrollView = nil;
    [self unregisterForKeyboardNotifications];
    [super viewDidUnload];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

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

}

-(void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}

- (void)keyboardWillShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect frame = self.view.frame;
    frame.size.height -= kbSize.height;
    CGPoint fOrigin = activeField.frame.origin;
    fOrigin.y -= scrollView.contentOffset.y;
    fOrigin.y += activeField.frame.size.height;
    if (!CGRectContainsPoint(frame, fOrigin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y + activeField.frame.size.height - frame.size.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
     [scrollView setContentOffset:CGPointZero animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    activeField = nil;
}

-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

PS: Spero che il codice aiuti qualcuno a rendere rapidamente l'effetto desiderato. (Xcode 4.5)


@ user271753

Per tornare alla visualizzazione originale aggiungi:

-(BOOL)textFieldShouldReturn:(UITextField *)textField{
   [textField resignFirstResponder];
   [self setViewMovedUp:NO];
   return YES;
}

Una cosa da considerare è se si desidera utilizzare un UITextFieldda solo. Non ho mai incontrato app per iPhone ben progettate che usino UITextFieldsal di fuori UITableViewCells.

Sarà un lavoro extra, ma ti consiglio di implementare tutte le viste di immissione dati su una tabella. Aggiungi un UITextViewal tuo UITableViewCells.


Usa questa terza parte che non è necessario scrivere anche una sola riga

github.com/hackiftekhar/IQKeyboardManager

scarica il progetto e trascina IQKeyboardManager nel tuo progetto. Se trovi qualche problema per favore leggi il documento README.

Ragazzi davvero il suo mal di testa rimuovere per gestire la tastiera ..

Grazie e buona fortuna!


Nota : questa risposta presuppone che il campo di testo sia in una scrollView.

Preferisco occuparmi di questo usando scrollContentInset e scrollContentOffset invece di scherzare con i frame della mia vista.

Prima ascoltiamo le notifiche della tastiera

//call this from viewWillAppear
-(void)addKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}
//call this from viewWillDisappear
-(void)removeKeyboardNotifications{
    [[NSNotificationCenter default
    Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

Il passo successivo è mantenere una proprietà che rappresenti il ​​primo risponditore corrente (UITextfield / UITextVIew che al momento ha la tastiera).

Utilizziamo i metodi delegati per impostare questa proprietà. Se stai usando un altro componente, avrai bisogno di qualcosa di simile.

Si noti che per il campo di testo lo abbiamo impostato in didBeginEditing e per textView in shouldBeginEditing. Questo perché textViewDidBeginEditing viene chiamato dopo UIKeyboardWillShowNotification per qualche motivo.

-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{
    self.currentFirstResponder = textView;
    return YES;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField{
    self.currentFirstResponder = textField;
}

Finalmente, ecco la magia

- (void)keyboardWillShow:(NSNotification*)aNotification{
    NSDictionary* info = [aNotification userInfo];
    CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];


    /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/
    if(self.currentFirstResponder){

        //keyboard origin in currentFirstResponderFrame
        CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.origin fromView:nil];

        float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y);

        //only scroll the scrollview if keyboard overlays the first responder
        if(spaceBetweenFirstResponderAndKeyboard>0){
            //if i call setContentOffset:animate:YES it behaves differently, not sure why
            [UIView animateWithDuration:0.25 animations:^{
                [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)];
            }];
        }
    }

    //set bottom inset to the keyboard height so you can still scroll the whole content

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0);
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;

}

- (void)keyboardWillHide:(NSNotification*)aNotification{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}

In realtà è meglio usare l'implementazione di Apple, come previsto nei docs . Tuttavia, il codice che forniscono è difettoso. Sostituisci la parte trovata in keyboardWasShown: appena sotto i commenti al seguente:

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

I problemi con il codice Apple sono i seguenti: (1) Calcolano sempre se il punto si trova all'interno del frame della vista, ma è un ScrollView , quindi potrebbe già averlo fatto scorrere ed è necessario tenere conto di tale offset:

origin.y -= scrollView.contentOffset.y

(2) Spingono il contenutoOffset all'altezza della tastiera, ma vogliamo il contrario (vogliamo spostare il contentOffset base all'altezza visibile sullo schermo, non ciò che non lo è):

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

Come per i documenti , a partire da iOS 3.0, la UITableViewControllerclasse ridimensiona automaticamente e riposiziona la sua vista tabella quando è in corso la modifica dei campi di testo. Penso che non sia sufficiente inserire il campo di testo all'interno di un UITableViewCellcome alcuni hanno indicato.

Dai documenti :

Un controller di visualizzazione tabella supporta la modifica in linea delle righe di visualizzazione tabella; se, ad esempio, le righe hanno campi di testo incorporati in modalità di modifica, scorre la riga in corso di modifica sopra la tastiera virtuale che viene visualizzata.


Shiun ha dichiarato: "Come si è scoperto, credo che UIScrollView implichi implicitamente l'UITextField attualmente modificato nella finestra visibile implicitamente" Questo sembra essere vero per iOS 3.1.3, ma non 3.2, 4.0 o 4.1. Ho dovuto aggiungere un scrollRectToVisible esplicito per rendere visibile UITextField su iOS> = 3.2.


Trovata la soluzione più semplice

- (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 = 80; // tweak as needed
    const float movementDuration = 0.3f; // tweak as needed

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

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

Questa è la soluzione che usa Swift.

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size

        let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;

        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your app might not need or want this behavior.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}

Piccola correzione che funziona per molti campi UIText

#pragma mark UIKeyboard handling

#define kMin 150

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
   if (currTextField) {
      [currTextField release];
   }
   currTextField = [sender retain];
   //move the main view, so that the keyboard does not hide it.
   if (self.view.frame.origin.y + currTextField.frame.origin. y >= kMin) {
        [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 = kMin - currTextField.frame.origin.y ;
   }
   else
   {
      // revert back to the normal state.
      rect.origin.y = 0;
   }
   self.view.frame = rect;

   [UIView commitAnimations];
}


- (void)keyboardWillShow:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately

   if ([currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y >= kMin)
   {
      [self setViewMovedUp:YES];
   }
   else if (![currTextField isFirstResponder] && currTextField.frame.origin.y  + self.view.frame.origin.y < kMin)
   {
      [self setViewMovedUp:NO];
   }
}

- (void)keyboardWillHide:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
   if (self.view.frame.origin.y < 0 ) {
      [self setViewMovedUp:NO];
   }

}


- (void)viewWillAppear:(BOOL)animated
{
   // register for keyboard notifications
   [[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]; 
}

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

Per i programmatori Swift :

Questo farà tutto per te, basta metterli nella classe del tuo controller di visualizzazione e implementare UITextFieldDelegate sul tuo controller di visualizzazione e impostare il delegato del textField su self

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

Implementare i metodi di callback delegati:

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

Qui ho trovato la soluzione più semplice per gestire la tastiera.

Devi solo copiare e incollare sotto il codice di esempio e modificare il tuo campo di testo o qualsiasi vista che vuoi spostare.

Passo 1

Basta copiare e incollare sotto due metodi nel tuo controller

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void)deregisterFromKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

Passo 2

registra e cancella le Notifiche della tastiera in viewWillAppear e viewWillDiseparano i metodi rispettivamente.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self registerForKeyboardNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [self deregisterFromKeyboardNotifications];
    [super viewWillDisappear:animated];
}

Step-3

Ecco la parte dell'anima, basta sostituire il campo di testo e modificare l'altezza di quanto vuoi spostare al rialzo.

- (void)keyboardWasShown:(NSNotification *)notification
{
    NSDictionary* info = [notification userInfo];
    CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //you need replace your textfield instance here
    CGPoint textFieldOrigin = self.tokenForPlaceField.frame.origin;
    CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;

    CGRect visibleRect = self.view.frame;
    visibleRect.size.height -= currentKeyboardSize.height;

    if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
    {
        //you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below

        CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height  + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
        [self.scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification *)notification
{
    [self.scrollView setContentOffset:CGPointZero animated:YES];
}

Riferimento : bene, per favore apprezzare questo ragazzo , che ha condiviso questo bel codice snip, soluzione pulita.

Spero che questo possa essere utile a qualcuno là fuori.


Ecco la soluzione di hacking che mi è venuta in mente per un layout specifico. Questa soluzione è simile alla soluzione di Matt Gallagher in quanto consente di scorrere una sezione in vista. Sono ancora nuovo nello sviluppo di iPhone e non ho familiarità con il funzionamento dei layout. Quindi, questo hack.

La mia implementazione era necessaria per supportare lo scorrimento quando si fa clic in un campo e si scorre anche quando l'utente seleziona la prossima volta sulla tastiera.

Ho avuto un UIView con un'altezza di 775. I controlli sono distribuiti fondamentalmente in gruppi di 3 su un grande spazio. Ho finito con il seguente layout IB.

UIView -> UIScrollView -> [UI Components]

Ecco che arriva l'hack

Ho impostato l'altezza di UIScrollView su 500 unità più grandi rispetto al layout effettivo (1250). Ho quindi creato un array con le posizioni assolute di cui ho bisogno per scorrere e una semplice funzione per ottenerle in base al numero del tag IB.

static NSInteger stepRange[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410
};

NSInteger getScrollPos(NSInteger i) {
    if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) {
        return 0 ;
    return stepRange[i] ;
}

Ora tutto ciò che devi fare è usare le seguenti due linee di codice in textFieldDidBeginEditing e textFieldShouldReturn (quest'ultimo se stai creando un prossimo campo di navigazione)

CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;

Un esempio.

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
    [self.scrollView setContentOffset:point animated:YES] ;
}


- (BOOL)textFieldShouldReturn:(UITextField *)textField {

    NSInteger nextTag = textField.tag + 1;
    UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];

    if (nextResponder) {
        [nextResponder becomeFirstResponder];
        CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ;
        [self.scrollView setContentOffset:point animated:YES] ;
    }
    else{
        [textField resignFirstResponder];
    }

    return YES ;
}

Questo metodo non "scorre indietro" come fanno altri metodi. Questo non era un requisito. Ancora una volta questo era per un UIView abbastanza 'alto', e non avevo giorni per imparare i motori di layout interni.


In textFieldDidBeginEditting e in textFieldDidEndEditing chiama la funzione [self animateTextField:textField up:YES] modo:

-(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];
}

Spero che questo codice ti possa aiutare.

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

Swift 4 .

È possibile scorrere facilmente su e giù UITextFieldO UIViewCon UIKeyBoardConAnimation

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!
    @IBOutlet var chatView: UIView!

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

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

    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.origin.y - curFrame.origin.y
        print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.chatView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
        },completion: nil)
    }

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

}

Apparentemente, (cputype (12) cpusubtype (11)) è un'altra nomenclatura per armv7s.

Puoi riferirti di più qui: http://www.galloway.me.uk/2012/09/hacking-up-an-armv7s-library/

Il blog sopra descritto descrive anche un metodo per rendere compatibili alcune librerie ARMV7. La descrizione di cui sopra si trova vicino alla fine dell'articolo in cui spiega l'output del comando file .

Per citare una parte di esso:

All'interno di questa intestazione (chiamata intestazione Mach-O) è presente un campo per il tipo di CPU e il sottotipo CPU. ARM è un tipo di CPU 12, armv7 è un sottotipo di CPU 9 e armv7s è un sottotipo di CPU 11.







ios objective-c uitextfield uikeyboard