4

In my app I have a UITextField on the navigationController toolbar.

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) NSArray *toolBarButtonItems;
@property (nonatomic,strong) UITextField *textField;
@property (nonatomic,strong) UITextField *textField2;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 0, 60, 40)];
    self.textField.delegate = self;
    self.textField.borderStyle = UITextBorderStyleRoundedRect;

    UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.textField];

    self.toolBarButtonItems = @[flexibleSpace,barButtonItem,flexibleSpace];

    self.toolbarItems = self.toolBarButtonItems;
    self.navigationController.toolbar.barTintColor = [UIColor blueColor];

    [self.navigationController setToolbarHidden:NO animated:NO];
}

When the textField is clicked the keyboard opens up and I create a new inputAccessoryView toolbar with another textField.

-(UIToolbar *)addToolBar{
    UIToolbar *toolbar = [[UIToolbar alloc]initWithFrame:self.navigationController.toolbar.frame];
    toolbar.barTintColor = [UIColor darkGrayColor];

    self.textField2 = [[UITextField alloc]initWithFrame:CGRectMake(0, 0, 60, 40)];
    self.textField2.delegate = self;
    self.textField2.borderStyle = UITextBorderStyleRoundedRect;

    UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc]initWithCustomView:self.textField2];

    [toolbar setItems:@[flexibleSpace,barButtonItem,flexibleSpace]];
    return toolbar;
}

The idea is to change the firstResponder to the textField on the inputAccessoryView so this way I can see what I'm editing. The reason I am doing this is cause I can't scroll the Navigation toolbar up past the keyboard and I want to see the text that I am editing.

-(void)textFieldDidBeginEditing:(UITextField *)textField{
    textField.inputAccessoryView = [self addToolBar];

    if(self.textField2.isFirstResponder != NO){
        [self.textField2 becomeFirstResponder];
    }
}

It doesn't seem to be working when I click on the textField in the navigationController toolbar. The new inputAccessoryView toolbar shows up over the keyboard but I can't edit the field because the responder doesn't seem to be changing. The return key doesn't work either. I have to hit it twice in order to close the keyboard and when I do the text doesn't match up between the two text fields.

-(BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    self.textField.text = self.textField2.text;
    return YES;
}
denvdancsk
  • 3,033
  • 2
  • 26
  • 41

1 Answers1

1

I got it to work like this:

#import "KJMViewController.h"

@interface KJMViewController ()

@property (strong, nonatomic) UITextField *textField1;
@property (strong, nonatomic) UITextField *textField2;

@end

@implementation KJMViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.textField1 = [[UITextField alloc]initWithFrame:CGRectMake(30, 7, 260, 30)];
    self.textField1.borderStyle = UITextBorderStyleRoundedRect;
    self.textField1.delegate = self;
    UIToolbar *navToolbar = self.navigationController.toolbar;
    [navToolbar addSubview:self.textField1];

    UIToolbar *toolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
    self.textField2 = [[UITextField alloc]initWithFrame:CGRectMake(30, 7, 260, 30)];
    self.textField2.borderStyle = UITextBorderStyleRoundedRect;
    self.textField2.delegate = self;
    [toolbar addSubview:self.textField2];
    self.textField1.inputAccessoryView = toolbar;
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(firstRes:) name:UIKeyboardDidShowNotification object:nil];
}

- (void)firstRes:(id)sender
{
    [self.textField2 becomeFirstResponder];
}

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

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if (textField == self.textField2) {
        self.textField1.text = self.textField2.text;
    }
    [textField resignFirstResponder];
    [self.textField1 resignFirstResponder];
    return YES;
}

- (void)viewDidDisappear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter]removeObserver:self forKeyPath:UIKeyboardDidShowNotification];
    [super viewDidDisappear:animated];
}

@end

Here's what's happening in viewDidLoad:

  • Initialise toolbar and textField2
  • Set the inputAccessory for textField1 (the one hidden by the keyboard) here so it's ready to become firstResponder

Then in the viewDidAppear method:

Sign up for a notification that's sent when the keyboard is shown. You'll then write some code in the "firstRes" method to make textField2 the firstResponder. You need to make it the firstResponder using this notification because you know that it's in the view hierarchy by this time, which means it's able to become firstResponder. Calling it in the -(void)textFieldDidBeginEditing:(UITextField *)textField seems to fire it before textField2 comes on screen, meaning that it can't become firstResponder. We sign up for it in the viewDidAppear method because we only want to get the notification if we're on screen.

After textField2 resignsFirstResponder, textField1 becomes first responder again, so you have to call resignFirstResponder twice in the textFieldShouldReturn method.

Also, if we leave the screen, we need to remove ourself as an observer of the keyboard notification in the viewDidDisappear method.

Here's a link to the project I made in Xcode so you can see how it works:

https://github.com/kylejm/UIToolBar-UITextView

kylejs
  • 1,128
  • 11
  • 25
  • Doesn't work. You have also got 4 text fields properties in your code now. Why do you need the other two text fields? You've only declared two properties yet you're using 4 in your code (textField,textField1,textField2,inputTF). Also, why would you use iVars in iOS7? – denvdancsk Dec 12 '13 at 14:40
  • Oh, it does for me. I didn't mean to write "textField" and "inputTF" - I wrote the code late at night and just overlooked them when changing the property names to then ones you're using whilst writing my answer. Properties are iVars, they are just used to have Xcode automatically generate accessor methods. – kylejs Dec 12 '13 at 17:50
  • I've edited my answer now so the correct property names are being used, hope it works for you now. – kylejs Dec 12 '13 at 17:57
  • Thanks but it doesn't seem to be working still. What is self.inputTF in the viewDidLoad method? Also, there's no longer a navigationController toolbar in your code. Why would you do that exactly? Are you making the inputAccessoryView for TextField1 the navigationController toolBar as well? – denvdancsk Dec 12 '13 at 19:47
  • @DJSK So sorry about the self.inputTF, I've corrected that now. As I understand from your question, you're simply trying to use another textField inside a toolbar, which is placed above the keyboard as an inputAccessory to a textView which is hidden by the keyboard so you can see and control what you're typing? If so, you don't need to interact with the navigationController toolbar which is hidden by the keyboard. – kylejs Dec 12 '13 at 20:00
  • @DJSK when I get back home later this evening, I'll upload my project for you to look at – kylejs Dec 12 '13 at 20:02
  • Thanks Kyle. I think I've almost got it working using your solution. The only problem I am having is that the return key doesn't work. The responder is changing and I am now able to use the textField on the input AccessoryView to see what I'm entering in the keyboard. However, when the return key is pressed nothing seems to be happening. – denvdancsk Dec 12 '13 at 20:06
  • @DJSK your return key issue - the first things I think of is to make sure your controller is conforming to the UITextFieldDelegate protocol and that you are setting your view controller as the delegate for the two textFields you make either in code or in IB/Storyboard – kylejs Dec 12 '13 at 20:25
  • Thanks, the delegates are setup correctly. It's weird, when you press the return key the text clears and the keyboard stays open. – denvdancsk Dec 12 '13 at 21:17
  • 1
    let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43083/discussion-between-kyle-jm-and-djsk) – kylejs Dec 12 '13 at 23:56