I added a tapgesturerecognizer to my view so when the user hits the search bar, but then decides to not type, the user can tap on the screen behind the keyboard, and the keyboard will disappear. this is my code in viewdidload:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[self.view addGestureRecognizer:tapGesture];
[tapGesture release];
Then to handle the tap:
- (void)handleTap:(UITapGestureRecognizer *)gesture {
if (self.searchDisplayController.active == YES) {
[self.searchDisplayController setActive:NO];
}
}
However, now my other buttons like items in the tabbar are not available. Am I missing something else? Thanks!
Try
[self.searchDisplayController.searchBar resignFirstResponder];
This will hide the keyboard without deactivating search mode.
Related
I'm using UILongPressGestureRecognizer class to handle if one item is being selected.
The logic is as follows: User press during 1 second an item (UIView subclass). Once the gesture is detected, the item is highlighted and moveable.
The user must move this item across the screen without stop touching it.
The problem I'm facing is the gesture recognized shadows touchesBegan/Move/Ended necessary for the item class to arrange the movement.
I tried to remove the gesture recognized once is detected and the item selected. But still sending messages to the handle of gesture instead of call touches methods.
Anyone knows any way to stop "listening" the gesture recognizer without leave the finger of the screen?
Thanks.
Here the code:
-(void)addGestures
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPress:)];
longPress.minimumPressDuration = iItemLongPressTime;
[self addGestureRecognizer:longPress];
[longPress release];
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
NSLog(#"Long press Ended");
}
else {
if (self.isSelected) return;
if ([delegate respondsToSelector:#selector(singleTouch:)])
[delegate singleTouch:self];
[self removeGestureRecognizer:[self.gestureRecognizers objectAtIndex:0]];
NSLog(#"Long press detected.");
}
}
As you can see in the else branch the delegate calls enables all procedures to mark this item as selected, and just after remove the recognizers.
What I'm missing?
--EDIT--
Done! This works:
#pragma mark Gesture Functions
-(void)addGestures
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPress:)];
longPress.minimumPressDuration = iItemLongPressTime;
[self addGestureRecognizer:longPress];
[longPress release];
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
NSLog(#"Long press Ended");
}
else {
NSLog(#"Long press detected.");
if (self.isSelected) return;
if ([delegate respondsToSelector:#selector(singleTouch:)])
[delegate singleTouch:self];
[sender removeTarget:self action:#selector(handleLongPress:)];
sender.enabled = NO;
[self removeGestureRecognizer:sender];
}
}
Regards!
Does the custom UIView class have its own touch handling code? If not, a simple solution is to set the allowableMovement property of the UILongPressGestureRecognizer to CGFLOAT_MAX, or some big number, and use the gesture update callbacks to drag your custom view around. You can get the displacement using the - (CGPoint)locationInView:(UIView *)view method on the superview, and compare its position to when the recognizer began.
There are two solutions in my mind.
For animating uiview, please wrote a new class which is inherited from the UIView class and implement the touch delegates instead of writing the Gustures to handle animation(if the touch delegates are not triggering in the current class).
2.I have successfully removed the UILongPressGestureRecognizer after triggered it once.
Please refer the below code .ask me if you have any queries
Steps I have Done
I have added a UIView as "myView" to my main-view when main-view loads.
I have given the Tag to the myView (you can give 1,2,3…etc) to differentiate the tapped view from the main-view subviews.
Assigned the UILongPressGestureRecognizer gesture to myView and assigned target as "moveMe" method.
When user Pressed the myView long, the "moveMe" method will trigger.
Then I iterated the mainView Subviews with the condition Tag == 1
I have removed the UILongPressGestureRecognizer from the subview.As we can know that Tagged 1 main-view subView is myView.
So the NSLog(#"gesture removed"); and NSLog(#"moveMe"); will log in console only at one time.
The NSLog(#"touchesBegan"); will trigger first instead of triggering the "moveMe" method.
Then NSLog(#"touchesBegan"); will trigger always after removed the gesture . "moveMe" method will not trigger ever.
Code
- (void)viewDidLoad {
//Adding to UIView to main view when application is loading.
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 80, 80)];
myView.backgroundColor = [UIColor viewFlipsideBackgroundColor];
myView.tag = 1; //adding a tag to identify it.
//Adding Long Press Gesture to the UIView.
UILongPressGestureRecognizer *myGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(moveMe:)];
[myView addGestureRecognizer:myGesture];
[myGesture release];
myGesture = nil;
[self.view addSubview:myView];
[myView release];
myView = nil;
[super viewDidLoad];
}
//Method to trigger when user pressed long on the added UIView.
-(void)moveMe:(id)sender
{
for (UIView *subViews in [self.view subviews])
{
if (subViews.tag == 1) {
[subViews removeGestureRecognizer:sender];
NSLog(#"gesture removed");
}
}
NSLog(#"moveMe");
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesBegan");
}
or please refer Disable gesture recognizer iOS
How can I hide the Number Pad programmatically in iPhone?
As I have created a Registration Form and for the ZIP/Postal Code I have set keypad as NumberPad.
So on entering numbers I would like to hide the NumberPad?
//put in viewdidload.
-(void)viewDidLoad
{
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[self.view addGestureRecognizer:gestureRecognizer];
[super.... ];
}
- (void) hideKeyboard
{
[textfieldname1 resignFirstResponder];
[textfieldname2 resignFirstResponder];
}
Send resignFirstResponder to the UI element to which the keyboard is linked (probably a UITextField/UITextView?).
I have a UITableView. I have added to this table a UIGestureRecognizer that looks for a swipe on a cell, and enables editing on that table if it detects a swipe. When I swipe right, it does indeed enable editing on the table. However, when I swipe left, I get the default red delete button appear on the right side of the cell. How can I disable this default behavior, and make it so that if I swipe left OR right, I get editing on either way?
- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
foldersTable.editing=YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIGestureRecognizer *recognizer;
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[foldersTable addGestureRecognizer:recognizer];
[recognizer release];
}
Just return UITableViewCellEditingStyleNone in your tableView:editingStyleForRowAtIndexPath: method.
There is a direction property on UISwipeGestureRecognizer. You can set that to both right and left swipes:
recognizer.direction = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft;
I am using another way to solve this problem.
NSMutableArray *tableViewGestures = [[NSMutableArray alloc]initWithArray:[self.tableView gestureRecognizers]];
[[tableViewGestures objectAtIndex:2] setDirection:UISwipeGestureRecognizerDirectionLeft];
NSLog(#"directions %#" , [tableViewGestures objectAtIndex:2] );
NSArray *newTableViewGestures = [[NSArray alloc]initWithArray:tableViewGestures];
[self.tableView setGestureRecognizers:newTableViewGestures];
I got the tableViewGestures NSArray and reset it.If I wanna use SwipeGestureRecognizerDirectionRigth,I just need to set the direction again.It's easy.Right?
Hello I have an opengl view and on that I have a tab bar. I'm using a tap recognizer to tap different 3d objects on screen. In the tab bar I have a button but it doesn't work because the tap recognizer catches these taps too. How do I stop this? I've already tried this:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIBarButtonItem class]]) return FALSE;
return TRUE;
}
I think I am somehow comparing wrong classess because when I debug it returns TRUE always.
Or you can just do [singleTap setCancelsTouchesInView:NO]. Example:
UITapGestureRecognizer *singleTap = [
[UITapGestureRecognizer alloc]
initWithTarget: self
action: #selector(yourSelector:)
];
[singleTap setCancelsTouchesInView:NO];
[[self view] addGestureRecognizer: singleTap];
if ([touch.view.superview isKindOfClass:[UIToolbar class]]) return FALSE;
This is how I got it to work. The superview is a UIToolbar, probably UIBarButtonIttem is a view after all.
I have a UITextField that is the subview of UIScrollView
I have there exist a single tap gesture (or perhaps the older touch) as part of UITextField that makes it the first responder. I wanted to add a double tap Gesture to the UITextField. In order to make the two Gesture's mutually exclusive I needed to overload (though this is not quite the right word because I'm not using the same name) the single tap Gesture. When I do it works fine so long as the function that it calls doesn't make the UITextField the first responder. If it does make the textfield the first responder it fails the second time it's called.... wtf. So stack, a little help would go a long way.
this is where I add the gesture
UITapGestureRecognizer * singleTextTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleTextTap:)];
singleTextTap.numberOfTapsRequired = 1;
[aTextField addGestureRecognizer:singleTextTap];
and this is where it is called
//single tap text
- (void) handleSingleTextTap:(UITapGestureRecognizer *)gestureRecognizer{
NSLog(#"handling single tap");
NSLog(#"textField gestures %#",
[gestureRecognizer.view.gestureRecognizers descriptionWithLocale:nil]);
[(UITextField *)gestureRecognizer.view becomeFirstResponder];
}
you may notice the NSLog that out puts the gestuers registered to the textField this was to check the state of my singleTextTap gesture. which is 'ended' the first time and all next times this code is never reached
The behaviour you're seeing is due to each time you send a becomeFirstResponder message to a UITextField it sets it's own gesture recognizers up. If you do a log on [textField gestureRecognizers] you'll see it sets up a lot of them. These are to deal with text editing functions such as long press for cursor movement and such. By way of adding these it cancels the ones you have setup. Easiest way to deal with this is something like this.
- (void) singleTap:(UITapGestureRecognizer*)singleTap {
if (![self.textField isFirstResponder]) {
[self.textField becomeFirstResponder];
self.label.text = #"Single Tap -> Make First Responder";
[self.label setNeedsDisplay];
}
}
- (void) doubleTap:(UITapGestureRecognizer*)doubleTap {
if (![self.textField isFirstResponder]) {
[self.textField becomeFirstResponder];
self.label.text = #"Double Tap -> Make First Responder";
[self.label setNeedsDisplay];
}
}
- (void) setupTextGestureRecognizers {
for (UIGestureRecognizer *rec in self.textField.gestureRecognizers) {
[self.textField removeGestureRecognizer:rec];
}
UITapGestureRecognizer *singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTap:)] autorelease];
UITapGestureRecognizer *doubleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTap:)] autorelease];
[singleTap setNumberOfTapsRequired:1];
[doubleTap setNumberOfTapsRequired:2];
[singleTap setCancelsTouchesInView:YES];
[doubleTap setCancelsTouchesInView:YES];
[singleTap requireGestureRecognizerToFail:doubleTap];
[self.textField addGestureRecognizer:singleTap];
[self.textField addGestureRecognizer:doubleTap];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setupTextGestureRecognizers];
self.textField.delegate = self;
}
- (BOOL) textFieldShouldReturn:(UITextField *)tf {
[tf resignFirstResponder];
if (tf == self.textField) {
[self setupTextGestureRecognizers];
}
return YES;
}
Here is an example project demonstrating this code in use.
What you're doing seems really strange, but whatever. I'll assume you know what you're doing.
You might try the following:
UITapGestureRecognizer *doubleTap = ...;
UITapGestureRecognizer *singleTap = ...;
[singleTap requireGestureRecognizerToFail:doubleTap];
This means that the single tap recognizer will only fire if the double tap one doesn't fire, effectively making them mutually exclusive.