Question

I'm trying to achieve a similar keyboard interaction that Messages has in iOS 7. I have a UIView which contains a UITextView, and when the user selects it to start typing, I want to make this UIView the inputAccessoryView. This would take care of the animation for me, as well as the new UIScrollView keyboard dismiss interaction in iOS 7.

When the UITextView begins editing, I'm trying to set its inputAccessoryView to its parent UIView (which is already in the view hierarchy). The keyboard appears but not with an accessory view.

I've read some people are using a duo of UITextFields to make this work, but that seems like a bad way to achieve this.

Any suggestions?

Was it helpful?

Solution

A much easier solution is to make your input field the input accessory view of your view controller:

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (UIView *)inputAccessoryView
{
    return self.yourInputField;
}

The view will be on screen at the bottom of the screen and when it becomes first responder in response to a user tapping it, the keyboard will be presented. The view will be animated such that it remains immediately above the keyboard.

OTHER TIPS

The only way to get this to work is via a second text field. The idea is to make it a subview but not visible (due to crazy rect). You then switch firstResponder back and forth between it and the real text field while its getting delegate methods. I created a some one viewController test project and did this (you can copy paste and verify behavior with about 2 minutes of time):

@implementation ViewController
{
    UITextField *field;
    UITextField *dummyView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    field = [[UITextField alloc] initWithFrame:CGRectMake(0, 460, 320, 20)];
    field.borderStyle = UITextBorderStyleRoundedRect;
    field.delegate = self;
    //field.inputAccessoryView = field;
    field.text = @"FOO";
    [self.view addSubview:field];

    dummyView = [[UITextField alloc] initWithFrame:CGRectMake(0, 40000, 320, 20)];
    dummyView.delegate = self;
    [self.view addSubview:dummyView];
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if(textField == field && textField.superview == self.view) {
        [field removeFromSuperview];
        dummyView.inputAccessoryView = field;

        [dummyView becomeFirstResponder];
    }
    return YES;
}

@end

I should add I've used this technique in shipping apps since iOS 4.

EDIT: So a couple of other ideas:

1) To make the glitch when the keyboard starts moving look a little better, you could take a snapshot of your textView, put that into a UIImageView, and when you remove the textView from the primary view, replace it with the UIImageView. Now the appearance is the same. Add an animation for the image so that noting happens for 50 ms, then the alpha goes to 0. Add a similar animation to your real textview, so that it has an alpha of 0 for 50 ms, then it goes to 1. You may be able to tweak this so the transition is good (but not great).

2) The way apple probably does this is to get the animation curve and timing from the keyboard moving notification. In this case they would add a accessory view with 0 height at first, and animate the textField so its tracking the keyboard, but above it. Both moving same distance at the same time. At the end of the animation, the textField is pulled out of self.view, the accessory view has its frame changed to have the height of the textField, and the textField is placed as a subview of the accessory container view. This should work but yeah, its a bit complex to do. If you want someone to code it for you offer a 100 pt bounty. You still need the dummy text field for when you go and move the textField at the end, since when you take it out of its containing view it will resign first responder. So at the end, you make the dummy field the first responder, move the textfield, then make the real textfield the first responder again.

This actually works best if you don't use .inputAccessoryView at all and instead just animate the position of the parent UIView as the keyboard opens and closes. Here is an answer describing the process step-by-step with all the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top