I have been trying to add a UITapGestureRecognizer in order to make it possible to change views using buttons inside my UIPageViewControllerDataSource.
I have added the subclasses
#interface OverallViewController : UIViewController <UIPageViewControllerDataSource,UIGestureRecognizerDelegate>
#property (strong, nonatomic) UIPageViewController *pageController;
Page navigation works fine for me but when trying the following UITapGestureRecognizer inside viewDidLoad I get nothing
UIView *topbar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 52)];
topbar.backgroundColor = [UIColor colorWithRed:(245/255.0) green:(245/255.0) blue:(245/255.0) alpha:1];
left = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"nav-profile-sm.png"]];
left.frame = CGRectMake(15, 15, 25, 25);
//End add top nav
[topbar addSubview:left];
[self.view addSubview:topbar];
//Add top navigation gestures
UITapGestureRecognizer *profiletap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(profileButtonTap)];
profiletap.numberOfTapsRequired = 1;
profiletap.delegate = self;
[left addGestureRecognizer:profiletap];
No response here
-(void) profileButtonTap {
NSLog(#"Profile button tapped");
}
And nothing when I try overriding gestureRecognizer
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint touchPoint = [touch locationInView:touch.view];
NSLog(#"Touch: %f,%f", touchPoint.x, touchPoint.y);
if (touchPoint.y < 52) {
return NO; // ignore the touch
}
return YES; // handle the touch
}
When I say that I get nothing I mean that nothing is logged, the methods do not seem to be called and I am unsure how I can solve or debug this further. Thanks for any help, ideas and suggestions!
Related
UIView *superview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
UIView *subview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
UIPanGestureRecognizer *recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget: self action: #selector(handlePinch);
superview.userInteractionEnabled = YES;
subview.userInteractionEnabled = YES;
[superview addGestureRecognizer:recognizer];
I have a subview overlapping on top of a superview. The subview has 4 buttons that needs to be tappable. The superview has a pinch-zoom gesture that zooms the view. But i would like to disable the zoom on the subview.
The recognizer is fired inside the subview as well, is there a way to exclude the recognizer from the subview?
I used the simple way below:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view != subview) { // accept only touchs on superview, not accept touchs on subviews
return NO;
}
return YES;
}
UIView *superview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
superview.tag=1; //set Tag for superview
UIView *subview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
subview.tag==2; //set Tag for subview
UIPanGestureRecognizer *recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget: self action: #selector(handlePinch);
superview.userInteractionEnabled = YES;
subview.userInteractionEnabled = YES;
[superview addGestureRecognizer:recognizer];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
if(touch.view .tag==2) //if subview is touched then disable pinch gesture.
{
return NO;
}
return YES;
}
This might not be the best option, but this could also work? Other StackOverflow users please be kind, I'm new!
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
CGPoint touchPoint = [gestureRecognizer locationInView: superview];
if(CGRectContainsPoint(subview.frame, touchPoint)
{
return NO;
}
return YES;
}
Apple Docs containing CGRectContainsPoint.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGGeometry/index.html#//apple_ref/c/func/CGRectContainsPoint
I'm trying to add the move gesture of uiview inside uiscrollview but I can not disable the srcoll event of uiscrollview. I have implemented the UIScrollview with paging enable in Main class. In another class, i added uiview in it, add gesture for it but i dont know how to disable scrolling of uiscrollview.
Please give me some advice. Thanks in advance.
You need to communicate from your UIView class with gesture in it by means of delegate to the main class asking scroll view to stop scrolling and later on enabling it. I have enclosed the code.
Your UIView.h file
#protocol MyUIViewProtocol <NSObject>
- (void)setScrollViewScrollEnabled:(BOOL)enabled;
#end
#interface MyUIView : UIView
#property (weak, nonatomic) id<MyUIViewProtocol> delegate;
#end
Your UIView.m file
#implementation MyUIView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setBackgroundColor:[UIColor redColor]];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panGestureMade:)];
[self addGestureRecognizer:panGesture];
}
return self;
}
- (void)panGestureMade:(UIPanGestureRecognizer *)recognizer
{
CGPoint pointsToMove = [recognizer translationInView:self];
[self setCenter:CGPointMake(self.center.x + pointsToMove.x, self.center.y + pointsToMove.y)];
[recognizer setTranslation:CGPointZero inView:self];
//Disable the scroll when gesture begins and enable the scroll when gesture ends.
if (self.delegate && [self.delegate respondsToSelector:#selector(setScrollViewScrollEnabled:)]) {
if (recognizer.state == UIGestureRecognizerStateBegan) {
[self.delegate setScrollViewScrollEnabled:NO];
}
else if (recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStateEnded) {
[self.delegate setScrollViewScrollEnabled:YES];
}
}
}
Your main class file with scroll view in it.
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 568)];
[self.scrollView setBackgroundColor:[UIColor yellowColor]];
[self.scrollView setPagingEnabled:YES];
[self.scrollView setContentSize:CGSizeMake(320 * 3, 568)];
[self.view addSubview:self.scrollView];
MyUIView *view = [[MyUIView alloc] initWithFrame:CGRectMake(40, 100, 100, 100)];
view.delegate = self;
[self.scrollView addSubview:view];
}
- (void)setScrollViewScrollEnabled:(BOOL)enabled
{
[self.scrollView setScrollEnabled:enabled];
}
Hope this answer helps you.
I am trying to add a tap gesture from a subclassed UIImageView and then control the tap from the View Controller. I am not getting any compiling errors but "addSubview" is not displaying any image. How can make the UIImageView to be displayed?
If I try to control the tap and pan gestures from the subclassed UIImageVIew I have no problems but I would like to control these functions from the View Controller
Relevant code looks like this.
UIImageView subclass
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
//self.userInteractionEnabled = YES;
previewController = [[PreviewController alloc]init];
[previewController self];
[self addSubview:character];
// Tap Initialization code
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:(PreviewController *)self.previewController action:#selector(addCharacter:)];
[self addGestureRecognizer:tap];
self.userInteractionEnabled = YES;
}
return self;
}
View Controller
- (void)addCharacter:(UITapGestureRecognizer *)t
{
NSLog(#"add character");
imageNSArray = [NSMutableArray array];
uiImg = [UIImage imageNamed:#"homer.png"];
CGPoint loc = [t locationInView:self.view];
character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[imageNSArray addObject:character];
//Locate the imageNSArray on frameImageView area only.
[self.view addSubview:character];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panCharacter:)];
[self.character addGestureRecognizer:pan];
character.userInteractionEnabled = YES;
}
put a view behind your subclassed imageView. Apply the gestureRecognition to the new View.
You can control your tap gesture from new view. Let me know if i am not clear, or if more info needed.
I think what you want is.. .you want to show a image when user taps on screen.
Do following steps:
1. drag & drop a tap gesture recognizer on default view of your view controller.
2. connect (ctrl +) gestureRecognizer with ViewController.m
Take a look at this code. (Just modified your code)
- (IBAction)onTap:(UITapGestureRecognizer *)sender {
NSLog(#"add character");
UIImage * uiImg = [UIImage imageNamed:#"sel.png"];
CGPoint loc = [sender locationInView:self.view];
UIImageView * character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[self.view addSubview:character];
}
Let me know if this is not what you want…
Edit
better go for this code… No need to do above steps.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onTap:)];
[self.view addGestureRecognizer:tap];
self.view.userInteractionEnabled = YES;
}
- (void)onTap:(UITapGestureRecognizer *)sender
{
NSLog(#"add character");
UIImage * uiImg = [UIImage imageNamed:#"sel.png"];
CGPoint loc = [sender locationInView:self.view];
UIImageView * character = [[UIImageView alloc] initWithImage:uiImg];
character.center = loc;
[self.view addSubview:character];
}
This is what I'm trying to do:
I want to start recognizing a gesture in a subview and then, when the finger leaves the subview, let the superview take over and handle the gesture. Is that possible?
At the moment, the view in which the gesture started "wins". Is there any way to "hand over" a gesture from one view to another "on the fly", without lifting the finger off the screen?
This is the code for a simple demo:
#implementation SPWKViewController {
UIView *_innerView;
UIPanGestureRecognizer *_outerGestureRecognizer;
UIPanGestureRecognizer *_innerGestureRecognizer;
UILabel *_label;
}
- (void)loadView
{
[super loadView];
self.view.backgroundColor = [UIColor yellowColor];
_innerView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, self.view.frame.size.width - 100, 200)];
_innerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_innerView.backgroundColor = [UIColor greenColor];
_label = [[UILabel alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 40)];
_label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_label.textAlignment = NSTextAlignmentCenter;
_label.backgroundColor = [UIColor clearColor];
[self.view addSubview:_innerView];
[self.view addSubview:_label];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_outerGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[self.view addGestureRecognizer:_outerGestureRecognizer];
_innerGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[_innerView addGestureRecognizer:_innerGestureRecognizer];
}
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {
if (gestureRecognizer == _outerGestureRecognizer) {
_label.text = #"outer";
} else {
_label.text = #"inner";
}
} else {
_label.text = #"";
}
}
#end
Some background information: The actual problem I'd like to solve is this: I'd like to put a UIWebView inside of a UIScrollView. When I scroll to the bottom of the UIWebView, I want the parent UIScrollView to "take over" and keep scrolling without having to lift the finger off the screen first. I figured that in order to achieve that, I'd need to "hand over" the gesture from the UIWebView to the parent UIScrollView.
Thank you!
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
container = [[UIView alloc] initWithFrame:self.view.frame];
UIImageView* main_im0 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon1.png"]];
[container addSubview:main_im0];
[self.view addSubview:container];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *tt = [touches anyObject];
UIImageView *touchedview=(UIImageView*)[tt view];
NSArray *views = [container subviews];
for (UIImageView* im in views)
{
UIImageView* focus=im;
if (touchedview==focus)
{
}
}
}
I have this piece of code that setting up an ImageView called main_im0 which is put into a UIView container which then put into view. When I clciked on the main_im0, I expect the touch function would hit the condition of touchedview==focus. However, I couldn't get that condition activated? what's wrong?
Please enable
main_im0.userInteractionEnabled = YES;
by default it's No for UIImageView
Jason, maybe I am misinterpreting your code but aren't you going a round about way of achieving a tap gesture on a UIView?
You can use:
// enable user interaction with this view
main_img0.userInteractionEnabled = YES;
// setup a tap gesture to call a method once triggered (like a javascript mouseClick event)
UITapGesture *tapGesture = [[UITapGesture alloc] initWithTarget:self selector:#selector(myMethodToDoSomething)];
[main_img0 addGestureRecognizer:tapGesture];
// if you are not using Automatic Reference Counting, then remember to release your allocated tapGesture object
[tapGesture release];
...somewhere later in your code....
// method to do something
-(void)myMethodToDoSomething
{
NSLog(#"This method executed");
}
Now when you tap on your main_img0 view, the method "myMethodToDoSomething" will execute
By the way, if you just want a custom looking button with your own photoshop designed image, you can simply create a UIButton with code and set the background image property of the UIButton. Like so:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
[button setImage:[UIImage imageNamed:#"mybutton.png"] forControlState:UIControlStateNormal];