Как показать кнопку "Готово" на цифровой клавиатуре iPhone
на цифровой клавиатуре нет кнопки "Готово". Когда пользователь заканчивает вводить числовую информацию в текстовое поле, как я могу заставить цифровую панель исчезнуть?
Я мог бы получить кнопку "сделать" с помощью клавиатуры по умолчанию, но тогда пользователям придется переключаться на цифровые клавиши для ввода цифр. Есть ли способ показать кнопку "Готово" на цифровой клавиатуре?
21 ответ:
другое решение. Идеально, если на экране есть другие текстовые поля без цифровой клавиатуры.
- (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]; }
вот адаптация ответа Люды для Swift:
в объявлении вашего подкласса UIViewController поставить
let numberToolbar: UIToolbar = UIToolbar()
В ViewDidLoad поставил:
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
и добавить функции hoopla и hoopla (не стесняйтесь выбирать другие имена, просто измените имена селектора в ViewDidLoad соответственно
func boopla () { textField.resignFirstResponder() } func hoopla () { textField.text="" textField.resignFirstResponder() }
трюк, который я видел, заключается в том, чтобы сделать пользовательскую прозрачную кнопку размером всего представления, а затем в ее методе щелчка, чтобы текстовое поле отказалось от первого ответчика. Таким образом, пользователь может нажать в любом месте за пределами поля, чтобы закрыть клавиатуру.
решением UIKeyboardTypeNumberPad и отсутствует ключ возврата отлично работает, но только если на экране нет других текстовых полей без цифровой клавиатуры.
Я взял этот код и превратил его в UIViewController, который вы можете просто подкласс, чтобы заставить цифровые панели работать. Вам нужно будет получить значки из приведенной выше ссылки.
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
и NumberPadViewController.м:
#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
наслаждайтесь.
Ниже приведен обзор ответа Люды со следующими изменениями:
вид аксессуара автоматически определяется по ширине рамки приложения
устаревшая константа
UIBarButtonItemStyleBordered
расторгнуткнопка "готово" создается как
UIBarButtonSystemItemDone
В настоящее время кнопка" готово " находится по центру в представлении аксессуаров. Вы можете расположить его слева или справа, удалив пространства на соответствующей стороне.
Я опустил кнопку "Отмена", потому что клавиатура по умолчанию тоже нет. Если вам нужна кнопка "Отмена", я предлагаю вам создать ее как
UIBarButtonSystemItemCancel
и что вы убедитесь, что вы не отбрасываете исходное значение в текстовом поле. Поведение "отмена", реализованное в ответе Люды, которое перезаписывает значение пустой строкой, может быть не тем, что вы хотите.- (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]; }
для получения дополнительной информации о строительных аксессуарах просмотры, см. документацию Apple на настраиваемые представления для ввода данных. Вы, вероятно, захотите ознакомиться со справочными страницами на UIToolbar и UIBarButtonItem как хорошо.
вот самый последний код. Просто включить #import " UIViewController+NumPadReturn.h " в вашем viewController.
здесь .h
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface UIViewController (NumPadReturn) @end
а .м
#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
A Swift 3 решение с помощью расширения. Идеально, если у вас есть несколько числовых
UITextField
объекты в вашем приложении, как это дает гибкость, чтобы решить, для каждогоUITextField
, следует ли выполнять пользовательское действие, когда сделал или отмена постучал.// // 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() } }
пример использования действий по умолчанию:
// // MyViewController.swift // @IBOutlet weak var myNumericTextField: UITextField! { didSet { myNumericTextField?.addDoneCancelToolbar() } }
пример использования с помощью пользовательского сделал действие:
// // MyViewController.swift // @IBOutlet weak var myNumericTextField: UITextField! { didSet { myNumericTextField?.addDoneCancelToolbar(onDone: (target: self, action: #selector(doneButtonTappedForMyNumericTextField))) } } func doneButtonTappedForMyNumericTextField() { print("Done"); myNumericTextField.resignFirstResponder() }
гораздо более простое решение
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; [textViewInstance1 resignFirstResponder]; [textViewInstance2 resignFirstResponder]; [textField resignFirstResponder]; }
этот пост на форуме описывает, как настроить UIKeyboard для добавления пользовательского представления на клавиатуре.
нашел @ user1258240 ответ быть довольно кратким, учитывая, что это не так просто, как задание
returnKeyType
собственность.просто хотел внести свой собственный" многоразовый " подход к этому:
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) }
SWIFT 3.0 другой вкус, используя части некоторых предыдущих ответов.
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() }
я описываю одно решение для iOS 4.2+ здесь но кнопка увольнения исчезает после появления клавиатуры. Это не страшно, но и не идеально.
решение, описанное в вопросе, связанном выше, включает в себя более элегантную иллюзию, чтобы отклонить кнопку, где я исчезаю и вертикально перемещаю кнопку, чтобы обеспечить внешний вид, что клавиатура и кнопка отклоняются вместе.
The простой путь:
создать пользовательская прозрачная кнопка и поместите его в левом нижнем углу, вместе сCGSize
как пустое место вUIKeyboardTypeNumberPad
. Переключить (Показать / Скрыть) эту кнопку на текстовом полеbecomeFirstResponder
, по нажатию кнопки соответственно.
вот самое простое решение, с которым я столкнулся. Я узнал об этом из начала iOS 5 Development book.
предполагая, что числовое поле называется
numberField
.
на
ViewController
добавьте следующий метод:-(IBAction)closeKeyboard:(id)sender;
на
ViewController.m
добавьте следующий код:-(IBAction)closeKeyboard:(id)sender { [numberField resignFirstResponder]; }
вернуться в .
- открыть
Utilities
Пан.- открыть
Identity inspector
подUtilities
Пан.- нажмите на кнопку
View
(в файле nib) раз. Убедитесь, что вы не нажали ни на один из элементов в представлении. Для уточнения, вы должны увидеть UIView подClass
inIdentity inspector
.- изменить класс от UIView для элементов графического интерфейса.
- открыть
Connection Inspector
.- нажмите и перетащите
Touch Down
и опустите стрелку на . (К ВАШЕМУ СВЕДЕНИЮ... Значок владельца файла отображается слева отView
и появляется как пустота куб с желтой рамкой.)- выберите метод:
closeKeyboard
.- запустить программу.
теперь, когда вы щелкните в любом месте на фоне
View
, вы должны быть в состоянии отклонить клавиатуру.надеюсь, это поможет вам решить вашу проблему. : -)
Я изменил решение Брайана, чтобы быть немного более надежным, так что он будет играть хорошо с другими типами клавиатур, которые могут появиться в том же виде. Это описано здесь:
создать кнопку Готово на iOS numpad UIKeyboard
Я бы попытался объяснить это здесь, но большая часть этого кода, чтобы посмотреть на это, не будет легко вписываться здесь
Если вы заранее знаете количество вводимых номеров (например, 4-значный PIN-код), вы можете автоматически отклонить после 4 нажатий клавиш, согласно моему ответу на этот аналогичный вопрос:
увольнение цифровой клавиатуре
в этом случае нет необходимости в дополнительной кнопке done.
мы также можем сделать "пользователь коснулся где-то еще" решение еще проще, если мы просто скажем нашему виду контроллера, чтобы закончить редактирование:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; [self.view endEditing:YES]; //YES ignores any textfield refusal to resign }
... предполагая, что" прикосновение в другом месте отклоняет клавиатуру " является желательным поведением для любых других редактируемых полей в представлении.
Если у вас есть несколько числовых полей, я предлагаю подкласс UITextField для создания NumericTextField, который всегда отображает цифровую клавиатуру с кнопкой Готово. Затем просто свяжите свои числовые поля с этим классом в Построителе интерфейса, и вам не понадобится никакой дополнительный код ни в одном из ваших контроллеров представления. Ниже приведен класс Swift 3.0, который я использую в 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() } }
для Swift 2.2 я использую это
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() }
все эти реализации о поиске вида клавиатуры и добавлении кнопки "Готово" в 3-й строке (именно поэтому кнопка.y = 163 B/C высота клавиатуры составляет 216) являются хрупкими, потому что iOS продолжает изменять иерархию представлений. Например, ни один из вышеперечисленных кодов не работает для iOS9.
Я думаю, что безопаснее просто найти самый верхний вид, с помощью [[[UIApplication sharedApplication] windows] lastObject], и просто добавьте кнопку в левом нижнем углу его, doneButton.frame = CGRectMake(0, SCREEN_HEIGHT-53, 106, 53);// портретный режим
Swift 2.2 / я использовал ответ Dx_. Тем не менее, я хотел эту функциональность на всех клавиатурах. Поэтому в моем базовом классе я поставил код:
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) } } }
тогда просто вызовите addDoneButtonForTextFields на себя.вид.subviews в viewDidLoad (или willDisplayCell при использовании табличного представления), чтобы добавить кнопку Готово для всех клавиатур.