So I have a self created top bar controller that is being implemented in my other controllers views. I have a textfield on this top bar. I was wondering what the best approach to having the keyboard dismiss if the user clicks anywere outside the keyboard. I do have a tap gesture recognizer that performs the method dismisskeyboard. However, this only works if the user clicks on the top bar outside the keyboard. Is there a way to set it up so if the user clicks anywere on the screen, then this will dismiss the keyboard?
The approach I would describe is a hack but still works.
create a transparent UIButton with the frame of the view, like below:
UIButton* overlay = [UIButton buttonWithType:UIButtonTypeCustom];
overlay.frame = self.view.bounds;
overlay.backgroundColor = [UIColor clearColor];
[overlay addTarget:self action:#selector(hideOverlay:) forControlEvents:UIControlEventTouchDown];
[self.view.subviews[0] insertSubview:overlay belowSubview:self.textField];
Create a method hideOverlay to dismiss the keyboard and hide the transparent:
-(void)hideOverlay:(id)sender {
UIView* overlay = sender;
[overlay removeFromSuperview];
[self.textField resignFirstResponder];
}
You should ideally call the first block of code in textFieldDidBeginEditing: protocol method of UITextFieldDelegate and you should register your calling class accordingly.
You might try giving the text field a transparent inputAccessoryView, sized to fill the rest of the screen, that catches taps and dismisses the keyboard.
Related
I have a UITextField which I can click on, and edit the contents of. I am running code when the UITextField is pressed by using:
[personalCountryLabel addTarget:self action:#selector(countryPressed) forControlEvents:UIControlEventEditingDidBegin];
This presents another view controller. However, when I click the back button, the UITextField is still selected, so the text runs again, sending me back to the view controller.
I use the code:
textField.enabled = false;
and
textField.enabled = true;
to respectively turn off and on the editing of the UITextField, but doing this in succession does not unselect the UITextField.
How can I therefore programmatically deselect the UITextField (i.e, where the line cursor is no longer blinking).
If I understand what you're asking correctly, you just want:
[textField resignFirstResponder];
/* Programmatically deselect the Uitextfiels below this Code */
UITextField *txtDeselect = [[UITextField alloc]initWithFrame:CGRectMake(self.view.frame.origin.x+20, self.view.frame.origin.y+20, self.view.frame.size.width-40, 40)];
[txtDeselect setBackgroundColor:[UIColor yellowColor]];
[txtDeselect setBorderStyle:UITextBorderStyleRoundedRect];
[txtDeselect setTextAlignment:NSTextAlignmentCenter];
[txtDeselect setText:#"Email"];
txtDeselect.enabled = NO;
[self.view addSubview:txtDeselect];
did you set outlet & delegate of UITextField in your view controller ?
why you use UItextfield for this ?
i recommend you use one of this before presenting new view controller :
option 1 :
[youtextfield resignFirstResponder];
//please sure you outlet connected & ....
you can call this on your viewWillAppear
option 2 :
[self.view endEditing:YES]; // this regularly
happend after present another VC)
you shouldn't use shouldEndEditing
I am using the SWRevealViewController project by John Lluch for my application and I have run into one minor issue that I can't seem to get straight.
I am using the SWRevealViewController to access my apps options menu from anywhere in my app just by swiping to the right and the main view slides to reveal the menu behind it.
This is handled by a swipe gesture recognizer that is added to the main view. To improve UX, I create a button to cover the main view when it gets swiped out of the way so all the user has to do to close the menu is tap the small part of the view that is showing or grab the view and pull it back.
It works great except on one of my views in which the majority of the view is a UIScrollView. To get it to work I have to add the gesture recognizer to the UIScrollView as well as the super view. But for some reason, once the view is swiped out of the way, the swipe gesture recognizer stops responding. But this only happen on the view where the majority of the screen is a scroll view thus, what the user grabs to pull the screen back is the scroll view.
Hopefully that was understandable. Any light that you guys can shine on this will be very helpful.
-(void)viewDidAppear:(BOOL)animated {
// so the user can tap the button to show the menu
[menuButton addTarget:self.revealViewController action:#selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
// so the user can swipe to show the menu
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
// so the user can swipe the scrollview to show the menu
[mainScrollView addGestureRecognizer:self.revealViewController.panGestureRecognizer];
self.revealViewController.delegate = self;
}
- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position {
if (position == FrontViewPositionRight) {
//create the button so the use can tap to close the menu
returnButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[returnButton addTarget:self.revealViewController action:#selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:returnButton];
} else {
[returnButton removeFromSuperview];
returnButton = nil;
}
}
So I just discovered that this issue has already been addressed within the SWRevealViewController Project. This post pointed me in the right direction. They have added a tap gesture recognizer that has the behaviour I was creating with the dynamically created button.
Adding
[self.view addGestureRecognizer:self.revealViewController.tapGestureRecognizer];
removes the need for the button, thus allowing the view to respond to both recognizers.
I have a UITableViewController that is pushed from a RootViewController. In the UITableView for the UITableViewController, I'm using a custom cell which has a button at the left with frame: CGRectMake(0,0,30,30).
It seems like when I set self.navigationController.interactivePopGestureRecognizer.enabled = NO; in the UITableViewController, the touch events for the button are received, but if I set it to enabled = YES, the touch events on the button are lost:
Here's my code for creating the button inside the custom tableviewcell.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0,0,30,30);
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
Any thoughts/suggestions on how I can fix this would be appreciated!
Thanks.
Set the cancelsTouchesInView property on the gesture recognizer to NO. The default is YES, which means the view to which it's attached won't get to also handle the touches.
It's easy as pie to add an inputAccessoryView on a UITextField, UITextView, or UISearchBar. However, there's no obvious and easy way to add one for your basic UIView as far as I can tell!
I have a UIView subclass that follows the UIKeyInput protocol. It receives keyboard input to do stuff that isn't related to entering text, so I'd rather not force it to subclass the former specified views because it adds bloat and would expose a bunch of properties that don't do anything, plus I'd need to work around the text entry that occurs natively to those classes (more bloat).
However, my UIView does need an input accessory view on its presented keyboard to function correctly.
Are there any simple ways to go about this? Do I have to register as an observer to the UIKeyboardWillShowNotification in my UIView subclass and add a subview, as an accessory view, to it manually?
Did you try simply adding the inputAccessoryView method to your viewController?
I believe it gets called when the keyboard is shown, so you don't actually have to assign one to each textField or view.
- (UIView *)inputAccessoryView
{
if (!inputAccessoryView)
{
CGRect accessFrame = CGRectMake(0.0, 0.0, 768.0, 77.0);
inputAccessoryView = [[UIView alloc] initWithFrame:accessFrame];
inputAccessoryView.backgroundColor = [UIColor blueColor];
UIButton *compButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
compButton.frame = CGRectMake(313.0, 20.0, 158.0, 37.0);
[compButton setTitle: #"Word Completions" forState:UIControlStateNormal];
[compButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[compButton addTarget:self action:#selector(completeCurrentWord:) forControlEvents:UIControlEventTouchUpInside];
[inputAccessoryView addSubview:compButton];
}
return inputAccessoryView;
}
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.