I have a 3 views in one screen with different components such as tables and buttons, when I try to dismiss the keyboard with the code below it doesn't dismiss when I click on the view that contains the textView( and that’s what I need! ) . However when I click on one of the other views it dismisses.
The following image shows the views that I have and the last view inside the scrollview is the one that contains the textView.
How can I get the keyboard to dismiss despite the view that is taped.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[aTextField resignFirstResponder];
}
}
also this code fails to dismiss:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self view] endEditing:TRUE];
}
You need to add tap gesture in the views which you want to click:
For you are using two UIViews with name Your_view1 and Your_view2, and textfields are txt1 and txt2. The code is below:
Your_view1:
UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTapGesture:)];
singleTapGesture.numberOfTapsRequired = 1;
[Your_view1 addGestureRecognizer:singleTapGesture];
Your_view2:
UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTapGesture:)];
singleTapGesture.numberOfTapsRequired = 1;
[Your_view2 addGestureRecognizer:singleTapGesture];
And the delegate is:
-(void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTapGesture{
[txt1 resignFirstResponder];
[txt2 resignFirstResponder];
}
If your textView is editable , tapping on that, will make it first responder. That’s why keyboard is not dismissing. If you don’t need edit textView, set it’s editable attribute to false
You should take a look at Apple document for UIScrollView.
Because a scroll view has no scroll bars, it must know whether a touch signals an intent to scroll versus an intent to track a subview in the content. To make this determination, it temporarily intercepts a touch-down event by starting a timer and, before the timer fires, seeing if the touching finger makes any movement.
That's why touchesBegan doesn't work when you click inside your scroll view.
A easy way to fix it, add a UITapGestureRecognizer for your viewController.view.
#property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer;
- (void)viewDidLoad {
[super viewDidLoad];
self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self.aTextField action:#selector(resignFirstResponder)];
[self.view addGestureRecognizer:self.tapGestureRecognizer];
}
managing keyboard get most of our development time luckly we have an alternative solution with this library
No need to write multiple line of code in every viewcontroller simply add one line of code in your didFinishLaunchingWithOptions
IQKeyboardManager.sharedManager().enable = true
This will save time
Hope this will help you
Related
I am trying to remove the keyboard when it is in editing mode of a textview.I have added tap gesture on the main view.But on the click of when editing mode is for textfield then keyboard is removed but when editing mode is for textview then keyboard is not removed.Please tell me how can i tackle this issue?
added tap gesture to the main view.
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[self.main_view setUserInteractionEnabled:true];
[self.main_view addGestureRecognizer:singleFingerTap];
calling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
if([self.txt_username isFirstResponder])
{
[self.txt_username resignFirstResponder];
}
if([self.txt_password isFirstResponder])
{
[self.txt_password resignFirstResponder];
}
}
I have already set the delegate for text view & also i have added the textview protocol.
delete code for set setUserInteractionEnabled =true , u not need that
and add this in your func
-(void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
[self.view endEditing:YES];
}
or u can use library TPKeyboardAvoiding , set for scrollview..its automatic close keyboard when u tap view..so u not need that UITapGestureRecognizer
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[[self view] endEditing:YES];
}
When there are new or changed touches for a given phase, the app object calls one of these methods. Each method takes two parameters: a set of touches and an event.
For more info Click here
i think you just put only textview resingFirstresponder.
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
[self.txt_username resignFirstResponder];
}
use it.
I am wanting to know when a user has touched anywhere on the screen of my app.
I have looked into using -(UIResponder *)nextResponder but unfortunately this will not work, as I am also reloaded a table automatically, so this gets trigged when that occurs.
I have also tried a gesture recognizer, with the following code. But this will only recognise touches on the view. Where as I have many buttons the user will be using to operate the app. I would like to avoid adding a gesture recogniser or code for this in every button and segment control I have on the screen
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnView:)];
[self.mainView addGestureRecognizer:tap];
- (void)tapOnView:(UITapGestureRecognizer *)sender
{
//do something
}
I have also tried -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event , but this has the same issue as the gesture recognizer.
I was wondering if there is any way I could achieve this task. I was hoping that I may be able to recognise the type of event from within the nextResponder, and then I could detect if it is button for example.
EDIT: The reason I am working on this is that my app needs to stay active and the screen cannot be locked (so I have disabled screen locking). To avoid excessive use of power, I need to dim the screen, but then return the brightness back to the original level once the app is touched. I need this feature to only occur on 1 of my viewcontrollers.
As mentioned by Ian MacDonald, using hitTest:: is a great solution to detect user interaction on an app wide scale, including when buttons, textfields, etc, are selected.
My solution was to subclass UIWindow and implement the hitTest method.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// do your stuff here
// return nil if you want to prevent interaction with UI elements
return [super hitTest:point withEvent:event];
}
You could attach your UITapGestureRecognizer to your [[UIApplication sharedApplication] keyWindow].
Alternatively, you could override hitTest: of your root UIView.
Is there a particular task you are hoping to accomplish? There may be a better way than assigning an "anywhere" gesture.
Edit: Use hitTest:.
#interface PassthroughView : UIView
#property (readonly) id target;
#property (readonly) SEL selector;
#end
#implementation PassthroughView
- (void)setTarget:(id)target selector:(SEL)selector {
_target = target;
_selector = selector;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
[_target performSelector:_selector];
return nil;
}
#end
#implementation YourUIViewController {
PassthroughView *anytouchView;
}
- (void)viewDidLoad {
// Add this at the end so it's above all other views.
anytouchView = [[PassthroughView alloc] initWithFrame:self.view.bounds];
[anytouchView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
[anytouchView setTarget:self selector:#selector(undim)];
[anytouchView setHidden:YES];
[self.view addSubview:anytouchView];
}
- (void)undim {
[anytouchView setHidden:YES];
}
- (void)dim {
[anytouchView setHidden:NO];
}
#end
Your edit adds more clarity to your question.
The reason I am working on this is that my app needs to stay active
and the screen cannot be locked (so I have disabled screen locking).
To avoid excessive use of power, I need to dim the screen, but then
return the brightness back to the original level once the app is
touched.
Since you are controlling the screen brightness, you can add one transparent view controller before dimming screen on top of your root controller which does only one job, listen to tap using Tap gesture. And on tap you can dismiss the view controller and adjust brightness to previous state.
By doing so you dont have to worry about buttons being clicked as they will be below the transparent view controller. Since its a whole new view controller sitting on top of stack you dont have to modify your existing code as well.
Ok I have had a similar problem before.
As I remember I subclassed the UIWindow for full screen detection and made it First responder.
Than I overridden the touch to handle from subclasses.
You can also use code to identify the control that is been touched.
#import <QuartzCore/QuartzCore.h>
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setMultipleTouchEnabled:YES];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Enumerate over all the touches
[touches enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
// Get a single touch and it's location
UITouch *touch = obj;
CGPoint touchPoint = [touch locationInView:self.view];
...
}];
}
To disable the locking of screen I used below code:
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
I used following functions to dim or increase the screen brightness
[[UIScreen mainScreen] setBrightness:0.0f]; //and
[[UIScreen mainScreen] setBrightness:1.0f];
I have put a UIView in my navigation item and I am using the JSBadgeView on it. I want for a different screen to appear upon clicking it, but I'm not sure how. iOS won't let me make a seque and I checked off "button" under traits but I'm not sure what to do after that. In Android, I would just do Object.setOnClickListener but as far as I know there is no method like that iOS. Any thoughts?
Create a tap gesture recogniser:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapHandler:)];
Add the tap gesture to the UIView:
[aView addGestureRecognizer:tap];
Then implement the tap handler:
- (IBAction)tapHandler:(UITapGestureRecognizer *)recognizer { // Handler code }
You should just be able to manually perform the required segue in the handler.
A simpler solution would be to implement the touchesBegan method as follows
This will detect when the view was clicked
- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
There are some answers out there such as this, but in the case where there is a UIScrollView or UICollectionView present, it doesn't work.
The touchesBegan method on the viewController will never get called.
On screen, I have a UITextField at the top.
Below that, filling up the rest of the screen is a UICollectionView.
I need to dismiss the keyboard if I touch anywhere besides the UITextField (including the collection view obviously)
So what is the best way to do this?
For such a common UI paradigm it seems like there should be a well-known solution, but I've yet to come across it.
To dismiss Keyboard on tap of the View: Add a Tap gesture to your ViewController.collectionView as follows:
//declare a property to store your current responder
#property (nonatomic, assign) id currentResponder;
//in viewDidLoad:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(resignOnTap:)];
[singleTap setNumberOfTapsRequired:1];
[singleTap setNumberOfTouchesRequired:1];
[self.collectionView addGestureRecognizer:singleTap];
//Implement the below delegate method:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.currentResponder = textField;
}
//Implement resignOnTap:
- (void)resignOnTap:(id)sender {
[self.currentResponder resignFirstResponder];
}
The simple way to do it is:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
Here's a better solution which doesn't require adding gesture recognisers individually to everything. It's in Swift, but could easily be converted to ObjC.
Add the following to your viewDidLoad():
let tap = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
and then add the following method declaration:
func dismissKeyboard()
{
view.endEditing(true)
}
...where view is your text field.
I've created a mini pop-up menu for the iPhone in a UIView, and I'd like the user to be able to dismiss the view if they do anything other than select one of the options. So, if a user taps/swipes/pinches any other element on the screen, the pop-up view should disappear.
However, I don't want to detect a gesture that will stop something else from happening... For example, there is a UITableView underneath and if I swipe up or down on it, I want it to move as expected as well as dismissing the mini pop-up view.
Should I use multiple gesture recognizers, or should I use touchesBegan, or is there a better way of doing it?
Put this in your UIViewController
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if (touch.view!=yourView && yourView) {
[yourView removeFromSuperview];
yourView=nil;
}
}
EDIT: changes made to detect touch and remove only if view exists
EDIT2: Well you could add the following to your UIButtons/UITableView methods
if (yourView) {
[yourView removeFromSuperview];
yourView=nil;
}
or add touchesBegan:withEvent: as a touchDown event to your buttons.
Both annoying to do but can't see another way to do it as the touchesBegan method doesn't get called with interactive elements.
EDIT3: Right scrap that, think i've nailed it
in your interface add the UIGestureRecognizerDelegate
#interface ViewController : UIViewController <UIGestureRecognizerDelegate> {
then in your viewDidLoad add this
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapMethod)];
tapped.delegate=self;
tapped.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapped];
then in your viewController add these 2 methods
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (touch.view!=yourView && yourView) {
return YES;
}
return NO;
}
-(void)tapMethod {
[yourView removeFromSuperview];
yourView=nil;
}