如何在iPhone OS 4上的数字键盘上显示“完成”按钮?

24

我想在iPhone数字键盘上添加一个“完成”按钮,底部左侧甚至有一个方便的空间可以放置该按钮。

之前,我使用了与问题584538Luzian Scherrer的优秀博客文章中描述的类似技巧,但这在iOS 4中停止工作。我可以通过创建自定义inputView来实现它,但我更愿意扩展Apple的键盘而不是编写自己的键盘。

是否有一种新的方法可以向标准键盘添加视图?是否有人发布了用于此的OSS inputView?还有其他方法吗?

7个回答

86

您可以添加一个带有“应用”和“取消”按钮的,并使用它来关闭数字键盘。

inputAccessoryView

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];

    numberToolbar.items = [NSArray arrayWithObjects:
       [[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)],
       nil];

    numberTextField.inputAccessoryView = numberToolbar;
}

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

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

谢谢!提示:您甚至不需要调用 sizeToFit - s1m0n
谢谢Luda,这个帮了我很大的忙 :) - Himanshu padia
2014年,我刚刚从这个绝妙的答案中移除了已弃用的typedef风格。 - Fattie

6
我已经解决了这个问题。在这里可以查看代码:http://gist.github.com/454844 存在两个问题:
  1. UIKeyboardWillShowNotification 在键盘视图存在之前被发送,但是如果你将代码安排在下一个运行循环中运行,它们就会存在。因此,您不必担心 DidShow,这在视觉上不太令人愉快。

  2. 在 iOS 4 上,UIKeyboard 视图位于视图层次结构的其他位置。


我更喜欢你的解决方案,而不是使用inputAccesoryView。太棒了!谢谢分享! - Mathieu

3

Luzian Scherrer的博客文章中描述的技术在iOS 4.0中确实有效

我添加键盘按钮的代码失败了,因为它是从textFieldDidBeginEditing:委托方法中调用的,在4.0中,该方法在键盘窗口的子视图创建之前被调用。我通过在观察到UIKeyboardWillShowNotification时调用我的代码来解决这个问题,这发生得足够晚。


这在4.2上不起作用。 - WrightsCS
1
我也遇到了4.2的同样问题。为什么这么复杂?!?!苹果?!? - AYBABTU
1
在我的应用程序中,我有两个文本字段。一个将显示数字键盘,另一个文本字段将显示普通字母键盘。我只想为数字键盘添加“完成”按钮。如何防止它出现在常规键盘上? - Satyam

3

2
我已将此问题提交给苹果作为一个bug。Interface Builder允许开发人员为Number Pad键盘类型指定Return Key类型。Bug编号8759674。
苹果回复说,该问题曾被记录为Bug ID#5885964,并关闭了8759674。

1

您可以使用此键盘通知代码在数字键盘上创建完成按钮。您只需在本地下载 done.png 图像即可。

在 .h 文件中

  {     //Keyboard Hide
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;

在 .m 文件中

@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:@"NumberDone.png"];
    self.numberPadDoneImageHighlighted = [UIImage imageNamed:@"NumberDone.png"];
} else {        
    self.numberPadDoneImageNormal = [UIImage imageNamed:@"NumberDone.png"];
    self.numberPadDoneImageHighlighted = [UIImage imageNamed:@"NumberDone.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 setTitle:@"Return" forState:UIControlStateNormal];
[self.numberPadDoneButton setFont:[UIFont boldSystemFontOfSize:18]];
[self.numberPadDoneButton setTitleColor:[UIColor colorWithRed:77.0f/255.0f green:84.0f/255.0f blue:98.0f/255.0f alpha:1.0] forState:UIControlStateNormal];  

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

1
我已经创建了一个版本,以启用数字键盘的横向版本... 插入Luzian Scherrer博客中描述的技术,并将两个额外的png(此处未包含)和“isLandscape”布尔值添加到“didRotateFromInterfaceOrientation”方法中。
    @interface AlarmController ()
    {
        CGRect doneButtnRectVert;
        CGRect doneButtnRectHorz;
        CGRect doneButtnRect;
        UIImage* DoneUpVert;
        UIImage* DoneDownVert;
        UIImage* DoneUpHorz;
        UIImage* DoneDownHorz;
        UIImage* DoneUp;
        UIImage* DoneDown;
        UIButton *oldDoneButton;
    }
    @end

    //---------------------------------------------------------------------------
    - (void)viewDidUnload
    {
    NSLog(@"viewDidUnload  AlarmController");
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                      name:UIKeyboardDidShowNotification object:nil];

        [super viewDidUnload];
    }

    //---------------------------------------------------------------------------
    - (void)addButtonToKeyboard
    {
    NSLog(@"addButtonToKeyboard  AlarmController");
        if (isLandscape)
        {
            doneButtnRect = doneButtnRectHorz;
            DoneUp = DoneUpHorz;
            DoneDown = DoneDownHorz;
        } else {
            doneButtnRect = doneButtnRectVert;
            DoneUp = DoneUpVert;
            DoneDown = DoneDownVert;
        }

        UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
        doneButton.frame = doneButtnRect;
        doneButton.adjustsImageWhenHighlighted = NO;
        [doneButton setImage:DoneUp forState:UIControlStateNormal];
        [doneButton setImage:DoneDown forState:UIControlStateHighlighted];

        [doneButton addTarget:self action:@selector(done:) forControlEvents:UIControlEventTouchUpInside];

        UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
        UIView* keyboard;
        for(int i=0; i<[tempWindow.subviews count]; i++)
        {
            keyboard = [tempWindow.subviews objectAtIndex:i];
            if([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES)
            {
                if (oldDoneButton) [oldDoneButton removeFromSuperview];
                [keyboard addSubview:doneButton];
            }
        }
        oldDoneButton = doneButton;
    }

    //---------------------------------------------------------------------------
    - (void)keyboardDidShow:(NSNotification *)note
    {
    NSLog(@"keyboardDidShow  AlarmController");
        [self addButtonToKeyboard];
    }

    #pragma mark -
    #pragma mark meaty area...

//---------------------------------------------------------------------------
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(@"textFieldDidEndEditing AlarmController");
    oldDoneButton = nil;
}

    //---------------------------------------------------------------------------
    - (void)viewDidLoad
    {
    NSLog(@"viewDidLoad  AlarmController");
        [super viewDidLoad];
        doneButtnRectVert = CGRectMake(0, 163, 106, 53);
        doneButtnRectHorz = CGRectMake(0, 122, 159, 40);
        DoneUpVert = [UIImage imageNamed:@"DoneUp3.png"];
        DoneDownVert = [UIImage imageNamed:@"DoneDown3.png"];
        DoneUpHorz = [UIImage imageNamed:@"DoneUpHor.png"];
        DoneDownHorz = [UIImage imageNamed:@"DoneDnHor.png"];

        doneButtnRect = doneButtnRectVert;
        DoneUp = DoneUpVert;
        DoneDown = DoneDownVert;
        oldDoneButton = nil;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接