Animating an `inputView` Keyboard Transition
Asked Answered
F

2

10

UITextField has an inputView property that can be used to specify a custom keyboard. Clearing this to nil provides the default keyboard.

If the UITextField is the first responder, no change occurs on setting inputView, but by calling [textField reloadInputView] the keyboard change will happen immediately.

I'd like to be able to switch between two different input approaches. The interface to trigger this will be a UISegmentedView installed as the UITextField's inputAccessoryView.

I've got this working, but the transition is very abrupt. Partly because the spinner and keyboard I transition between have different sizes on the iPad.

I've found that is I wrap an animation block around reloadInputView, I will get a smooth animation between the two keyboard's view frames. Unfortunately there is a visual judder because the transition is not animated:

[UIView animateWithDuration: 0.3 animations:^()
{
    [firstResponder reloadInputViews];
}];

Alternatively, if I wrap the reload in a transition, I can get a nice cross fade, but I don't get smooth frame changes:

[UIView transitionWithView: keyboardWindow
                  duration: 0.3
                   options: UIViewAnimationOptionTransitionCrossDissolve
                animations: ^(){ [firstResponder reloadInputViews]; }
                completion: nil];

(In the second code block I obtained keyboardWindow from self.window because this view is installed as the UITextField's inputAccessoryView which is ultimately nested under the keyboard's window.)

What I'd like is to animate and transition the input view reload. I tried placing reload in a transition in an animation, and I also tried placing the reload in an animation in a transition – neither seemed to help.

Any ideas? Thanks!

Finecut answered 14/1, 2015 at 17:39 Comment(0)
I
1

You can invoke resignFirstResponder to make the input view disappear and then invoke becomeFirstResponder, after a delay, to make the keyboard appear and vice versa.

The following sets to inputView after resigning the normal keyboard.

let delayTime = dispatch_time(DISPATCH_TIME_NOW,Int64(1 * (NSEC_PER_SEC/3)))

textField.resignFirstResponder()

dispatch_after(delayTime, dispatch_get_main_queue()) {
     self.textField.inputView = currentInputView
     self.textField.becomeFirstResponder()
} 

This sets to keyboard.

dispatch_after(delayTime, dispatch_get_main_queue()) {
     self.textField.inputView = nil
     self.textField.becomeFirstResponder()
}
Imagination answered 20/1, 2015 at 17:54 Comment(1)
Thanks – I don't want to resign the hide the keyboard and then reveal it again, though.Finecut
D
1

I'm able to successfully animate changes to an inputView without any glitches by:

  1. Adding the new inputView as a subview of the existing inputView and then
  2. Switching the UIControl's inputView to the custom inputView after your choice of animation is complete.

As an example, here's how to quickly fade in a custom inputView:

//start the view as invisible
_customInputView.alpha = 0.0f;

//add the custom inputView as a subview of the existing inputView
[self.inputView addSubview:_customInputView];

//animate the opacity change
[UIView animateWithDuration:0.25f 
                      delay:0.0f
                    options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         _customInputView.alpha = 1.0f;
                     } completion:^(BOOL finished) {
                         //switch the UIControl's inputView
                         self.inputView = _customInputView;
                     }];
Darkish answered 9/3, 2017 at 20:14 Comment(1)
That sounds like a good approach. Thanks. I'm not in a position to test this at the moment, but you get a +1 from me :-)Finecut

© 2022 - 2024 — McMap. All rights reserved.