Barra de herramientas con "Anterior" y "Siguiente" para el keyboard inputAccessoryView

He estado intentando implementar esta barra de herramientas, donde solo se habilita el button 'Siguiente' cuando el campo de text superior es el primer respondedor y solo el button 'Anterior' está habilitado cuando el campo de text inferior es el primer respondedor.

Funciona un poco, pero lo que sucede es que tengo que tocar dos veces los botones 'Anterior' / 'Siguiente' para habilitar / deshabilitar el button contrario.

¿Me estoy perdiendo algo en la cadena de respuesta que está haciendo que esto suceda?

Aquí está mi código:

- (void)viewDidLoad { [super viewDidLoad]; [self.topText becomeFirstResponder]; } - (UIToolbar *)keyboardToolBar { UIToolbar *toolbar = [[UIToolbar alloc] init]; [toolbar setBarStyle:UIBarStyleBlackTranslucent]; [toolbar sizeToFit]; UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:@[@"Previous", @"Next"]]; [segControl setSegmentedControlStyle:UISegmentedControlStyleBar]; segControl.momentary = YES; segControl.highlighted = YES; [segControl addTarget:self action:@selector(changeRow:) forControlEvents:(UIControlEventValueChanged)]; [segControl setEnabled:NO forSegmentAtIndex:0]; UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithCustomView:segControl]; NSArray *itemsArray = @[nextButton]; [toolbar setItems:itemsArray]; return toolbar; } - (void)changeRow:(id)sender { int idx = [sender selectedSegmentIndex]; if (idx == 1) { [sender setEnabled:NO forSegmentAtIndex:1]; [sender setEnabled:YES forSegmentAtIndex:0]; self.topText.text = @"Top one"; [self.bottomText becomeFirstResponder]; } else { [sender setEnabled:NO forSegmentAtIndex:0]; [sender setEnabled:YES forSegmentAtIndex:1]; self.bottomText.text =@"Bottom one"; [self.topText becomeFirstResponder]; } } -(void)textFieldDidBeginEditing:(UITextField *)textField { if (!textField.inputAccessoryView) { textField.inputAccessoryView = [self keyboardToolBar]; } } 

Rápido:

 lazy var inputToolbar: UIToolbar = { var toolbar = UIToolbar() toolbar.barStyle = .default toolbar.translucent = true toolbar.sizeToFit() var doneButton = UIBarButtonItem(title: "Done", style: .bordenetworking, target: self, action: "inputToolbarDonePressed") var flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) var fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) var nextButton = UIBarButtonItem(image: UIImage(named: "keyboardPreviousButton"), style: .bordenetworking, target: self, action: "keyboardNextButton") nextButton.width = 50.0 var previousButton = UIBarButtonItem(image: UIImage(named: "keyboardNextButton"), style: .Bordenetworking, target: self, action: "keyboardPreviousButton") toolbar.setItems([fixedSpaceButton, nextButton, fixedSpaceButton, previousButton, flexibleSpaceButton, doneButton], animated: false) toolbar.userInteractionEnabled = true return toolbar }() 

En UITextFieldDelegate

  func textFieldShouldBeginEditing(textField: UITextField) -> Bool { textField.inputAccessoryView = inputToolbar return true } 

Bien, después de ver los shinys controles de BSKeyboard , intenté implementar la habilitación y deshabilitación del control segmentado en textFieldDidBeginEditing , en lugar de dónde estaba mi @selector . También introduje una variable para el control segmentado. Ahora funciona. Aquí está el fragment de código modificado:

 - (void)viewDidLoad { [super viewDidLoad]; [self.topText becomeFirstResponder]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (UIToolbar *)keyboardToolBar { UIToolbar *toolbar = [[UIToolbar alloc] init]; [toolbar setBarStyle:UIBarStyleBlackTranslucent]; [toolbar sizeToFit]; self.segControl = [[UISegmentedControl alloc] initWithItems:@[@"Previous", @"Next"]]; [self.segControl setSegmentedControlStyle:UISegmentedControlStyleBar]; self.segControl.momentary = YES; [self.segControl addTarget:self action:@selector(changeRow:) forControlEvents:(UIControlEventValueChanged)]; [self.segControl setEnabled:NO forSegmentAtIndex:0]; UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithCustomView:self.segControl]; NSArray *itemsArray = @[nextButton]; [toolbar setItems:itemsArray]; return toolbar; } - (void)changeRow:(id)sender { int idx = [sender selectedSegmentIndex]; if (idx) { self.topText.text = @"Top one"; [self.bottomText becomeFirstResponder]; } else { self.bottomText.text =@"Bottom one"; [self.topText becomeFirstResponder]; } } -(void)textFieldDidBeginEditing:(UITextField *)textField { if (!textField.inputAccessoryView) { textField.inputAccessoryView = [self keyboardToolBar]; } if (textField.tag) { [self.segControl setEnabled:NO forSegmentAtIndex:1]; [self.segControl setEnabled:YES forSegmentAtIndex:0]; } } 

Mi sugerencia aquí es "no redevise la rueda".

Tener el button Prev y Next sobre un keyboard para cambiar entre UITextView s es tan común que puede encontrar muchas buenas implementaciones lists para usar.

Echa un vistazo a BSKeyboardControl , por ejemplo.

Aquí hay una extensión UIViewController que uso cada vez que necesito un grupo de UITextField s para proporcionar navigation mediante el accesorio de input. No es necesario usar la delegación de UITextField con este enfoque, y agregar el comportamiento a múltiples formularios, pero viene de una sola línea. También es compatible con el button 'Listo' para descartar.

 extension UIViewController { func addInputAccessoryForTextFields(textFields: [UITextField], dismissable: Bool = true, previousNextable: Bool = false) { for (index, textField) in textFields.enumerate() { let toolbar: UIToolbar = UIToolbar() toolbar.sizeToFit() var items = [UIBarButtonItem]() if previousNextable { let previousButton = UIBarButtonItem(image: UIImage(named: "Backward Arrow"), style: .Plain, target: nil, action: nil) previousButton.width = 30 if textField == textFields.first { previousButton.enabled = false } else { previousButton.target = textFields[index - 1] previousButton.action = #selector(UITextField.becomeFirstResponder) } let nextButton = UIBarButtonItem(image: UIImage(named: "Forward Arrow"), style: .Plain, target: nil, action: nil) nextButton.width = 30 if textField == textFields.last { nextButton.enabled = false } else { nextButton.target = textFields[index + 1] nextButton.action = #selector(UITextField.becomeFirstResponder) } items.appendContentsOf([previousButton, nextButton]) } let spacer = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil) let doneButton = UIBarButtonItem(barButtonSystemItem: .Done, target: view, action: #selector(UIView.endEditing)) items.appendContentsOf([spacer, doneButton]) toolbar.setItems(items, animated: false) textField.inputAccessoryView = toolbar } } } 

ejemplo:

 let field1 = UITextField() let field2 = UITextField() addInputAccessoryForTextFields([field1, field2], dismissable: true, previousNextable: true) 

Aquí hay un icono de flecha razonable.

También puedes probar el pod UITextField-Navigation :

pod 'UITextField-Navigation'

Añade dos properties de carga perezosa nextTextField y previousTextField a cualquier UITextField. Todo lo que necesita es especificar el nextTextField en el generador de interfaces o mediante progtwigción, y la barra de herramientas se agrega al keyboard para usted.

Programáticamente:

 import UITextField_Navigation let textField1 = UITextField() let textField2 = UITextField() textField1.nextTextField = textField2 assert(textField2 == textField1.nextTextField) assert(textField1 == textField2.previousTextField) 

En el generador de interfaces:

conecte nextTextField en Interface Builder introduzca la descripción de la imagen aquí

Prueba esto :-

 - (void)viewDidLoad { [super viewDidLoad]; [self.topText becomeFirstResponder]; } - (UIToolbar *)keyboardToolBar { UIToolbar *toolbar = [[UIToolbar alloc] init]; [toolbar setBarStyle:UIBarStyleBlackTranslucent]; [toolbar sizeToFit]; UISegmentedControl *segControl = [[UISegmentedControl alloc] initWithItems:@[@"Previous", @"Next"]]; [segControl setSegmentedControlStyle:UISegmentedControlStyleBar]; segControl.momentary = YES; segControl.highlighted = YES; [segControl addTarget:self action:@selector(changeRow:) forControlEvents:(UIControlEventValueChanged)]; [segControl setEnabled:NO forSegmentAtIndex:0]; UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithCustomView:segControl]; NSArray *itemsArray = @[nextButton]; [toolbar setItems:itemsArray]; int idx = [sender selectedSegmentIndex]; if (idx == 1) { [sender setEnabled:NO forSegmentAtIndex:1]; } else { [sender setEnabled:NO forSegmentAtIndex:0]; } return toolbar; } - (void)changeRow:(id)sender { int idx = [sender selectedSegmentIndex]; if (idx == 1) { self.topText.text = @"Top one"; [self.bottomText becomeFirstResponder]; } else { self.bottomText.text =@"Bottom one"; [self.topText becomeFirstResponder]; } } -(void)textFieldDidBeginEditing:(UITextField *)textField { if (!textField.inputAccessoryView) { textField.inputAccessoryView = [self keyboardToolBar]; } } 

no necesita habilitar otro elemento, ya que reinicializan cada vez que cambia el keyboard …

Actualizado para Swift 3.0

 lazy var inputToolbar: UIToolbar = { var toolbar = UIToolbar() toolbar.barStyle = .default toolbar.isTranslucent = true toolbar.sizeToFit() var doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ContactViewController.inputToolbarDonePressed)) var flexibleSpaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) var fixedSpaceButton = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) var nextButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(ContactViewController.keyboardNextButton)) var previousButton = UIBarButtonItem(title: "Previous", style: .plain, target: self, action: #selector(ContactViewController.keyboardPreviousButton)) toolbar.setItems([fixedSpaceButton, previousButton, fixedSpaceButton, nextButton, flexibleSpaceButton, doneButton], animated: false) toolbar.isUserInteractionEnabled = true return toolbar }() 

Y entonces:

 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { textField.inputAccessoryView = inputToolbar return true } 

Recuerde cambiar thange "ContactViewController" al nombre de su controller de vista.