ios keyboard uitextfield uisegmentedcontrol accessory

Barra de herramientas con "Anterior" y "Siguiente" para la entrada del tecladoAccesoriosVista



keyboard uitextfield (7)

He intentado implementar esta barra de herramientas, donde solo el botón "Siguiente" está habilitado cuando el primer campo de texto es el primer Respuesta y solo el botón "Anterior" cuando el primer campo de texto es la primera Respuesta.

Funciona, pero lo que sigue ocurriendo es que debo presionar los botones ''Anterior'' / ''Siguiente'' dos veces cada vez para habilitar / deshabilitar el botón opuesto.

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


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 "ContactViewController" de thange al nombre de su View Controller.


Aquí hay una extensión de UIViewController que uso cuando necesito un grupo de UITextField s para proporcionar navegación a través del accesorio de entrada. No es necesario utilizar la delegación de UITextField con este enfoque, y agregar el comportamiento a múltiples formas se convierte en una sola línea. También admite el botón ''Hecho'' para descartar.

extension UIViewController { func addInputAccessoryForTextFields(textFields: [UITextField], dismissable: Bool = true, previousNextable: Bool = false) { for (index, textField) in textFields.enumerated() { 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.isEnabled = 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.isEnabled = false } else { nextButton.target = textFields[index + 1] nextButton.action = #selector(UITextField.becomeFirstResponder) } items.append(contentsOf: [previousButton, nextButton]) } let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: view, action: #selector(UIView.endEditing)) items.append(contentsOf: [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.


De acuerdo, después de ver el brillante BSKeyboardControls , intenté implementar la habilitación y deshabilitación del control segmentado en la textFieldDidBeginEditing , en lugar de donde estaba mi @selector . También introduje una variable para el control segmentado. Ahora funciona. Aquí está el fragmento 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 reinventar la rueda".

Tener el botón Prev y Next sobre un teclado para cambiar entre UITextView s es tan común que puede encontrar muchas implementaciones buenas listas para usar.

Echa un vistazo a BSKeyboardControls , por ejemplo.


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 es necesario habilitar otro elemento, ya que se reinicializan cada vez que cambia el teclado ...


Rápido:

lazy var inputToolbar: UIToolbar = { var toolbar = UIToolbar() toolbar.barStyle = .default toolbar.translucent = true toolbar.sizeToFit() var doneButton = UIBarButtonItem(title: "Done", style: .bordered, 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: .bordered, target: self, action: "keyboardNextButton") nextButton.width = 50.0 var previousButton = UIBarButtonItem(image: UIImage(named: "keyboardNextButton"), style: .Bordered, 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 }


También puedes probar el pod UITextField-Navigation :

pod ''UITextField-Navigation''

Agrega dos propiedades con carga nextTextField y previousTextField a cualquier UITextField. Todo lo que necesita es especificar el nextTextField en el generador de interfaz o mediante programación, y la barra de herramientas se agrega al teclado para usted.

Programmáticamente:

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

En el Interface Builder: