iPhone键盘工具栏类

时间:2012-01-12 17:53:28

标签: iphone objective-c ios5 xcode4.2

我在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

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

2 个答案:

答案 0 :(得分:3)

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

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

然后,在helper对象的.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];
}

@end

现在这里是委托类: 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),然后执行[委托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
}

答案 1 :(得分:0)

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

https://github.com/rexfinn/RFKeyboardToolbar