2012-01-02 11 views
36

So che questa domanda è stata fatta più e più volte, ma nulla sembra funzionare per me. La maggior parte delle soluzioni disponibili sono piuttosto obsolete, e il resto sono incredibilmente enormi blocchi di codice che sono dieci volte più grandi della vera codifica dei progetti. Ho alcuni UITextField allineati verticalmente, ma quando la tastiera si avvia per modificarne uno, copre il campo di testo. Mi stavo chiedendo se c'è un modo semplice per principianti per far scorrere la vista verso l'alto, e poi tornare indietro quando il montaggio inizia e finisce?Come si scorre la vista quando appare la tastiera?

Grazie.

+0

possibile duplicato di [Come fare un UITextField salire quando la tastiera è presente] (http://stackoverflow.com/questions/1126726/how-to-make-a-uitextfield-move-up-when -keyboard-is-present) –

risposta

28

Ho realizzato soluzioni che funzionano con le visualizzazioni scroll e non scroll utilizzando la notifica della tastiera e un rilevamento del primo risponditore corrente, ma a volte uso questa soluzione banale invece: il modo semplice è quello di rilevare la tastiera di apertura tramite il testo metodo del delegato di campo textViewDidBeginEditing: e per spostare l'intera vista verso l'alto. Il modo più semplice per farlo è con qualcosa sulla falsariga di cambiare self.view.bounds.origin.y a -100 (o qualsiasi altra cosa). Utilizzare il corrispondente metodo textViewShouldEndEditing: per impostarlo sull'opposto, che è 100 in questo caso. Il cambio bounds è una procedura relativa. Dopo averlo cambiato, la cornice viene spostata, ma l'origine dei limiti è ancora zero.

+6

Grazie. Questo è il mio codice finora: '- (BOOL) textViewDidBeginEditing: (UITextField *) textField { [UIView beginAnimations: nil context: NULL]; [UIView setAnimationDuration: 0.35f]; CGRect frame = self.view.frame; frame.origin.y = -100; [self.view setFrame: frame]; [UIView commitAnimations]; } 'Ma ricevo un avviso che dice" Il controllo raggiunge la fine della funzione non vuota ". Non sono sicuro di come aggirare questo, mi dispiace, sono ancora un principiante. – John

+1

np. Aggiungi 'return YES;' alla fine del metodo per dire che stai permettendo la modifica. Non dimenticare di impostare questa classe come delegato per quella visualizzazione di testo. Esiste un metodo corrispondente per UITextFieldDelegates chiamato 'textFieldDidBeginEditing:' se necessario. –

+0

Fantastico, questo ha funzionato, grazie mille. Ancora una domanda, come posso impostare questa classe come delegato per quella visualizzazione di testo? Scusa se è una domanda stupida lol. – John

24

Da quando l'ho trovato, utilizzo TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.

Si sta lavorando molto, ed è molto facile da installare:

  • Aggiungi un UIScrollView nella XI ter del controller della vista
  • Impostare classe della vista di scorrimento per TPKeyboardAvoidingScrollView (ancora nel XI ter, tramite l'ispettore identità)
  • Mettere tutti i controlli all'interno di quella vista di scorrimento

è anche possibile creare a livello di codice, se si vuole.


Esiste una classe per lo stesso bisogno all'interno di UITableViewController; è necessario solo nel caso in cui supporti una versione di iOS inferiore a 4.3.

+0

Cool, grazie, ho intenzione di provare questo ora. Questa potrebbe essere una domanda stupida, ma ho già impostato il pennino, aggiungendo una vista di scorrimento in cima al pennino che non funziona? (Ho anche impostato uno sfondo in Vista immagine) – John

+0

Basta aggiungere la vista al pennino, quindi spostare gli altri elementi all'interno della vista. Verranno mantenute tutte le proprietà dei tuoi elementi (IBOutlet, configurazione). Se hai incasinato, cancella l'ultimo passo (o ripristina il tuo ultimo commit!) – Guillaume

+0

se la libreria è fatta da Micheal Tyson, quindi la sto usando. Semplice. – abbood

-1

ho in questo una scrollview e 3 campi di testo. Ho un semplice codice dalla mia propria applicazione:

file h è: file di

#import <UIKit/UIKit.h> 

@interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate> 

@property (nonatomic, retain) NSDictionary *dict_contactDetail; 

@property (nonatomic, retain) IBOutlet UILabel *lbl_name; 
@property (nonatomic, retain) IBOutlet UITextField *txtField_tel; 
@property (nonatomic, retain) IBOutlet UITextField *txtField_address; 
@property (nonatomic, retain) IBOutlet UITextField *txtField_email; 

@property (nonatomic, retain) IBOutlet UIScrollView *scrollView; 

@end 

.m:

#import "AddContactViewController.h" 

@interface AddContactViewController() 

@end 

@implementation AddContactViewController 

@synthesize dict_contactDetail; 

@synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view from its nib. 

    // NSLog(@"dict_contactDetail : %@", dict_contactDetail); 

    UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonSystemItemDone target:self action:@selector(addEmergencyContact:)]; 
    self.navigationItem.rightBarButtonItem = rightButton; 


    lbl_name.text = [NSString stringWithFormat:@"%@ %@", [dict_contactDetail valueForKey:@"fname"], [dict_contactDetail valueForKey:@"lname"]]; 

    txtField_tel.returnKeyType = UIReturnKeyDone; 
    txtField_email.returnKeyType = UIReturnKeyDone; 
    txtField_address.returnKeyType = UIReturnKeyDone; 

} 



-(void)addEmergencyContact:(id)sender 
{ 
    scrollView.frame = CGRectMake(0, 0, 320, 460); 
} 

#pragma mark - text field delegates 
- (void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    if([textField isEqual:txtField_tel]) 
    { 
     [scrollView setContentOffset:CGPointMake(0, 70)]; 
     scrollView.frame = CGRectMake(0, 0, 320, 210); 
    } 
    if([textField isEqual:txtField_address]) 
    { 
     [scrollView setContentOffset:CGPointMake(0, 140)]; 
     scrollView.frame = CGRectMake(0, 0, 320, 210); 
    } 
    if([textField isEqual:txtField_email]) 
    { 
     [scrollView setContentOffset:CGPointMake(0, 210)]; 
     scrollView.frame = CGRectMake(0, 0, 320, 210); 
    } 
} 

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    scrollView.frame = CGRectMake(0, 0, 320, 460); 
    [textField resignFirstResponder]; 
    return YES; 
} 



@end 
1

ho trascorso qualche tempo su questo problema e pezzi raccolto codice per creare una soluzione finale. Il mio problema era legato allo scorrimento e alla tastiera di UITableView, aperto/chiuso.

avete bisogno di due metodi parziali nella classe delle cellule:

void EditingBegin(UITextField sender) 
    { 
     // Height of tallest cell, you can ignore this! 
     float tableMargin = 70.0f; 
     float tableHeight = _tableView.Frame.Size.Height; 
     float keyBoardHeight = KeyboardHeight(); 

     NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows; 
     RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section); 
     RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section); 
     float lastCellY = rectLast.Y - rectFirst.Y; 
     if (lastCellY > tableHeight - keyBoardHeight) 
     { 
      float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight); 
      this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f); 
     } 

     float cellPosition = this._tableView.RectForSection(this._section).Y; 
     if (cellPosition > tableHeight - keyBoardHeight) 
     { 
      if (this._tableView.ContentInset.Bottom == 0.0f) 
      { 
       float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight); 
       this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f); 
      } 
      else 
      { 
       this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true); 
      } 
     } 
    } 

    partial void EditingEnd(UITextField sender) 
    { 
     UIView.BeginAnimations(null); 
     UIView.SetAnimationDuration(0.3f); 
     this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f); 
     UIView.CommitAnimations(); 
    } 

e poi nella classe di visualizzazione del controller:

public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration) 
    { 
     base.WillAnimateRotation(toInterfaceOrientation, duration); 

     float bottom = this.TableView.ContentInset.Bottom; 
     if (bottom > 0.0f) 
     { 
      if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown) 
      { 
       bottom = bottom * UIScreen.MainScreen.Bounds.Width/UIScreen.MainScreen.Bounds.Height; 
      } 
      else 
      { 
       bottom = bottom * UIScreen.MainScreen.Bounds.Height/UIScreen.MainScreen.Bounds.Width; 
      } 

      UIEdgeInsets insets = this.TableView.ContentInset; 
      this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f); 
     } 
    } 
0

Se si dispone di un UITableView o un UIScrollView è meglio per modificare i valori per contentOffset invece di apportare modifiche allo frame.

Lavorando su Peter's Answer, l'aggiunta di questo metodo per la classe funziona bene:

- (void)textViewDidBeginEditing:(UITextField *)textField { 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.35f]; 
    CGPoint offset = self.tableView.contentOffset; 
    offset.y += 200; // You can change this, but 200 doesn't create any problems 
    [self.tableView setContentOffset:offset]; 
    [UIView commitAnimations]; 
} 

Questo è tutto, non c'è bisogno di aggiungere il metodo textViewDidEndEditing.


non avrei bisogno di dirlo, ma per far funzionare la vostra UITextField o UITextViewdeve essere un delegato del controller.

3

@BenLu e altri utenti che si trovano ad affrontare problemi della funzione non vengono mai chiamati sempre è a causa del seguente motivo: quanto bydefaults funzione delegata inbuild di ritorno void invece di BOOL questo è come dovrebbe essere la seguente:

-(void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.35f]; 
    CGRect frame = self.view.frame; 
    frame.origin.y = -100; 
    [self.view setFrame:frame]; 
    [UIView commitAnimations]; 
} 

-(void)textFieldDidEndEditing:(UITextField *)textField 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.35f]; 
    CGRect frame = self.view.frame; 
    frame.origin.y = 100; 
    [self.view setFrame:frame]; 
    [UIView commitAnimations]; 
} 
0

A partire dalla risposta di Peter, ho sviluppato il seguente approccio in Swift 3.0 con iOS 10.1. Sto facendo questo per un textView, quindi ho implementato le funzioni UITextViewDelegate textViewDidBeginEditing e textViewDidEndEditing dove aggiusto i limiti della vista. Come puoi vedere, imposto il valore dell'origine Y su un piccolo numero positivo per scorrere verso l'alto e poi di nuovo su 0 per tornare alla posizione originale.

Ecco il codice pertinente dal mio ViewController. Non è necessario animare, ma aggiunge un tocco di classe.

func textViewDidBeginEditing(_ textView: UITextView) 
{ 
    if UIScreen.main.bounds.height < 568 { 
     UIView.animate(withDuration: 0.75, animations: { 
      self.view.bounds.origin.y = 60 
     }) 
    } 
} 

func textViewDidEndEditing(_ textView: UITextView) 
{ 
    if UIScreen.main.bounds.height < 568 { 
     UIView.animate(withDuration: 0.75, animations: { 
      self.view.bounds.origin.y = 0 
     }) 
    } 
} 
Problemi correlati