2012-01-02 20 views
36

Sé que esta pregunta se ha formulado una y otra vez, pero nada parece funcionar para mí. La mayoría de las soluciones están bastante desactualizadas, y el resto son bloques de código increíblemente grandes que son diez veces más grandes que la codificación real de los proyectos. Tengo unos UITextFields alineados verticalmente, pero cuando el teclado se inicia para editar uno, cubre el campo de texto. Me preguntaba si existe una forma sencilla para principiantes de desplazar la vista hacia arriba y luego hacia atrás cuando la edición comienza y termina.Cómo desplazarse hacia arriba cuando aparece el teclado?

Gracias.

+0

posible duplicado de [Como hacer un UITextField moverse hacia arriba cuando está presente el teclado] (http://stackoverflow.com/questions/1126726/how-to-make-a-uitextfield-move-up-when -keyboard-is-present) –

Respuesta

28

He creado soluciones que funcionan con vistas de desplazamiento y sin desplazamiento usando la notificación del teclado y una detección de la primera respuesta actual, pero a veces utilizo esta solución trivial: la manera simple es detectar el teclado de apertura mediante el texto el método del delegado de campo textViewDidBeginEditing: y mover toda la vista hacia arriba. La forma más fácil de hacerlo es con algo como cambiar self.view.bounds.origin.y a -100 (o lo que sea). Use el método correspondiente textViewShouldEndEditing: para establecerlo en el opuesto, que es 100 en este caso. Cambiar bounds es un procedimiento relativo. Después de cambiarlo, se mueve el marco pero el origen de los límites sigue siendo cero.

+6

Gracias. Este es mi código hasta el momento: '- (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]; } 'Pero recibo una advertencia que dice" El control llega al final de la función no válida ". No estoy seguro de cómo solucionar esto, lo siento, todavía soy un principiante en esto. – John

+1

np. Agregue 'return YES;' al final del método para decir que está permitiendo la edición. No olvides configurar esta clase como el delegado para esa vista de texto. Hay un método correspondiente para UITextFieldDelegates llamado 'textFieldDidBeginEditing:' si es necesario. –

+0

Impresionante, eso funcionó, muchas gracias. Solo una pregunta más, ¿cómo configuro esta clase como el delegado para esa vista de texto? Lo siento si es una pregunta tonta jajaja. – John

24

Desde que lo encontré, uso TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.

Se está trabajando muy bien, y es muy fácil de configurar:

  • Añadir un UIScrollView en xib de su controlador de vista
  • conjunto de clases de la vista de desplazamiento para TPKeyboardAvoidingScrollView (todavía en el XI ter, a través del inspector de la identidad)
  • colocar todos los controles dentro de ese punto de vista de desplazamiento

también pueden crear mediante programación, si lo desea.


Hay una clase para la misma necesidad dentro de un UITableViewController; solo es necesario en caso de que admita una versión de iOS por debajo de 4.3.

+0

Genial, gracias, voy a intentar esto ahora. Esta podría ser una pregunta tonta, pero ya configuré la punta, ¿agregará una vista de desplazamiento sobre la punta? (También he establecido un fondo en la Vista de imagen) – John

+0

Simplemente agregue la vista a la punta, luego mueva los otros elementos dentro de la vista. Todas las propiedades de sus elementos (IBOutlet, configuración) se mantendrán. En caso de que haya cometido un error, cancele el último paso (o vuelva a su última confirmación) – Guillaume

+0

si la biblioteca está hecha por Micheal Tyson, entonces la estoy usando. Sencillo. – abbood

-1

Tengo un scrollview y 3 campos de texto en esto. Tengo un código simple de mi propia aplicación:

archivo .h es: archivo

#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

pasé algún tiempo en este problema y se reunieron piezas de código para crear una solución final. Mi problema estaba relacionado con el desplazamiento UITableView y el teclado abrir/cerrar.

Se necesitan dos métodos parciales en su clase de células:

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

y luego en la clase de controlador de vista:

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

Si usted tiene un UITableView o una UIScrollView que es mejor para cambiar los valores de contentOffset en lugar de hacer cambios en el frame.

Trabajando en Peter's Answer, la adición de este método a la clase funciona muy bien:

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

Eso es todo, no hay necesidad de añadir el método textViewDidEndEditing.


que no debería necesitar decir esto, pero para que esto funcione su UITextField o UITextViewdebe haber un delegado de su controlador.

3

@BenLu y otros usuarios que se enfrentan a problemas de la función nunca se están llamados es debido a razones siguientes: Como los bydefaults función delegado inbuild volverá vacía en lugar de BOOL esto es como debe ser como sigue:

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

Comenzando con la respuesta de Peter, desarrollé el siguiente enfoque en Swift 3.0 bajo iOS 10.1. Estoy haciendo esto para una vista de texto, así que he implementado las funciones UITextViewDelegate textViewDidBeginEditing y textViewDidEndEditing donde ajusto los límites de la vista. Como puede ver, ajusto el valor Y de origen a un pequeño número positivo para desplazarme hacia arriba y luego de vuelta a 0 para volver a la posición original.

Aquí está el código relevante de mi ViewController. No es necesario animar, pero agrega un toque agradable.

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