如何在iOS中的小键盘上添加“完成”按钮


84

因此,小键盘默认情况下不带有“完成”或“下一步”按钮,因此我想添加一个。在iOS 6及以下版本中,有一些技巧可以在键盘上添加按钮,但它们似乎在iOS 7中不起作用。

首先我订阅显示通知的键盘

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

然后,当键盘显示时,我尝试添加一个按钮:

- (void)keyboardWillShow:(NSNotification *)note 
{
    // create custom button
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem];
    doneButton.frame = CGRectMake(0, 50, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setTitle:@"Done" forState:UIControlStateNormal];
    [doneButton addTarget:self action:@selector(dismissKeyboard) 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 view found; add the custom button to it
        if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
        [keyboard addSubview:doneButton];
    }
}

但是for循环不会运行,因为它找不到任何子视图。有什么建议么?我找不到适用于iOS7的任何解决方案,所以我应该采用其他方法吗?

编辑:感谢对工具栏家伙的所有建议,但是我不愿意走那条路,因为我的空间很有限(而且很丑)。


尝试过此帖子?neoos.ch/blog/…–
Anil

@Anil苹果禁止使用这种自定义UIKeyboard的方式。
βhargavḯ

检查UIKeyboardDidShowNotification。
Praveen Matanam


2
我真的不想添加工具栏,我想将按钮放在键盘上。
乔治·麦基宾

Answers:


26

这是在iOS7 num-keypad中投影完成按钮的简单方法。在下面的UITextField委托方法中,为键盘显示添加一个通知。

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

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];
}

现在实现如下方法keyboardWillShow。在这里,我们需要特别注意iOS7。

- (void)keyboardWillShow:(NSNotification *)note {
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:@"doneButtonNormal.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:@"doneButtonPressed.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIView *keyboardView = [[[[[UIApplication sharedApplication] windows] lastObject] subviews] firstObject];
        [doneButton setFrame:CGRectMake(0, keyboardView.frame.size.height - 53, 106, 53)];
        [keyboardView addSubview:doneButton];
        [keyboardView bringSubviewToFront:doneButton];

        [UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]-.02
                              delay:.0
                            options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
                         animations:^{
                             self.view.frame = CGRectOffset(self.view.frame, 0, 0);
                         } completion:nil];
    });
}else {
    // locate keyboard view
    dispatch_async(dispatch_get_main_queue(), ^{
        UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
        UIView* keyboard;
        for(int i=0; i<[tempWindow.subviews count]; i++) {
            keyboard = [tempWindow.subviews objectAtIndex:i];
            // keyboard view found; add the custom button to it
            if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
                [keyboard addSubview:doneButton];
        }
    });
  }
}

现在将此宏添加到合适的标头中以检测SYSTEM_VERSION

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)


1
谢谢,这就是我想要的:)不幸的是,如果屏幕上已经有键盘,然后您切换到需要数字键盘的字段,则不会调用keyBoardWillShow。但是,谢谢,朝着正确方向迈出了一步。
乔治·麦基宾

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO为什么不选择NSFoundationVersionNumber> NSFoundationVersionNumber_iOS_6_0?我测试了一下,NSFoundationVersionNumber_iOS_5_0更好
govo

dispatch_async在这里不是侵入键盘的最可靠方法。:(
pronebird

7
在iOS8中,此完成按钮不会隐藏,在关闭键盘后。
Hemant Chittora 2014年

2
这个答案虽然很聪明,但肯定会失败。
SwiftArchitect

187

更安全的方法是将UIToolBarwith DoneButton用作inputAccessoryView


样例代码:

UIToolbar *keyboardDoneButtonView = [[UIToolbar alloc] init];
[keyboardDoneButtonView sizeToFit];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
                                                               style:UIBarButtonItemStyleBordered target:self
                                                              action:@selector(doneClicked:)];
[keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];
txtField.inputAccessoryView = keyboardDoneButtonView;

您的-doneClicked方法应如下所示:

- (IBAction)doneClicked:(id)sender
{
    NSLog(@"Done Clicked.");
    [self.view endEditing:YES];
}

Swift示例代码:

let keyboardDoneButtonView = UIToolbar.init()
keyboardDoneButtonView.sizeToFit()
let doneButton = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.Done, 
                                                   target: self, 
                                                   action: Selector("doneClicked:")))    

keyboardDoneButtonView.items = [doneButton]
textFieldInput.inputAccessoryView = keyboardDoneButtonView

您的-doneClicked方法应如下所示:

func doneClicked(sender: AnyObject) {
  self.view.endEditing(true)
}

我可能最终不得不这样做。我真的不喜欢占用多少空间。
乔治·麦基宾

3
@GeorgeMcKibbin:这里的空间不应该成为问题,因为只有在您键入时才会占用该空间。而且,根据我的观点,这种方法远比弄乱通常苹果公司不喜欢的Keyboard更好。
Bhavin 2013年

这样做时,我只会在屏幕的最底部看到工具栏,并且不再显示键盘。有什么想法吗?
克里斯

很好的答案,只有一个小窍门,arrayWithObjects毫不掩饰地推荐使用常量:[NSArray arrayWithObjects:doneButton,nil] => @ [doneButton]
Austin

1
iOS 8.0UIBarButtonItemStyleBordered中的版本已弃用UIBarButtonItemStyleDoneUIBarButtonItemStylePlain
Nazir

131

更简单的方法:

Swift 3.0及更高版本

func addDoneButton() {
    let keyboardToolbar = UIToolbar()
    keyboardToolbar.sizeToFit()
    let flexBarButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
        target: nil, action: nil)
    let doneBarButton = UIBarButtonItem(barButtonSystemItem: .done,
        target: view, action: #selector(UIView.endEditing(_:)))
    keyboardToolbar.items = [flexBarButton, doneBarButton]
    textField.inputAccessoryView = keyboardToolbar
}

Swift 2.3及以下版本

func addDoneButton() {
    let keyboardToolbar = UIToolbar()
    keyboardToolbar.sizeToFit()
    let flexBarButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace,
        target: nil, action: nil)
    let doneBarButton = UIBarButtonItem(barButtonSystemItem: .Done,
        target: view, action: #selector(UIView.endEditing(_:)))
    keyboardToolbar.items = [flexBarButton, doneBarButton]
    textField.inputAccessoryView = keyboardToolbar
}

目标C

- (void)addDoneButton {
    UIToolbar* keyboardToolbar = [[UIToolbar alloc] init];
    [keyboardToolbar sizeToFit];
    UIBarButtonItem *flexBarButton = [[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
    target:nil action:nil];
    UIBarButtonItem *doneBarButton = [[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemDone
    target:self.view action:@selector(endEditing:)];
    keyboardToolbar.items = @[flexBarButton, doneBarButton];
    self.textField.inputAccessoryView = keyboardToolbar;
}

编辑:

我创建了一个名为DCKit的有用的库,该库已经开箱即可使用工具栏:

在iOS键盘上方完成工具栏(使用DCKit库)

它还具有许多其他很酷的功能。


1
在我看来,您从1年前开始在Bhavin的答案中添加了一个弹性栏按钮作为新答案,因此我可以理解为什么有人对此投了反对票。也许我也想念这里吗?
Mark McCorkle 2014年

2
是的,我不使用initWithTitle:@"Done",而是使用initWithBarButtonSystemItem:UIBarButtonSystemItemDone。这将返回标准的Apple的完成栏按钮。而且,它已经本地化了
Andrey Gordeev 2014年

3
这应该作为对以前的正确答案IMO的改进(注释)而添加,或者应予以否决。新答案应包含对原始问题的不同方法,而不是对现有问题的改进。但是,谢谢您的改进。;-)
Mark McCorkle 2014年

4
不,我不这么认为。注释不应该用于编写代码:)
Andrey Gordeev 2014年

13

由于我不得不翻译Swift版本,因此仅基于上述答案即可:

   @IBOutlet weak var numberTextField: UITextField!

    override func viewDidLoad() {
        addDoneButtonTo(numberTextField)
    }

    // MARK: Done for numberTextField

    private func addDoneButtonTo(textField: UITextField) {
        let flexBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
        let doneBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "didTapDone:")
        let keyboardToolbar = UIToolbar()
        keyboardToolbar.sizeToFit()
        keyboardToolbar.items = [flexBarButton, doneBarButton]
        textField.inputAccessoryView = keyboardToolbar
    }

    func didTapDone(sender: AnyObject?) {
        numberTextField.endEditing(true)
    }

3

您可以使用

myTextField.inputAccessoryView = _inputView;

输入附件视图是始终位于键盘上方并随键盘一起关闭的视图 [textfield resignFirstResponder]

放在done输入视图上,并对文本字段执行resignfirst响应器。



2
enter code here

1. register the controller to the notification

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // Keyboard events
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

2. don't forget to remove the controller from the notification centre

-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.view endEditing:YES];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

3. implement keyboard notification handlers

- (void)keyboardWillShow:(NSNotification *)notification {

// create custom button
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 107, 106, 53);
    [doneButton setTitle:@"Done" forState:UIControlStateNormal];
    [doneButton addTarget:self  action:@selector(doneButton:)forControlEvents:UIControlEventTouchUpInside];

// save the reference to the button in order to use it in keyboardWillHide method
   self.donekeyBoardBtn = doneButton;

// to my mind no need to search for subviews
   UIWindow *windowContainigKeyboard = [[[UIApplication sharedApplication] windows]  lastObject];
   [windowContainigKeyboard addSubview:self.donekeyBoardBtn];
   self.donekeyBoardBtn.frame = CGRectMake(0., CGRectGetHeight(w.frame) -  CGRectGetHeight(self.donekeyBoardBtn.frame), CGRectGetWidth(self.donekeyBoardBtn.frame), CGRectGetHeight(self.donekeyBoardBtn.frame));
}

- (void)keyboardWillHide:(NSNotification *)notification {

    [self.donekeyBoardBtn removeFromSuperview];
}

4. implement done button action

- (void)doneButton:(id)sender{
   // add needed implementation
      [self.view endEditing:YES]; 
}

我实现的答案与我必须做的非常相似。谢谢。但是,在键盘显示时,按钮不是动画对象。
Arpit B Parekh

1

您确实需要检测您是在手机还是iPad上,因为iPad在“数字”键盘上实现了返回键


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.