I use a UITableView for a user/password login control. Right now it's the only control on the view, along with a login button. When i click inside, the text edit content becomes active, the keyboard pops up and I can type. however there is no way to stop the editing. I'd like to click outside on the white area of my UIView so that the focus is taken away from the text editors inside my UITableVIew and the keyboard becomes invisible again.
How do I do that?
You can add button which alpha channel is equil zero. There is behind your login and password field. Set action to this button in the following way:
-(void)hideKeyboard:(id)sender
{
[self.username resignFirstResponder];
[self.password resignFirstResponder];
}
In viewDidLoad make your view controller listen to keyboard notifications and create a tap recognizer which will receive all events outside of your tableView:
- (void)viewDidLoad
{
[super viewDidLoad];
...
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(keyboardWillShow:) name:
UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:#selector(keyboardWillHide:) name:
UIKeyboardWillHideNotification object:nil];
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard:)];
...
}
Then in the notification methods for the keyboard add and remove the gesture recognizer from your view.
//add gesture recognizer when keyboard appears
-(void)keyboardWillShow:(NSNotification *) note {
[self.view addGestureRecognizer:tapRecognizer];
}
//remove it when keyboard disappears
-(void)keyboardWillHide:(NSNotification *) note
{
[self.view removeGestureRecognizer:tapRecognizer];
}
In the action method of your gesture recognizer you resign all first responders to dismiss the keyboard:
-(IBAction)dismissKeyboard:(id)sender
{
//this removes ALL firstResponder from view
[self.view endEditing:TRUE];
}
Don't forget to end listening to the keyboard notifications at some point:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Add a Single Tap GestureRecognizer and resign the keyboard in the called function
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(resignKeyBoard)];
[tap setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:tap];
Related
I have a UIPageViewController that has a vertical orientation when it scrolls but it will not scroll to the top when the status bar is pressed. There are no other scroll views on the page if that helps.
Is there a scrolltotop function for a page view controller?
For easier implementation you can use this code in your childVC. This setting will make only visible ChildVC to be scrollsToTop-able.
- (void)viewDidLoad
{
self.collectionView.scrollsToTop =NO;
}
-(void)viewDidAppear:(BOOL)animated
{ self.collectionView.scrollsToTop =YES;
}
-(void)viewWillDisappear:(BOOL)animated
{
self.collectionView.scrollsToTop =NO;
}
UIPageViewController as far as I know does not have any scrollToTop ability. To provide such a feature, I add an observer to listen status bar touch events. I use your appcoda link as reference project, so if you insert codes into related files, it'll work perfectly.
// AppDelegate.m
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[[NSNotificationCenter defaultCenter] postNotificationName:#"touchStatusBarClick" object:nil];
}
// ViewController.m
- (void)viewDidLoad
{
// add this line at the bottom of the function
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarTouched) name:#"touchStatusBarClick" object:nil];
}
// This function is called when status bar is touched
-(void) statusBarTouched
{
PageContentViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:nil];
}
I hope it helps.
I have main viewcontroller that opens via popover segue other view controller with buttons.
On button click what I wish to happen is function from first viewcontroller fire and the popover will close. How do I do so properly?
On settings button click the popover open. Then when user click Manual Content Update the the view will close and start function on Projects Main viewController.
You can use NSNotificationCenter.
In your main UIViewController add:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receivePopoverNotification:)
name:#"PopoverNotification"
object:nil];
}
-(void) dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void) receivePopoverNotification:(NSNotification *) notification
{
[self.popover dismissPopoverAnimated: YES];
self.popover = nil;
}
In your UIPopoverController add:
-(IBAction) pressButton: (id) sender {
[[NSNotificationCenter defaultCenter]
postNotificationName:#"PopoverNotification"
object:nil];
}
Purpose: I am attempting to toggle the "Save" UIBarButtonItem with the "Hide Keyboard" UIBarButtonItem whenever the Keyboard appears (and then do the opposite when the "Hide Keyboard" button is clicked).
So far I have created two UIBarButtonItems and connected them both to Interface Builder.
#property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *hideKeyButton;
This is the code I have setup so far in my main:
- (void)keyboardDidShow:(NSNotification *)aNotification {
// Show HideKey Button
// Hide Save Button
}
- (void)keyboardWillHide:(NSNotification *)aNotification {
// Show Save Button
// Hide HideKey Button
}
On Interface Builder, the Save button is present by default. Programatically, how do I show the HideKey button and Hide the Save button? Thanks.
There are two parts to make this work.
First, you need to register for the notifications, what you can do is, in your viewDidLoad, add the following:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
Secondly, in your event handlers, simply set the buttons:
- (void)keyboardDidShow:(NSNotification *)aNotification {
self.navigationItem.rightBarButtonItem = hideKeyButton;
}
- (void)keyboardWillHide:(NSNotification *)aNotification {
self.navigationItem.rightBarButtonItem = saveButton;
}
Instead of using IB for this task, I would do it programmatically.
Something like this:
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self
action:#selector(saveButtonPressed:)];
[self.navigationItem setRightBarButtonItem:saveButton];
And in a similar fashion to create and set the HideKey button.
Then, of course you may want to cache the UIBarButtonItems, setting lazy #properties for them.
I have a modal popup which is placed behind the keyboard.
How can I move the modal popup to a higher position?
This is work around to get rid of mentioned situation.
I assume you are using becomeFirstResponder for textField. Write below code in class which is presented modally.
-(void)viewDidAppear:(BOOL)animated{
[self performSelector:#selector(txtFieldResponder) withObject:nil afterDelay:0.1];
}
-(void)txtFieldResponder{
[self.txt becomeFirstResponder];
}
Hope this helps.
Use this:
Register class for keyboard show and hide notification
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:#selector(showKeyboard:) name:UIKeyboardDidShowNotification object:nil];
[center addObserver:self selector:#selector(hideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
Then implement
- (void)showKeyboard:(NSNotification *)notification {
//Change popup frame here
}
- (void)hideKeyboard:(NSNotification *)notification {
//Change popup frame to previous state
}
Trying to implement a UITapGestureRecognizer to a form sheet modal viewcontroller.
If user touches outside of the form sheet, form sheet should dismiss, it does so code works just fine.
Problem is If I manually dismiss the form sheet and try to touch any point in view it still tries to call UITapGestureRecognizer method and app crashes.
Error ::
-[xxxxView handleTapBehind:]: message sent to deallocated instance
-(void)done
{
[self.navigationController popViewControllerAnimated:YES];
//send notification that folder has been created
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshDetails" object:nil];
}
-(void)viewDidAppear:(BOOL)animated
{
// gesture recognizer to cancel screen
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapBehind:)];
[recognizer setNumberOfTapsRequired:1];
recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
[self.view.window addGestureRecognizer:recognizer];
}
- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window
//Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.
if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil])
{
// Remove the recognizer first so it's view.window is valid.
[self.view.window removeGestureRecognizer:sender];
[self dismissModalViewControllerAnimated:YES];
}
}
}
Why is handleTapBehind: still called after I dismiss viewcontroller? How can I fix this?
You add gesture recognizer to window:
[self.view.window addGestureRecognizer:recognizer];
And set target to your controller;
So, when your controller closed - it's released, but gesture recognizer still alive. And when it fire it try to send action to your controller, which already does not exists.
So, you should add recognizer to controller's view or remove him in viewWillDissaper method.
Try using gesture recognizer's delegate method, put a flag when you manually dismissed the vc and in shouldReceiveTouch:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if(flag)
{
return NO;
}
return YES;
}
Don't forget to set the delegate as the current viewcontroller. Also you can now remove the line [self.view.window removeGestureRecognizer:sender];
I will like to add the code from #mikhail 's answer
(UITapGestureRecognizer *)senderTap
-(void)viewWillDisappear:(BOOL)animated{
[self.view.window removeGestureRecognizer:senderTap];
}
In my code I capture UITapGestureRecognizer (sender) in a selector method when ViewDidAppear is called.