I have a question - is there any possibilities in iPhone to make UITapGestureRecognizer respond the tap only on a part of UIImageView. Actualy, the problem is as follows - there is an UIImageView with gesture recognizer add and some part of these UIImageView is covered with other View. When tapping on this other View, UIImageView recognizes the tap. How this problem can be solved?
I'm not sure I understand your question. Do you want the gesture recognizer to be triggered when the view which overlaps the image view is tapped? If so, I guess you could just add the gesture recognizer to the overlapping view.
If you have two overlapping views and want to only handle the touch if the overlapped part was touched, I suggest adding the tap gesture recognizer to the main view and check if the overlap was touched.
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureRecognizerTriggered:)];
[self.view addGestureRecognizer:gestureRecognizer];
}
- (void)tapGestureRecognizerTriggered:(UITapGestureRecognizer *)gestureRecognizer
{
CGPoint location = [gestureRecognizer locationInView:self.view];
if (CGRectContainsPoint(self.frontView.frame, location) &&
CGRectContainsPoint(self.backView.frame, location))
{
// Handle touch
}
}
If you want to handle the touch if the touch happens in the front CGRectContainsPoint(self.backView.frame, location) from the conditional statement.
Related
i am making a chat application, and in the chat window there are uilabels in uitableviewcells. initially the keyboard will be present but when the user touches on any place on uitableview, i will make the chat window as fullscreen (dissappearing keyboard).
i cant find a way/trick to accomplish this.
i have tried the following method: by using tableview:didselectrowatindexpath, i am able to do it but, user needs to press on an existent uitableviewcell. but i want to understand the press even when uitableview is empty..
note: my chat tableview is interactive e.x. some rows will include image button which need to be pressable, so i cant just put an invisible button onto uitableview.
thank you for your thoughts
Aytunc Isseven
What you want to do is add a gesture recognizer to the UITableView that responds to the appropriate gestures. I would recommend against using UITapGestureRecognizer as the UITableView is already using taps for selecting the cells, so you might want to try the UILongPressGestureRecognizer. I put together a small sample of how you can do this as follows:
In my viewDidLoad I did the following:
UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressFrom:)];
[self.tableView addGestureRecognizer:gesture];
and the handleLongPressFrom: is as follows:
- (void)handleLongPressFrom:(UILongPressGestureRecognizer *)recognizer {
NSLog(#"handleLongPressFrom: %#", recognizer);
// Add real code here
}
The full list of gestures can be found here.
Oh, if you did want to still use tap, check out this stack overflow question. I don't know if the method presented works fully, but it'd be a good place to start.
Using UITapGestureRecognizer with a UITableView:
Okay, since the tap gesture seems to be the correct one for your use case you can try and do the following. Step 1 is to set up the gesture recognizer as I listed above using the tap gesture instead of the long press gesture.
The code in viewDidLoad is very similar with an important addition ...
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
// we need to set the gesture delegate so we can allow the tap to pass through to the
// UITableViewCell if necessary.
gesture.delegate = self;
[self.tableView addGestureRecognizer:gesture];
The handleTapFrom: function is pretty much the same with just the different gesture recognizer as the parameter.
- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
NSLog(#"handleTapFrom: %#", recognizer);
// Add real code here
}
The major changes to this approach is that we need to implement the UIGestureRecognizerDelegate protocol. Since our goal is to allow the tap gesture to pass through the UITableView to it's subviews (i.e. the UITableViewCell and it's components) we need to implement the gestureRecognizer:shouldRecieveTouch: function. The following implementation should cover what you are attempting.
#pragma mark UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// If the view that is touched is not the view associated with this view's table view, but
// is one of the sub-views, we should not recognize the touch.
if (touch.view != self.tableView && [touch.view isDescendantOfView:self.tableView]) {
return NO;
}
return YES;
}
The isDescendantOfView: function returns YES if the view it is testing against is the same as the view doing the testing, so we need to accommodate that case separately. You can generify this function by using gestureRecognizer.view instead of self.tableView, but I didn't think it was necessary in this case.
The trick is to make your viewController put a tap recognizer on the view but make it always opt out by returning NO from the delegate method "gestureRecognizerShouldBegin". That way gestureRecognizerShouldBegin gets called for every touch on the view, but you don't interfere with the normal event handling of the table.
- (void)viewDidLoad {
[super viewDidLoad];
[self detectTouchesOnView:self.tableView];
}
- (void)detectTouchesOnView:(UIView*)theView {
UITapGestureRecognizer* tapR = [[UITapGestureRecognizer alloc]initWithTarget:nil action:nil];
tapR.delegate = self;
[theView addGestureRecognizer:tapR];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
// React to the UITableView being touched E.G. by hiding the keyboard as below.
[self.view endEditing:YES];
return NO;
}
I am creating a custom UIView and adding a UITapGestureRecognizer on it. I have a handler for the tap gesture. But at the same time I want my UIView to listen to touchesBegan & touchesEnded methods. I have implemented gestureRecognizer:shouldReceiveTouch: method also but touchesBegan/touchesEnded methods does not get called. Any clue why?
Inside my custom UIView
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)iGestureRecognizer shouldReceiveTouch:(UITouch *)iTouch {
return YES;
}
Inside my view controller
MyCustomView aCustomView = [[[MyCustomView alloc] init] autorelease];
UIGestureRecognizer *myGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[aCustomView addGestureRecognizer:myGestureRecognizer];
[myGestureRecognizer release];
You need to set cancelsTouchesInView (and likely delaysTouchesBegan and delaysTouchesEnded) to NO for the gesture recognizer. The default behavior of a gesture recognizer is to avoid having both it and the view process the touch. These settings let you fine-tune that behavior.
As stated earlier, you need to set the cancelTouchesInView property to NO on your UITapGestureRecognizer.
From the Apple Docs:
cancelsTouchesInView—If a gesture recognizer recognizes its gesture,
it unbinds the remaining touches of that gesture from their view (so
the window won’t deliver them). The window cancels the previously
delivered touches with a (touchesCancelled:withEvent:) message. If a
gesture recognizer doesn’t recognize its gesture, the view receives
all touches in the multi-touch sequence.
Further reading:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIGestureRecognizer_Class/
I have a View With Navigation Bar
Actually I have taken a Image View and Put it on a navigation bar....
As I want Button Not at right or Left but at somewhere on the navigation bar
By this method I can recognize touch on view but can not recognize touch on Navigation Bar ?
Can I change anything...
In this method...
Why?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event {
CGPoint p;
p.x=0;
p.y=0;
p = [[touches anyObject] locationInView:self.nvbrCalculateBar];
NSLog(#" %f",p.x);
if(p.x==0 && q.x==0)
{
}
else
{
//Load View
}
}
You can add a UITapGestureRecognizer to your UIImageView and that should do the trick
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapEvent:)];
[yourImageView addGestureRecognizer:tap];
[tap release];
- (void)tapEvent:(UITapGestureRecognizer *)gesture {
//Do whatever you need when user taps the imageView
}
Also set the userInteractionEnabled of the imageView to YES to be able to receive the gesture recognizer events.
Hope this helps.
The UINavigationBar itself is not set to return touches, since I believe its not part of the actual UIView (for which the touchesBegan) method applies. Instead, you can push various items onto the nav bar (e.g. buttons) which you can define interactions for.
See its reference here.
USer Interaction Must be enabled of UINavigation Bar Property, And then Apply touch method..
Can you try:
[imageView setUserInteractionEnabled:NO];
This should prevent your imageview to cancel the touches.
could anyone tell me how to place a translucent black mask over the whole screen, but with the area of a particular UIView being excluded? I want to use this mask over a UITextField, which calls resignFirstResponder when the outside part of the textfield is tapped.
The subview tree would be like:
UIWindow
|-UIView
| |-UITextField
|
|-Mask
Thanks,
You can use the:
- (void)bringSubviewToFront:(UIView *)view
And send the UITextField to the front after you add the black mask view.
UPDATE
Ok this are the steps to do it (you can see the apple example for UIGestureRecognizers for more)
create a mask view (programmatically or with IB) and call it "maskView".
create a gestureRecognizer and add it to the maskView.
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
recognizer.delegate = self;
UIImageView *maskView = [[UIImageView alloc] init];
[maskView addGestureRecognizer:recognizer];
you will need to set your view controller as the delegate for "UIGestureRecognizerDelegate"
#interface YourViewController : UIViewController <UIGestureRecognizerDelegate>
add the maskView to your ViewController when you want to mask the screen. and then move the text field above the mask.
[self.view addSubView:maskView];
[self.view bringSubviewToFront:textField];
set this 2 functions:
in the first one you can set the action if the user touches the mask
- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
//resign the first responder when the user taps the mask
//you can remove the mask here if you want to
}
in the second one you tell the app not to receive touches from the textField
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// Disallow recognition of tap gestures in the segmented control.
if ((touch.view == textField)) {//checks if the touch is on the textField
return NO;
}
return YES;
}
Hope it make some sense
shani
Previously I've used the tap Detecting Window technique to detect taps in a UIWebView, but now I've tried to use gesture recognizers instead. The following code is in the viewDidLoad method of a view controller, which has a single UIWebView. This code compiles fine, but the handleTap method is never called. This seems like it should be simple.
// Configure a gesture recognizer to detect taps in the web view
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap)];
[self.myWebView addGestureRecognizer:singleTap];
[singleTap release];
[super viewDidLoad];
Set your view controller as the recognizer delegate:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap)];
recognizer.delegate = self;
[self.myWebView addGestureRecognizer:recognizer];
And enable simultaneous gesture recognition (as the UIWebView probably sets a few recognizers itself, yours are skipped) :
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Since the UIWebView does already handle a lot of touch events, it might be a bit tricky to add your own gesture recognizer.
I don't know if the user has to interact with your web view but you might try to add a UIView on top of the UIWebView and add the gesture recognizer to this view. It should still propagate unrecognized touch events to the underlying web view, thus leaving its interactivity intact.