Adding [myUITextField becomeFirstResponder]; does not bring up keyboard - ios

I've created a screen that has a UITextField on it. When I get a EditingDidBegin event, I resignFirstResponder, Bring up a Popover with another textField in it and for that TextField call the BecomeFirstResponder on it.
When it runs, I get Blinking insertion pointer and the X clear contents. Though no Keyboard. The Master UIView is set to UserInteractionEnabled:YES.
target action for First UITextField, its on its own view.
[textField addTarget:self action:#selector(wantsToEditValue:) forControlEvents:UIControlEventEditingDidBegin];
Target Action selector:
- (IBAction)wantsToEditValue:(id)sender {
// set notification so we can update from popover
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(saWriteValue:)
name:kRefreshFromPopover object:nil];
//we dont want the TagValue textfield to really be the first responder.
[textField resignFirstResponder];
[... setup popoverVC, and View. present popover...]
}
Here is the code to create the 2nd UITextField. This code is in the VC for the Popover..
- (void)viewDidLoad
{
if (IoUIDebug & IoUIDebugSelectorNames) {
NSLog(#"%# - %#", [self description], NSStringFromSelector(_cmd) );
} [super viewDidLoad];
[self createElementInputControl];
[self createWriteButton];
//We want the input Focus
[textFieldInput becomeFirstResponder];
//Resize our view to handle the new width
CGRect newViewSize = CGRectMake(self.view.frame.origin.x,
self.view.frame.origin.y,
writeButton.frame.origin.x + writeButton.frame.size.width + kWriteElementOffset ,
self.view.frame.size.height);
[self.view setFrame:newViewSize];
}
Create Input Code:
-(void) createElementInputControl {
textFieldInput = [[UITextField alloc] initWithFrame:CGRectMake( kWriteElementOffset ,
kWriteElementHeightOffset,
kTagValueInputInitialWidth,
kWriteElementDefaultHeight)];
textFieldInput.borderStyle = UITextBorderStyleRoundedRect;
textFieldInput.clearButtonMode = UITextFieldViewModeWhileEditing;
textFieldInput.textAlignment = UITextAlignmentLeft;
[textFieldInput setDelegate:self];
[textFieldInput setKeyboardType:UIKeyboardTypeDefault];
// Set the value of the text
[textFieldInput setText:self.myTag.value];
CGSize textFieldInputSize = [textFieldInput.text sizeWithFont:textFieldInput.font];
//Set the Button Width
[textFieldInput setFrame:CGRectMake(textFieldInput.frame.origin.x, textFieldInput.frame.origin.y, textFieldInputSize.width + kTagValueInputWidthBuffer, textFieldInput.frame.size.height)];
[self.view addSubview:textFieldInput];
}
When I remove the becomeFirstResponder code, the Popover come up as normal, though no blinking insertion pointer. I tap the field, I get Insertion Pointer, X clear content button, and yes a Keyboard.
I want the keyboard to show without having to click in the new Text Field.
Thanks!

In order to become a first responder, the view must be in the view hierarchy.
You need to add your textFieldInput as a subview to something.
As per Apple's doc in UIResponder:
You may call this method to make a responder object such as a view the first responder. However, you should only call it on that view if it is part of a view hierarchy. If the view’s window property holds a UIWindow object, it has been installed in a view hierarchy; if it returns nil, the view is detached from any hierarchy.

When you call the become first responder from the didBeginEditing you will run into an infinite loop.Reason being, when you call becomeFirstResponder it calls didBeginEditing. So It Explains the cursor blink and your statement
When I remove the becomeFirstResponder code, the Popover come up as
normal, though no blinking insertion pointer. I tap the field, I get
Insertion Pointer, X clear content button, and yes a Keyboard.
To solve your problem,
In the beginEditingMethod ,
if(texfield.tag == firstTextFieldTag)
{
//Create second TextField and make it become first responder
}
else
{
// do want you want in the beginEditing of your second textfield.
}

Related

Scroll the table view to the pop over-presenting text field when keyboard fires up by a text field inside the pop over

I have a UITableViewController with many cells, each cell contains four text fields vertical on each other, a pop over is presented by tapping on any text field, however, this pop over contains a text field when tapped the keyboard is fired and most likely the pop over will be shifted up to prevent the keyboard from hiding its text field (this is the default behavior of the pop over), but in the background (the dimmed view), the tableViewController loses its correct scrolling behavior to keep the pop over presenting-textField on the track while the keyboard is visible ..
a sample project can be downloaded here.
how can I offset the table view to keep the pop over presenting-textField on screen while keyboard is visible in this case ?
I tried the well-known TPKeyboardAvoiding library but it didn't solve the issue.
p.s. tableViewController works well for the first 3 or 4 keyboard firings, but loses precise scrolling on later attempts.
Screenshot (the green text field is the text field which presented the pop over, but tableViewController scrolls to the incorrect text field indicated in red):
any help would be highly appreciated.
EDIT:
this question is not a duplicate for: Making a UITableView scroll when text field is selected
because the text field that I need the table view to scroll to is the one that fires a pop over not a keyboard, and scrollToRowAtIndexPath does not work precisely in this case because each cell contains 4 text fields.
use (CGRect)convertRect:(CGRect)rect toView:(UIView *)view to get cell position on tableviews superview and accordingly handle the tableview offset
Here is my solution :
Change into
TableViewController.m
1. Register for keyboard Notifications (UIKeyboardWillShowNotification, UIKeyboardWillHideNotification)
2. Create local variables:
CGSize _currentPopoverContentSize; //if you want to have custom size for popover
UIView *_currentPopoverSender; //to remember from wich view you will present popover
BOOL _keyboardIsShown; //enable in keyboardWillShow, and disable in keyboardWillHide
3. In my presentPopover method:
- (void)presentPopoverControllerWithSize:(CGSize)size fromView:(UIView *)sender{
MyController *controller = [[[MyController alloc] init] autorelease];
if (self.popover)
{
[_popover release];
_popover = nil;
}
_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
_popover.popoverContentSize = size;
_popover.delegate = self;
//checking if keyboard is shown - if NO, than present popover, if YES - just `resignFirstResponder` for your _`activeTextField`(you can set it in -textFieldDidBeginEditing: and nullify in -textFieldDidEndEditing:)
if (!_keyboardIsShown)
{
[_popover presentPopoverFromRect:[sender bounds]
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
_popOver.popoverContentSize = CGSizeMake(320, 700);
}
else
{
[_activeTextField resignFirstResponder];
}
_currentPopoverContentSize = size;
_currentPopoverSender = sender;
}
4. Than:
- (void)keyboardWillBeHidden:(NSNotification*)aNotification{
[UIView animateWithDuration:0.3
animations:^{
//do some stuff
_popOver.popoverContentSize = CGSizeMake(320, 700);
} completion:^(BOOL finished) {
if (_popover && _currentPopoverSender)
{
[_popover presentPopoverFromRect:[_currentPopoverSender bounds]
inView:_currentPopoverSender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}];
_keyboardIsShown = NO;
}
5.:
-(void)textFieldDidBeginEditing:(UITextField *)textField{
[textField resignFirstResponder];
[self presentPopoverControllerWithSize:textField.frame.size fromView:_activeText];
// self.vc = [[self storyboard] instantiateViewControllerWithIdentifier:#"ProductSourcePopOver"];
//
// if(_popOver == nil){ //make sure popover isn't displayed more than once in the view
// _popOver = [[UIPopoverController alloc]initWithContentViewController:self.vc];
// }
// _popOver.popoverContentSize = CGSizeMake(320, 700);
//
// [_popOver presentPopoverFromRect:_activeText.frame inView:_activeText permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
// _popOver.delegate = self;
}
This might helps you :)
Change the entire view frame size.
For example, keyboard height is 100 then,
CGRect frame = self.view.frame;
self.view.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height - keyboardHeight);
Then call didSelectRowAtIndexPath method again for the same indexPath, so it will reload the popover.
This is just a base idea, there might be some modifications required to achieve exact behavior.
Hope this will help you.
How about add the tag(00 01 02 03, 10 11 12 13...etc) for each UITextfield in the cell, From tens digit you can know which cell, from single digits you know which textfield.
Register for UIKeyboardWillShowNotification and when that selector gets triggered, call your pop over code:
[self presentPopoverControllerWithSize:textField.frame.size fromView:_activeText];
The reason for this is that the iOS handles itself presenting the popover and handling it's frame. So it's generally a good practice to present the pop over after the keyboard is shown.
Hope this helps..

Make UITextView parent be its own inputAccessoryView

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?
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.
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.

Why resignFirst Responder does not hide keyboard?

This is my custom UITextField class:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.delegate = self;
[self addTarget:self action:#selector(hideKeyboard) forControlEvents:UIControlEventTouchUpOutside];
}
return self;
}
- (void) hideKeyboard
{
NSLog(#"Clicked outside");
[self resignFirstResponder];
}
However, when I click outside of the text field, hideKeyboard never gets called. Can anyone explain why and how should I fix this?
The event you registered for will only happen if you begin the touch inside the text field and finish the touch outside of the text field.
If you start the touch outside the text field, the text field does not get any event.
Add a touch gesture recognizer to the view that contains the text field. When that event is triggered, resign the current first responder.
Your touches could be swallowed by some other UIControl that is consuming them. Without seeing your hierarchy it's impossible to tell.
However, I wouldn't suggest this even if you just had 1 UITextField on a blank UIView; it doesn't scale well, and could lead to strange bugs later if you add another UIControl to the view. What happens if you have this TextField and a UIButton in the same UIView?
Rather, I'd change the superview to be a UIControl (subclass of UIView), and just use UIControlEventTouchUpInside to trigger a method that dismisses the keyboard.

UITextField in inputAccessoryView won't becomeFirstResponder

I have a view called songInfoView with 3 UITextFields and a UIButton. I create a temp UITextField in the parent view to bring up the keyboard and assign songInfoView as the inputAccessoryView. This works as expected.
Then, I try to set a text field in songInfoView as first responder. The cursor moves to this field, but when I try to type, nothing happens. I can tap on the text field and type as expected, but I want it to work without having to tap on it. Am I missing something? Am I doing this out of order? Thanks for your help.
songInfoView = [[SongInfoViewController alloc]init];
songInfoView.delegate = self;
UITextField *tempTextField = [[UITextField alloc]initWithFrame:CGRectMake(10.0f, 10.0f, 50.0f, 30.0f)];
[self.view addSubview:tempTextField];
[tempTextField setInputAccessoryView:songInfoView.view];
[tempTextField becomeFirstResponder];
[songInfoView.titleTextField becomeFirstResponder];
Well, I figured it out myself. It turns out (I think) that the on screen keyboard (along with it's accessory view) has it's own window. So, within songInfoView's viewDidAppear method, I had to call
[self.view.window makeKeyAndVisible];
Just remember to call this again within the view controller you used to load the keyboard after the keyboard disappears. Hope this helps someone else down the road.

Using next and previous button with UITextField, problems with firstresponder

I am using a subclass of a scrollview that moves the keyboard out of the way. (TPKeyboardAvoidingScrollView)
I think this is conflicting with my implementation of the next and previous buttons. I have built an inputaccessoryview
I have a category that sets the next and previous textfields for each field
when i edit a textfield, i set the current, previous and next textfields
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
_currentTextField = textField;
_prevTextField = [textField prevTextField];
_nextTextField = [textField nextTextField];
return YES;
}
when they click next or previous i call this method
- (void)selectAdjacentResponder:(id)sender{
UISegmentedControl *segmented = sender;
if(segmented.selectedSegmentIndex == 0){
[_prevTextField becomeFirstResponder];
} else {
[_nextTextField becomeFirstResponder];
}
}
this works fine.. but when i close the keyboard. my scrollview is messed up. if i add the line
[_currentTextField resignFirstResponder];
to the first line of my selectadjacent method it solves the problem. but the problem is it makes the screen focus in a funky way since i'm dismissing and accessing the next textfield at the same time.
i have tried resigning first responder when i close the keyboard. but i think my scrollview is calculated before that point.. any idea what to do =/

Resources