I have a buttonA and when the buttonA is clicked, I want the keyboard to show with a UITextField in the inputAccessoryView. Is there a way to have the keyboard show manually and also set the inputAccessoryView without having a UITextField initially?
Thanks.
A component which enables customization of the keyboard input accessory view on iOS. The input accessory view is displayed above the keyboard whenever a TextInput has focus. This component can be used to create custom toolbars.
You cannot summon the keyboard without an object which can become first responder. There are two ways to work around:
Subclass a UIView
and implement UIKeyInput
protocol in it. For example:
In your .h file:
@interface InputObject : UIView<UIKeyInput>
@property (nonatomic, copy) NSString *text;
@property (nonatomic, strong) UIView *inputAccessoryView; // You must override inputAccessoryView , since it's readonly by default
@end
In your .m file, implement the protocol:
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (BOOL)hasText
{
return [self.text length];
}
- (void)insertText:(NSString *)text
{
NSString *selfText = self.text ? self.text : @"";
self.text = [selfText stringByAppendingString:text];
[[NSNotificationCenter defaultCenter] postNotificationName:kInputObjectTextDidChangeNotification object:self];
}
- (void)deleteBackward
{
if ([self.text length] > 0)
self.text = [self.text substringToIndex:([self.text length] - 1)];
else
self.text = nil;
[[NSNotificationCenter defaultCenter] postNotificationName:kInputObjectTextDidChangeNotification object:self];
}
Let's say you want to summon the keyboard in your -viewDidAppear:
, the code goes like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// inputObject and textField are both your ivars in your view controller
inputObject = [[InputObject alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
inputObject.inputAccessoryView = textField;
[self.view addSubview:inputObject];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inputObjectTextDidChange:) name:kInputObjectTextDidChangeNotification object:nil];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[inputObject becomeFirstResponder]; // This will summon the keyboard
}
Then implement the notification selector in your view controller:
- (void)inputObjectTextDidChange:(NSNotification *)notification
{
// Just set the text here. notification.object is actually your inputObject.
textField.text = ((InputObject *)(notification.object)).text;
}
This is probably what you mean by "set the inputAccessoryView without having a UITextField initially"
inputAccessoryView
by carefully arranging its animation. But this solution needs your textField to be the first responder. Firstly, you observe the keyboard events in your -viewDidLoad
:
- (void)viewDidLoad
{
[super viewDidLoad];
// Init the textField and add it as a subview of self.view
textField = [[UITextField alloc] init];
textField.backgroundColor = [UIColor redColor];
[self.view addSubview:textField];
// Register keyboard events
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil];
}
Secondly, set the frame of your textField
in -viewWillAppear:
, in order to guarantee its frame won't be affected by autoresizing :
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
textField.frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds), CGRectGetWidth(self.view.bounds), 50);
}
And then, arrange your textField
animation and let it be synchronized with the keyboard animation. Your keyboard notification selectors may be like this:
- (void)keyboardWillShowNotification:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
UIViewAnimationCurve curve = [[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGFloat duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect keyboardFrame = [[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardFrame = [self.view convertRect:keyboardFrame toView:self.view];
[UIView animateWithDuration:duration delay:0.0f options:(UIViewAnimationOptions)curve animations:^{
CGRect textFieldFrame = textField.frame;
textFieldFrame.origin.y = keyboardFrame.origin.y - CGRectGetHeight(textFieldFrame);
textField.frame = textFieldFrame;
}completion:nil];
}
- (void)keyboardWillHideNotification:(NSNotification *)notification
{
NSDictionary *userInfo = notification.userInfo;
UIViewAnimationCurve curve = [[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGFloat duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
[UIView animateWithDuration:duration delay:0.0f options:(UIViewAnimationOptions)curve animations:^{
textField.frame = CGRectMake(0, CGRectGetMaxY(self.view.bounds), CGRectGetWidth(self.view.bounds), 50);
}completion:nil];
}
At last, call [textField becomeFirstResponder]
to trigger the animation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With