【问题标题】:How to add a 'Done' button to numpad keyboard in iOS如何在 iOS 的数字键盘上添加“完成”按钮
【发布时间】:2013-12-10 03:12:33
【问题描述】:

所以,小键盘键盘默认没有“完成”或“下一步”按钮,所以我想添加一个。在 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 的解决方案,所以我应该以不同的方式执行此操作吗?

编辑:感谢工具栏人员的所有建议,但我宁愿不走那条路,因为我的空间很差(而且有点难看)。

【问题讨论】:

标签: ios iphone cocoa-touch uitextfield uikit


【解决方案1】:

更安全的方法是使用UIToolBarDone 按钮作为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)
}

【讨论】:

  • 我可能不得不这样做。我真的不喜欢它占用的空间。
  • @GeorgeMcKibbin:这里的空间不应该是问题,因为它只会在您输入时占用该空间。此外,在我看来,这种方法比弄乱通常 Apple 不喜欢的键盘要好得多。
  • 执行此操作时,我只会在屏幕最底部看到工具栏,而键盘不再出现。想法?
  • 很好的答案,只有一个花絮,arrayWithObjects 被暗中弃用,取而代之的是文字:[NSArray arrayWithObjects:doneButton, nil] => @[doneButton]
  • 来自 iOS 8.0 的 UIBarButtonItemStyleBordered 已弃用 UIBarButtonItemStyleDoneUIBarButtonItemStylePlain
【解决方案2】:

更简单的方法:

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 的有用库,它已经拥有开箱即用的工具栏:

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

【讨论】:

  • 在我看来,您在一年前的 Bhavin 的答案中添加了一个 flex bar 按钮作为新答案,所以我可以看到为什么有人反对它。也许我在这里也错过了什么?
  • 是的,我不使用initWithTitle:@"Done",而是使用initWithBarButtonSystemItem:UIBarButtonSystemItemDone。这将返回标准的 Apple 完成栏按钮。而且,它已经本地化了
  • 这应该作为对先前正确答案 IMO 的改进(评论)添加,或者期待反对票。新的答案应该涉及对原始问题的不同方法,而不是对现有问题的改进。尽管如此,还是感谢您的改进。 ;-)
  • 不,我不这么认为。注释不应该用于编写代码:)
【解决方案3】:

这是在 iOS7 数字键盘中投射完成按钮的简单方法。在下面 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)

【讨论】:

  • 谢谢,这就是我想要的 :) 不幸的是,如果屏幕上已经有一个键盘,然后您切换到需要数字键盘的字段,则不会调用 keyBoardWillShow。但是谢谢,朝着正确的方向迈出了一步哈哈。
  • SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO 为什么不是 NSFoundationVersionNumber>NSFoundationVersionNumber_iOS_6_0?我测试了一下,NSFoundationVersionNumber_iOS_5_0 更好
  • dispatch_async 不是在这里侵入键盘的最可靠方法。 :(
  • 在 iOS8 中这个完成按钮没有隐藏,在关闭键盘后。
  • 这个答案,虽然很聪明,但注定会失败。
【解决方案4】:

因为我必须翻译它,所以只是在上面的答案上使用 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)
}

【讨论】:

    【解决方案5】:

    您可以在键盘的输入附件视图中添加一个按钮

    myTextField.inputAccessoryView =_inputView;
    

    输入附件视图是一个始终出现在键盘上并使用[textfield resignFirstResponder] 关闭的视图

    done 放在输入视图上并执行文本字段的 resign first responder。

    【讨论】:

      【解决方案6】:
      1. 将控制器注册到通知中
      - (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];
      }
      
      1. 别忘了从通知中心移除控制器
      - (void)viewWillDisappear:(BOOL)animated {
          [super viewWillDisappear:animated];
          [self.view endEditing:YES];
          [[NSNotificationCenter defaultCenter] removeObserver:self];
      }
      
      1. 实现键盘通知处理程序
      - (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];
      }
      
      1. 实现完成按钮操作
      - (void)doneButton:(id)sender {
          // add needed implementation
          [self.view endEditing:YES]; 
      }
      
      

      【讨论】:

      • 我实现的答案与我必须做的非常相似。谢谢。但是当键盘显示时,按钮不会作为动画对象出现。
      【解决方案7】:

      随便用

      yourTextField.inputAccessoryView

      希望你能帮忙

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

          键盘视图可以找到hasPrefix:@"UIKeyboard",按钮不能作为子视图添加。这是我的解决方案:enter link description here

          【讨论】:

            猜你喜欢
            • 2022-11-01
            • 2016-03-19
            • 2021-07-20
            • 2012-04-22
            • 2011-05-20
            • 2023-03-15
            • 2010-10-09
            • 2013-09-21
            • 1970-01-01
            相关资源
            最近更新 更多