2009-02-25 17 views
205

No hay un botón "Listo" en el teclado numérico. Cuando un usuario termina de ingresar información numérica en un campo de texto, ¿cómo puedo hacer que desaparezca el teclado numérico?Cómo mostrar el botón "Listo" en el teclado numérico del iPhone

Pude obtener un botón "Hecho" usando el teclado predeterminado, pero luego los usuarios tendrían que cambiar a las teclas numéricas para ingresar números. ¿Hay alguna manera de mostrar un botón "Listo" en el teclado numérico?

Respuesta

320

Otra solución. Perfecto si hay otros campos de texto sin almohadilla numérica en la pantalla.

inputAccessoryView

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)]; 
    numberToolbar.barStyle = UIBarStyleBlackTranslucent; 
    numberToolbar.items = @[[[UIBarButtonItem alloc]initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelNumberPad)], 
         [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], 
         [[UIBarButtonItem alloc]initWithTitle:@"Apply" style:UIBarButtonItemStyleDone target:self action:@selector(doneWithNumberPad)]]; 
    [numberToolbar sizeToFit]; 
    numberTextField.inputAccessoryView = numberToolbar; 
} 

-(void)cancelNumberPad{ 
    [numberTextField resignFirstResponder]; 
    numberTextField.text = @""; 
} 

-(void)doneWithNumberPad{ 
    NSString *numberFromTheKeyboard = numberTextField.text; 
    [numberTextField resignFirstResponder]; 
} 
+1

Sin duda la mejor manera de lograr esto. Explícitamente porque se adhiere a HIG estricto de manzanas. –

+3

La otra solución es muy frágil en términos de cualquier cambio gráfico en el teclado en pantalla lo romperá. – kailoon

+0

Si hay varios campos de texto, ¿cómo puedo determinar qué UITextField se está editando? – Nate

13

El truco que he visto utilizar es crear un botón transparente personalizado del tamaño de toda la vista y luego, en su método de clic, hacer que el campo de texto resigne la primera respuesta. Entonces el usuario puede hacer clic en cualquier lugar fuera del campo para cerrar el teclado.

+3

He hecho esto además de la tecla Volver. Hace una aplicación mucho más fácil de usar. Me gusta dar a las teclas de retorno y hacer clic en los métodos de devolución en cualquier lugar. – IcyBlueRose

+3

ahora que tenemos UIGestureRecognizers, simplemente configure un reconocedor de gestos de toque en la vista principal del controlador de vista y haga que envíe endEditing: YES a su vista. Esto cerrará el teclado de cada campo de texto que el teclado pueda reparar, al tocar fuera del teclado. – chadbag

5

This forum post describe cómo personalizar el UIKeyboard para agregar su vista personalizada al teclado.

10

La solución en funciona muy bien, pero solo si no hay otros campos de texto que no sean números en la pantalla.

Tomé ese código y lo convertí en un UIViewController que puede simplemente crear una subclase para que funcionen los pads numéricos. Deberá obtener los iconos del enlace de arriba.

NumberPadViewController.h:

#import <UIKit/UIKit.h> 

@interface NumberPadViewController : UIViewController { 
    UIImage *numberPadDoneImageNormal; 
    UIImage *numberPadDoneImageHighlighted; 
    UIButton *numberPadDoneButton; 
} 

@property (nonatomic, retain) UIImage *numberPadDoneImageNormal; 
@property (nonatomic, retain) UIImage *numberPadDoneImageHighlighted; 
@property (nonatomic, retain) UIButton *numberPadDoneButton; 

- (IBAction)numberPadDoneButton:(id)sender; 

@end 

y NumberPadViewController.m:

#import "NumberPadViewController.h" 

@implementation NumberPadViewController 

@synthesize numberPadDoneImageNormal; 
@synthesize numberPadDoneImageHighlighted; 
@synthesize numberPadDoneButton; 

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle { 
    if ([super initWithNibName:nibName bundle:nibBundle] == nil) 
     return nil; 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.0) { 
     self.numberPadDoneImageNormal = [UIImage imageNamed:@"DoneUp3.png"]; 
     self.numberPadDoneImageHighlighted = [UIImage imageNamed:@"DoneDown3.png"]; 
    } else {   
     self.numberPadDoneImageNormal = [UIImage imageNamed:@"DoneUp.png"]; 
     self.numberPadDoneImageHighlighted = [UIImage imageNamed:@"DoneDown.png"]; 
    }   
    return self; 
} 

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

    // Add listener for keyboard display events 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { 
     [[NSNotificationCenter defaultCenter] addObserver:self 
                selector:@selector(keyboardDidShow:) 
                name:UIKeyboardDidShowNotification 
                object:nil];  
    } else { 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(keyboardWillShow:) 
                name:UIKeyboardWillShowNotification 
                object:nil]; 
    } 

    // Add listener for all text fields starting to be edited 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(textFieldDidBeginEditing:) 
               name:UITextFieldTextDidBeginEditingNotification 
               object:nil]; 
} 

- (void)viewWillDisappear:(BOOL)animated { 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { 
     [[NSNotificationCenter defaultCenter] removeObserver:self 
                 name:UIKeyboardDidShowNotification 
                 object:nil];  
    } else { 
     [[NSNotificationCenter defaultCenter] removeObserver:self 
                 name:UIKeyboardWillShowNotification 
                 object:nil]; 
    } 
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:UITextFieldTextDidBeginEditingNotification 
                object:nil]; 
    [super viewWillDisappear:animated]; 
} 

- (UIView *)findFirstResponderUnder:(UIView *)root { 
    if (root.isFirstResponder) 
     return root;  
    for (UIView *subView in root.subviews) { 
     UIView *firstResponder = [self findFirstResponderUnder:subView];   
     if (firstResponder != nil) 
      return firstResponder; 
    } 
    return nil; 
} 

- (UITextField *)findFirstResponderTextField { 
    UIResponder *firstResponder = [self findFirstResponderUnder:[self.view window]]; 
    if (![firstResponder isKindOfClass:[UITextField class]]) 
     return nil; 
    return (UITextField *)firstResponder; 
} 

- (void)updateKeyboardButtonFor:(UITextField *)textField { 

    // Remove any previous button 
    [self.numberPadDoneButton removeFromSuperview]; 
    self.numberPadDoneButton = nil; 

    // Does the text field use a number pad? 
    if (textField.keyboardType != UIKeyboardTypeNumberPad) 
     return; 

    // If there's no keyboard yet, don't do anything 
    if ([[[UIApplication sharedApplication] windows] count] < 2) 
     return; 
    UIWindow *keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1]; 

    // Create new custom button 
    self.numberPadDoneButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
    self.numberPadDoneButton.frame = CGRectMake(0, 163, 106, 53); 
    self.numberPadDoneButton.adjustsImageWhenHighlighted = FALSE; 
    [self.numberPadDoneButton setImage:self.numberPadDoneImageNormal forState:UIControlStateNormal]; 
    [self.numberPadDoneButton setImage:self.numberPadDoneImageHighlighted forState:UIControlStateHighlighted]; 
    [self.numberPadDoneButton addTarget:self action:@selector(numberPadDoneButton:) forControlEvents:UIControlEventTouchUpInside]; 

    // Locate keyboard view and add button 
    NSString *keyboardPrefix = [[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2 ? @"<UIPeripheralHost" : @"<UIKeyboard"; 
    for (UIView *subView in keyboardWindow.subviews) { 
     if ([[subView description] hasPrefix:keyboardPrefix]) { 
      [subView addSubview:self.numberPadDoneButton]; 
      [self.numberPadDoneButton addTarget:self action:@selector(numberPadDoneButton:) forControlEvents:UIControlEventTouchUpInside]; 
      break; 
     } 
    } 
} 

- (void)textFieldDidBeginEditing:(NSNotification *)note { 
    [self updateKeyboardButtonFor:[note object]]; 
} 

- (void)keyboardWillShow:(NSNotification *)note { 
    [self updateKeyboardButtonFor:[self findFirstResponderTextField]]; 
} 

- (void)keyboardDidShow:(NSNotification *)note { 
    [self updateKeyboardButtonFor:[self findFirstResponderTextField]]; 
} 

- (IBAction)numberPadDoneButton:(id)sender { 
    UITextField *textField = [self findFirstResponderTextField]; 
    [textField resignFirstResponder]; 
} 

- (void)dealloc { 
    [numberPadDoneImageNormal release]; 
    [numberPadDoneImageHighlighted release]; 
    [numberPadDoneButton release]; 
    [super dealloc]; 
} 

@end 

disfrutar.

+2

El enlace a la solución original ahora redirecciona a http://www.neoos.ch/ –

6

Aquí está el código más reciente. Simplemente incluya #import "UIViewController + NumPadReturn.h" en su viewController.

Aquí es el .h

#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 

@interface UIViewController (NumPadReturn) 



@end 

Y el .m

#import "UIViewController+NumPadReturn.h" 


@implementation UIViewController (NumPadReturn) 

-(void) viewDidLoad{ 
    // add observer for the respective notifications (depending on the os version) 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(keyboardDidShow:) 
                name:UIKeyboardDidShowNotification 
                object:nil];  
    } else { 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(keyboardWillShow:) 
                name:UIKeyboardWillShowNotification 
                object:nil]; 
    } 

} 


- (void)keyboardWillShow:(NSNotification *)note { 
    // if clause is just an additional precaution, you could also dismiss it 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 3.2) { 
     [self addButtonToKeyboard]; 
    } 
} 

- (void)keyboardDidShow:(NSNotification *)note { 
    // if clause is just an additional precaution, you could also dismiss it 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { 
     [self addButtonToKeyboard]; 
    } 
} 

- (void)addButtonToKeyboard { 
    // create custom button 
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
    doneButton.frame = CGRectMake(0, 163, 106, 53); 
    doneButton.adjustsImageWhenHighlighted = NO; 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.0) { 
     [doneButton setImage:[UIImage imageNamed:@"DoneUp3.png"] forState:UIControlStateNormal]; 
     [doneButton setImage:[UIImage imageNamed:@"DoneDown3.png"] forState:UIControlStateHighlighted]; 
    } else {   
     [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal]; 
     [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted]; 
    } 
    [doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside]; 
    // locate keyboard view 
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1]; 
    UIView* keyboard; 
    for(int i=0; i<[tempWindow.subviews count]; i++) { 
     keyboard = [tempWindow.subviews objectAtIndex:i]; 
     // keyboard found, add the button 
     if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { 
      if([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES) 
       [keyboard addSubview:doneButton]; 
     } else { 
      if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES) 
       [keyboard addSubview:doneButton]; 
     } 
    } 
} 

- (void)doneButton:(id)sender { 
    NSLog(@"doneButton"); 
    [self.view endEditing:TRUE]; 
} 



@end 
+0

, esto parece funcionar en el simulador pero en el dispositivo ... tampoco puedo ver el botón HECHO ni sucede nada cuando toco el botón vacío espacio ... alguna idea? – xoail

+14

Vaya, no use este código. Se anulan los métodos de clase de una categoría, lo que hará que se ignore el viewDidLoad "real", etc. de su clase UIViewController. –

2

describo una solución para iOS 4.2+ here pero el botón de despedir a un fundido de entrada después de que aparezca el teclado. No es terrible, pero tampoco es ideal.

La solución descrita en la pregunta vinculada anteriormente incluye una ilusión más elegante para descartar el botón, donde me desvanezco y desplazo verticalmente el botón para proporcionar la apariencia de que el teclado y el botón se descartan juntos.

6

Una solución mucho más fácil

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 

    [textViewInstance1 resignFirstResponder]; 
    [textViewInstance2 resignFirstResponder]; 
    [textField resignFirstResponder]; 
} 
2

La forma más sencilla es:

Crear botón personalizado transparente y lo coloca en la esquina izquierda hacia abajo, lo que tendrá CGSize misma como espacio vacío en UIKeyboardTypeNumberPad. Alternar (mostrar/ocultar) este botón en textField becomeFirstResponder, al hacer clic en el botón, respectivamente.

2

Aquí es la solución más sencilla que he encontrado. Lo aprendí del libro de desarrollo Beginning iOS 5.

Suponiendo que el campo de número se llame numberField.

  1. En ViewController, agregue el siguiente método:

    -(IBAction)closeKeyboard:(id)sender; 
    
  2. En ViewController.m, agregue el código siguiente:

    -(IBAction)closeKeyboard:(id)sender 
    { 
    
        [numberField resignFirstResponder]; 
    
    } 
    
  3. Ir de nuevo a nib archivo.

  4. Abrir Utilities pan.
  5. Abra Identity inspector en Utilities panorámica.
  6. Haga clic en el View (en archivo de punta) una vez. Asegúrese de no haber hecho clic en ninguno de los elementos en la vista. En aras de la aclaración, debería ver UIView bajo Class en Identity inspector.
  7. Cambia la clase de UIView a UIControl.
  8. Abierto Connection Inspector.
  9. Haga clic y arrastre Touch Down y suelte la flecha en el icono File Owner. (FYI ... El icono del propietario del archivo se muestra a la izquierda de View y aparece como un cubo hueco con marco amarillo.)
  10. Seleccione el método: closeKeyboard.
  11. Ejecute el programa.

Ahora cuando haga clic en cualquier lugar en el fondo de View, debería poder cerrar el teclado.

Espero que esto lo ayude a resolver su problema. :-)

2

Modifiqué la solución de Bryan para que fuera un poco más robusta, para que funcionara bien con otros tipos de teclados que pudieran aparecer en la misma vista. Es descrito aquí:

Create a DONE button on the iOS numpad UIKeyboard

que iba a tratar de explicar aquí, pero la mayor parte es el código para mirar que no cabrían fácilmente aquí

+0

Esta fue la mejor solución que encontré para XCode 4.5 y funciona con iOS 6.0. Agrega un botón HECHO al teclado numérico. Vaya a la publicación original para obtener los gráficos del botón HECHO. http://www.neoos.ch/blog/37-uikeyboardtypenumberpad-and-the-missing-return-key – birdman

+0

gracias! ¡Me alegra que te haya ayudado! – horseshoe7

2

Si usted sabe de antemano el número de números para ser introducidos (por ejemplo, un PIN de 4 dígitos) que podría auto-despedir después de 4 pulsaciones de teclas, como por mi respuesta a esta pregunta similar:

dismissing Number Pad

No hay necesidad de un botón adicional hecho en este caso .

36

Aquí es una adaptación de la respuesta de Luda para Swift:

En la declaración de la subclase UIViewController poner

let numberToolbar: UIToolbar = UIToolbar() 

en viewDidLoad poner:

numberToolbar.barStyle = UIBarStyle.BlackTranslucent 
    numberToolbar.items=[ 
     UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Bordered, target: self, action: "hoopla"), 
     UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil), 
     UIBarButtonItem(title: "Apply", style: UIBarButtonItemStyle.Bordered, target: self, action: "boopla") 
    ] 

    numberToolbar.sizeToFit() 

    textField.inputAccessoryView = numberToolbar //do it for every relevant textfield if there are more than one 

y añadir las funciones de alboroto y hoopla (siéntase libre de elegir otros nombres, simplemente cambie los nombres del selector en ViewDidLoad según corresponda

func boopla() { 
    textField.resignFirstResponder() 
} 

func hoopla() { 
    textField.text="" 
    textField.resignFirstResponder() 
} 
+0

Respuesta actualizada realmente útil – MikeJ

+1

'UIBarButtonItemStyle.Bordered' está en desuso desde iOS 8.0. 'UIBarButtonItemStyle.Plain' se sugiere en su lugar. – Jonny

+0

Los selectores se deben actualizar a: #selector (YourViewController.boopla) –

2

también podemos hacer la "usuario tocó en otro lugar" solución aún más simple si le decimos punto de vista de nuestra vista controlador para finalizar la edición:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
     [super touchesBegan:touches withEvent:event]; 

     [self.view endEditing:YES]; //YES ignores any textfield refusal to resign 
} 

... asumiendo que "tocar a otra parte descarta el teclado "es el comportamiento deseado para cualquier otro campo editable en la vista también.

9

continuación es una revisión de la respuesta de Luda con los siguientes cambios:

  • la vista accesorio está dimensionado automáticamente a la anchura del bastidor aplicación

  • el desuso constante UIBarButtonItemStyleBordered se evita

  • el botón "Hecho" se crea una instancia como UIBarButtonSystemItemDone

Actualmente, el botón "Listo" se centra en la vista de accesorios. Puede colocarlo a izquierda o derecha eliminando el espacio en el lado pertinente.

He omitido un botón "Cancelar" porque el teclado predeterminado tampoco tiene uno. Si desea un botón "Cancelar", le sugiero que lo cree como un UIBarButtonSystemItemCancel y que se asegure de no descartar el valor original en su campo de texto. El comportamiento "Cancelar" implementado en la respuesta de Luda, que sobrescribe el valor con una cadena en blanco, puede no ser lo que desea.

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    float appWidth = CGRectGetWidth([UIScreen mainScreen].applicationFrame); 
    UIToolbar *accessoryView = [[UIToolbar alloc] 
           initWithFrame:CGRectMake(0, 0, appWidth, 0.1 * appWidth)]; 
    UIBarButtonItem *space = [[UIBarButtonItem alloc] 
          initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace 
          target:nil 
          action:nil]; 
    UIBarButtonItem *done = [[UIBarButtonItem alloc] 
          initWithBarButtonSystemItem:UIBarButtonSystemItemDone 
          target:self 
          action:@selector(selectDoneButton)]; 
    accessoryView.items = @[space, done, space]; 
    self.valueField.inputAccessoryView = accessoryView; 
} 

- (void)selectDoneButton { 
    [self.valueField resignFirstResponder]; 
} 

Para obtener más información sobre la construcción de puntos de vista de accesorios, consulte la documentación de Apple en custom views for data input. Probablemente también desee consultar las páginas de referencia en UIToolbar y UIBarButtonItem.

+0

'[UIScreen mainScreen] .applicationFrame' está en desuso en iOS 9. Use' [UIScreen mainScreen] .bounds' –

0

Todas esas implementaciones sobre encontrar la vista del teclado y agregar el botón hecho en la 3ra fila (es por eso que button.y = 163 b/c la altura del teclado es 216) son frágiles porque iOS mantiene la jerarquía de vista. Por ejemplo, ninguno de los códigos anteriores funciona para iOS9.

Creo que es más seguro encontrar la vista más arriba, por [[[UIApplication sharedApplication] windows] lastObject], y simplemente agregue el botón en la esquina inferior izquierda, doneButton.frame = CGRectMake (0, SCREEN_HEIGHT) -53, 106, 53); // modo retrato

1

Para Swift 2.2 Yo uso este

func addDoneButtonOnKeyboard() { 
    let doneToolbar: UIToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 50)) 

    let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil) 
    let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(DetailViewController.finishDecimalKeypad)) 

    var items: [UIBarButtonItem]? = [UIBarButtonItem]() 
    items?.append(flexSpace) 
    items?.append(done) 

    doneToolbar.items = items 
    doneToolbar.sizeToFit() 
    self.productPrice.inputAccessoryView=doneToolbar 
} 

func finishDecimalKeypad() { 
    self.productPrice?.resignFirstResponder() 
} 
0

Swift 2.2/Yo utilicé la respuesta de Dx_. Sin embargo, quería esta funcionalidad en todos los teclados. Así que en mi clase base pongo el código:

func addDoneButtonForTextFields(views: [UIView]) { 
    for view in views { 
     if let textField = view as? UITextField { 
      let doneToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 50)) 

      let flexSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil) 
      let done = UIBarButtonItem(title: "Done", style: .Done, target: self, action: #selector(dismissKeyboard)) 

      var items = [UIBarButtonItem]() 
      items.append(flexSpace) 
      items.append(done) 

      doneToolbar.items = items 
      doneToolbar.sizeToFit() 

      textField.inputAccessoryView = doneToolbar 
     } else { 
      addDoneButtonForTextFields(view.subviews) 
     } 
    } 
} 

func dismissKeyboard() { 
    dismissKeyboardForTextFields(self.view.subviews) 
} 

func dismissKeyboardForTextFields(views: [UIView]) { 
    for view in views { 
     if let textField = view as? UITextField { 
      textField.resignFirstResponder() 
     } else { 
      dismissKeyboardForTextFields(view.subviews) 
     } 
    } 
} 

A continuación, sólo llaman addDoneButtonForTextFields en self.view.subviews en viewDidLoad (o willDisplayCell si se utiliza una vista de tabla) para agregar el botón Hecho para todos los teclados.

2

Si tiene varios campos numéricos, sugiero que se subclassing UITextField para crear un NumericTextField que siempre muestra un teclado numérico con un botón hecho. Luego, simplemente asocie sus campos numéricos con esta clase en Interface Builder y no necesitará ningún código adicional en ninguno de sus Controladores de Vista. La siguiente es la clase Swift 3.0 que estoy usando en Xcode 8.0.

class NumericTextField: UITextField { 
    let numericKbdToolbar = UIToolbar() 

    // MARK: Initilization 
    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     self.initialize() 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     self.initialize() 
    } 

    // Sets up the input accessory view with a Done button that closes the keyboard 
    func initialize() 
    { 
     self.keyboardType = UIKeyboardType.numberPad 

     numericKbdToolbar.barStyle = UIBarStyle.default 
     let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) 
     let callback = #selector(NumericTextField.finishedEditing) 
     let donebutton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: callback) 
     numericKbdToolbar.setItems([space, donebutton], animated: false) 
     numericKbdToolbar.sizeToFit() 
     self.inputAccessoryView = numericKbdToolbar 
    } 

    // MARK: On Finished Editing Function 
    func finishedEditing() 
    { 
     self.resignFirstResponder() 
    } 
} 
+0

Prefiero su solución de subclase. – AechoLiu

2

He encontrado @user1258240's answer a ser bastante concisa dado que esto no es tan simple como establecer una propiedad returnKeyType.

Sólo quería aportar mi propia "reutilizable" acercamiento a este:

func SetDoneToolbar(field:UITextField) { 
    let doneToolbar:UIToolbar = UIToolbar() 

    doneToolbar.items=[ 
     UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil), 
     UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.dismissKeyboard)) 
    ] 

    doneToolbar.sizeToFit() 
    field.inputAccessoryView = doneToolbar 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    SetDoneToolbar(field: UITextField_1) 
    SetDoneToolbar(field: UITextField_2) 
    SetDoneToolbar(field: UITextField_3) 
    SetDoneToolbar(field: UITextField_N) 
} 
+0

también funciona para SWIFT 4 – richc

3

Una solución Swift usando una extensión. Ideal si tiene varios objetos numéricos UITextField en su aplicación, ya que le da la flexibilidad para decidir, para cada UITextField, si se realizará una acción personalizada cuando Hecho o se pulsa Cancelar.

enter image description here

// 
// UITextField+DoneCancelToolbar.swift 
// 

import UIKit 

extension UITextField { 
    func addDoneCancelToolbar(onDone: (target: Any, action: Selector)? = nil, onCancel: (target: Any, action: Selector)? = nil) {  
     let onCancel = onCancel ?? (target: self, action: #selector(cancelButtonTapped)) 
     let onDone = onDone ?? (target: self, action: #selector(doneButtonTapped)) 

     let toolbar: UIToolbar = UIToolbar() 
     toolbar.barStyle = .default 
     toolbar.items = [ 
      UIBarButtonItem(title: "Cancel", style: .plain, target: onCancel.target, action: onCancel.action), 
      UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil), 
      UIBarButtonItem(title: "Done", style: .done, target: onDone.target, action: onDone.action) 
     ] 
     toolbar.sizeToFit() 

     self.inputAccessoryView = toolbar 
    } 

    // Default actions: 
    func doneButtonTapped() { self.resignFirstResponder() } 
    func cancelButtonTapped() { self.resignFirstResponder() } 
} 

Ejemplo de uso mediante las acciones predeterminadas:

// 
// MyViewController.swift 
// 

@IBOutlet weak var myNumericTextField: UITextField! { 
    didSet { myNumericTextField?.addDoneCancelToolbar() } 
} 

Ejemplo de uso utilizando una costumbre Hecho acción:

// 
// MyViewController.swift 
// 

@IBOutlet weak var myNumericTextField: UITextField! { 
    didSet { 
     myNumericTextField?.addDoneCancelToolbar(onDone: (target: self, action: #selector(doneButtonTappedForMyNumericTextField))) 
    } 
} 

func doneButtonTappedForMyNumericTextField() { 
    print("Done"); 
    myNumericTextField.resignFirstResponder() 
} 
2

SWIFT 3.0 Un sabor diferente, usando partes de algunas respuestas anteriores.

func addToolbarToNumberPad() 
{ 
    let numberPadToolbar: UIToolbar = UIToolbar() 

    numberPadToolbar.isTranslucent = true 
    numberPadToolbar.items=[ 
     UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(self.cancelAction)), 
     UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil), 
     UIBarButtonItem(title: "Custom", style: .done, target: self, action: #selector(self.customAction)), 
     UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.doneAction)), 
    ] 

    numberPadToolbar.sizeToFit() 

    textField.inputAccessoryView = numberPadToolbar 
} 

func cancelAction() 
{ 
    textField.resignFirstResponder() 
} 

func customAction() 
{ 
    textField.resignFirstResponder() 
} 

func doneAction() 
{ 
    textField.resignFirstResponder() 
} 

override func viewDidLoad() 
{ 
    super.viewDidLoad() 

    self.addToolbarToNumberPad() 
} 
Cuestiones relacionadas