【问题标题】:iPhone keyboard toolbar classiPhone 键盘工具栏类
【发布时间】:2012-02-09 00:31:15
【问题描述】:

我按照http://www.youtube.com/watch?v=YgeuauhsDhQ 的教程在键盘上方创建了上一个、下一个、完成按钮,该按钮随键盘向上滑动。

但是,我注意到他正在对特定视图执行此操作,我不想将其复制/粘贴到具有文本字段的每个视图中。我尝试为此开设一个课程,但后来意识到他根据当前焦点所在的字段放弃了键盘。

是否有人知道已经有一个类,所以我不必为每个具有文本字段的视图控制器创建它?或者知道如何修改他的版本以作为可以导入到视图控制器中的类来工作?

抱歉,我对 iPhone 开发有点陌生。

//KeyboardToolbar.h

#import <Foundation/Foundation.h>

@interface KeyboardToolbar : NSObject
{
    UIToolbar *keyboardToolbar;
}

@property (nonatomic, retain) UIToolbar *keyboardToolbar;

-(void)resignKeyboard:(id)sender;
-(void)previousField:(id)sender;
-(void)nextField:(id)sender;
@end

//KeyboardToolbar.m
#import "KeyboardToolbar.h"


@implementation KeyboardToolbar

@synthesize keyboardToolbar;

- (void)loadToolbar
{
    if (keyboardToolbar == nil) {

        keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 44.0)];

        UIBarButtonItem *previousButton = [[UIBarButtonItem alloc] initWithTitle:@"Previous" style:UIBarButtonItemStyleBordered target:self action:@selector(previousField:)];

        UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" style:UIBarButtonItemStyleBordered target:self action:@selector(nextField:)];

        UIBarButtonItem *extraSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(resignKeyboard:)];

        [keyboardToolbar setItems:[[NSArray alloc] initWithObjects:previousButton, nextButton, extraSpace, doneButton, nil]];
    }
}

- (void)resignKeyboard:(id)sender
{
    //Resign the keyboard here? I would need to get the element with the keyboard then hide it.
}

@end

我如何使这个类更加动态,以便我可以在我的所有视图中使用它,而只需很少复制/粘贴到每个控制器中。

【问题讨论】:

    标签: iphone objective-c ios5 xcode4.2


    【解决方案1】:

    我也是这方面的新手,但我想我可以提供帮助。我做了类似的事情。我设置了一个辅助对象来充当用户当前正在与之交互的任何视图控制器的委托。您将编写代码以显示工具栏。您将在助手(委托)类的 .m 文件中实现这些方法。将您的助手类添加为 UIKeyboardDidShowNotification 的观察者。因此,在我的 UIViewControllers 的 viewDidLoad 中,我将委托设置为我的助手对象。然后,当当前视图控制器上出现键盘时,通知将发送到委托(帮助对象)。 这里有一个小代码来澄清: 在辅助对象的 init 方法中:

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

    然后,在您的辅助对象的 .m 文件中,在 keyboardWasShown: 中,调用 [self makeToolbar] 或任何您调用的方法。很抱歉冗长。就像我说的,我很新,但我希望这会有所帮助。

    编辑:所以我做了一个简单的小测试/插图。这是我的 ViewController 类的 .h。这是将包含 UITextFields 的 ViewController,这两者都会调出键盘并通过委托方法向其中添加工具栏。对于冗长的回复感到抱歉,但我认为向您提供所有对我有用的东西是最有用的。

    #import <UIKit/UIKit.h>
    #import "TextFieldDelegate.h"
    
    @interface ViewController : UIViewController <UITextFieldDelegate> {
        //Outlets for 2 UITextFields, added in IB. Selecting either will add the toolbar to your keyboard as long as the delegate is assigned and the methods in the delegate are implemented as shown. 
        IBOutlet UITextField *myTextField;
        IBOutlet UITextField *myOtherTextField;
    
        //we'll need to set the delegate for this class, so go ahead and declare a variable and make it a property (and synthesize it in the .m). 
        id delegate;
    }
    
    @property (nonatomic, strong) id delegate;
    
    @end
    

    ViewController.m:

    @implementation ViewController
    @synthesize delegate;
    
    //removed method stubs and only left my modifications to the template. 
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        //create an instance of your delegate class and set it as the view controller's delegate. 
        //the text fields need their parent as the delegate, and the parent in turn assigns the helper class as its delegate. 
        //really this is the whole point, that you can just assign delegates to your view
        //controllers and text fields and they can all access the one method implementation
        //instead of each having to implement it separately themselves. 
        [myTextField setDelegate:self];
        [myOtherTextField setDelegate:self];
        TextFieldDelegate *myDelegate = [[TextFieldDelegate alloc] init];
        [self setDelegate: myDelegate];
    
        //set the delegate's currentViewController property so that we can add a subview to this View. 
        [delegate setCurrentViewController:self];
    
    }
    
    - (void)textFieldDidBeginEditing:(UITextField *)textField {
        //set the delegate's current text field property so that we can resignFirstResponder. 
        [delegate setCurrentTextField:textField];
    }
    

    @结束

    现在是委托类: TextFieldDelegate.h:

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface TextFieldDelegate : UIViewController <UITextFieldDelegate> {
        UIViewController *currentViewController;
        UITextField *currentTextField;
        UIToolbar *keyboardToolbar;
        CGSize kbSize;
    }
    
    - (void)loadToolbar;
    
    @property (nonatomic, strong) UIViewController *currentViewController;
    @property (nonatomic, strong) UITextField *currentTextField;
    
    @end
    

    以及委托的实现: TextFieldDelegate.m:

    #import "TextFieldDelegate.h"
    
    @implementation TextFieldDelegate
    
    //synthesize properties so that View Controllers can set them as needed. 
    @synthesize currentViewController, currentTextField;
    
    - (id)init {
        self = [super init];
        if (self) {
            //register for the keyboard did show notification
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWasShown:)
                                                         name:UIKeyboardDidShowNotification
                                                       object:nil];
        }
        return self;
    }
    
    - (void)keyboardWasShown:(NSNotification *)aNotification {
        //get the keyboard size for positioning the toolbar. (depending on where you want it, I guess, I was just imagining it directly above the keyboard. 
        NSDictionary *info = [aNotification userInfo];
        kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        //call the method to make the toolbar appear. 
        [self loadToolbar];
    }
    
    - (void)loadToolbar
    {
        if (keyboardToolbar == nil) {
    
            //setting the position of the toolbar. 
            CGRect frameRect = self.view.frame;
            frameRect.size.height -= kbSize.height;
    
            keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, frameRect.size.height - 60.0, 320.0, 60.0)];
    
            //your code for toolbar setup. 
            UIBarButtonItem *previousButton = [[UIBarButtonItem alloc] initWithTitle:@"Previous" style:UIBarButtonItemStyleBordered target:self action:@selector(previousField:)];
    
            UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" style:UIBarButtonItemStyleBordered target:self action:@selector(nextField:)];
    
            UIBarButtonItem *extraSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    
            UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(resignKeyboard:)];
    
            [keyboardToolbar setItems:[[NSArray alloc] initWithObjects:previousButton, nextButton, extraSpace, doneButton, nil]];
    
            //this line sends a message to the currently active view controller, telling it to add as a subview the toolbar that we have just created. 
            [[currentViewController view] addSubview:keyboardToolbar];
        }
    }
    
    - (void)resignKeyboard:(id)sender {
        [currentTextField resignFirstResponder];
        [keyboardToolbar removeFromSuperview];
        //set the toolbar to nil so that when you touch the other text field, it will build      again. 
        keyboardToolbar = nil;
    }
    
    @end
    

    原来如此。就像我说的,我也是新人。但我希望这会有所帮助。

    @jostster 编辑:哦,如果您将对自定义委托方法 loadToolbar 的调用移动到 ViewController 的 textFieldDidBeginEditing 方法中,它会起作用。在 ViewController.m 中

    - (void)textFieldDidBeginEditing:(UITextField *)textField {
        //set the delegate's current text field property so that we can resignFirstResponder. 
        [delegate setCurrentTextField:textField];
        [delegate loadToolbar];
    }
    

    然后您可以在委托实现中从keyboardWasShown 中删除[self loadToolbar] 调用。

    编辑:要让你的下一个和上一个按钮工作,首先给你的委托一个属性:NSArray *textFieldArray。然后,在您的视图控制器中,创建一个文本字段数组(我们将其称为 tfArray),然后执行 [delegate setTextFieldArray:tfArray];然后实现你的 previousField: 和 nextField: 方法是这样的:

    - (void)previousField:(id)sender {
        //get the index in the array of your currently active textField
        int activeIndex = [textFieldArray indexOfObject:currentTextField];
        //make sure you're not going to try to access an empty spot in the array
        if (activeIndex > 0) {
        UITextField *previousField = [textFieldArray objectAtIndex:activeIndex - 1];
        [previousField becomeFirstResponder];
        }
    }
    //same again but with a plus sign
    - (void)nextField:(id)sender {
        int activeIndex = [textFieldArray indexOfObject:currentTextField];
    
        if (activeIndex < 1) {
        UITextField *nextField = [textFieldArray objectAtIndex:activeIndex + 1];
        [nextField becomeFirstResponder];
        }
    }
    

    可能有一种更简洁的方法可以做到这一点,但代码量太少了,我觉得输入两次并不是什么大不了的事。这就是它的要点,如果你有一大堆文本字段要前进,你只想说:

    if (activeIndex < [textFieldArray count]) {
    //advance to the next textField
    }
    

    【讨论】:

    • 如果您能提供帮助,我编辑了我的 OP 以包含代码。
    • 谢谢!此外,当您进行更新时,请确保您发布带有 @ 和您想要引起注意的人名的评论,以便我们可以看到我们有更新。一个问题是,在 youtube 视频中,工具栏会随着键盘向上滑动,并且可以改变方向。我注意到这个也不行。
    • 好的,我通过keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, 44.0)]; 而不是[[currentViewController view] addSubview:keyboardToolbar]; 使用currentTextField.inputAccessoryView = keyboardToolbar; 让它工作,但是我必须单击该字段,然后单击另一个字段以显示工具栏。你知道如何让它在第一次点击文本字段时起作用吗?
    • 您需要对原始帖子发表评论,或者使用 @ 用户名发布帖子以供他们查看消息。不在实际帖子中。您的编辑成功了!感谢您的所有帮助!
    • 下一个和上一个呢?
    【解决方案2】:

    我在 Github 上发现这个项目可能有用。

    https://github.com/rexfinn/RFKeyboardToolbar

    【讨论】:

      猜你喜欢
      • 2012-03-24
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 2019-01-05
      • 1970-01-01
      相关资源
      最近更新 更多