UITapGestureRecognizer not working on custom UIView class - ios

I've made a custom view class. I'm initializing it in my view controller class. I've enabled user interaction then also it's not working. I've searched it in similar questions but most of them say to enable user interaction.
Here's the code I've written.
#interface ProfileCreatorViewController (){
SectionTitleView *ProfileTitle;
CGRect mainFrame;
}
#end
#implementation ProfileCreatorViewController
- (void)viewDidLoad {
[super viewDidLoad];
mainFrame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + NAVBAR_HEIGHT, self.view.frame.size.width, self.view.frame.size.height);
CGRect profileFrame = CGRectMake(mainFrame.origin.x + 5, mainFrame.origin.y, mainFrame.size.width - 20, 50);
ProfileTitle = [[SectionTitleView alloc]initWithFrame:profileFrame withTitle:#"Profile" withUnderLineColor:[UIColor blackColor] withDownButton:[UIImage imageNamed:#"rightArrow"]];
[self.view addSubview:ProfileTitle];
UITapGestureRecognizer *recog = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(downButtonClicked)];
[ProfileTitle addGestureRecognizer:recog];
ProfileTitle.userInteractionEnabled = YES;
}
-(void) downButtonClicked{
NSLog(#"clicked");
}

You can check couple of things here
profileFrame's height and width are not very small (print profileFrame)
ProfileTitle is not complete transparent (Gesture will also not work when view's alpha is very close to 0)
ProfileTitle is not obscured by any other view (use visual debugger for that)

#interface ProfileCreatorViewController ()<UIGestureRecognizerDelegate>{
SectionTitleView *ProfileTitle;
CGRect mainFrame;
}
#end
#implementation ProfileCreatorViewController
- (void)viewDidLoad {
[super viewDidLoad];
mainFrame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + NAVBAR_HEIGHT, self.view.frame.size.width, self.view.frame.size.height);
CGRect profileFrame = CGRectMake(mainFrame.origin.x + 5, mainFrame.origin.y, mainFrame.size.width - 20, 0);
ProfileTitle = [[SectionTitleView alloc]initWithFrame:profileFrame withTitle:#"Profile" withUnderLineColor:[UIColor blackColor] withDownButton:[UIImage imageNamed:#"rightArrow"]];
[self.view addSubview:ProfileTitle];
UITapGestureRecognizer *recog = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(downButtonClicked:)];
recog.delegate=self;
[ProfileTitle addGestureRecognizer:recog];
ProfileTitle.userInteractionEnabled = YES;
}
-(void) downButtonClicked:(UITapGestureRecognizer *)sender{
NSLog(#"clicked");
}
Add a delegate and change your method signature

Try these..
create property of your custom view like these..and also import it in your ProfileCreatorViewController.h file like these..
#import "SectionTitleView.h"
#property (nonatomic , strong) SectionTitleView *previewView;
Add UIGestureRecognizerDelegate
#interface ProfileCreatorViewController ()<UIGestureRecognizerDelegate>
{
SectionTitleView *ProfileTitle;
CGRect mainFrame;
}
set NumberOfTapsRequired if you want
UITapGestureRecognizer *recog =
[[UITapGestureRecognizer alloc]initWithTarget:self
action:#selector(downButtonClicked:)];
ProfileTitle.userInteractionEnabled = YES;
[recog setNumberOfTapsRequired:1]; //No. of taps..
[ProfileTitle addGestureRecognizer:recog];
and also its method
-(void) downButtonClicked:(UITapGestureRecognizer*)gesture
{
NSLog(#"Taped");
}
i hope it helps..

You need the UIGestureRecognizerDelegate inside the header file.
Also create a property to hold the UITapGestureRecognizer inside:
#property (strong, nonatomic) UITapGestureRecognizer tapGesture;
You also shouldn't create the UITapGestureRecognizer inside the parent class. The ProfileTitle should generate this by itself. So you'd better insert the code inside viewDidLoad inside SectionTitleView.
FYI: And don't use capitalized variable names

Related

UITapGestureRecognizer not working with UIImageView Custom class

UITapGestureRecognizer is not working with my UIImageView Class on my UIViewController.
HousePictureView *pictureHouse = [[HousePictureView alloc] init:[dictionary objectForKey:#"photo_url"]];
UITapGestureRecognizer *picturestap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showpictures)];
picturestap.numberOfTapsRequired = 1;
[pictureHouse addGestureRecognizer:picturestap];
[parentScroll addSubview:pictureHouse];
HousePictureView.m
#interface HousePictureView() {
CGFloat screenwidth;
}
#property (strong, nonatomic) UIImageView *pictureView;
#end
#implementation HousePictureView
-(id)init:(NSString*)url
{
screenwidth = [UIScreen mainScreen].bounds.size.width; // Width of this screen
if(self = [super init])
{
_pictureView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,screenwidth,300)];
[_pictureView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[Functions resizeImage:[UIImage imageNamed:#"nophoto"] newSize:CGSizeMake(screenwidth,300)]];
_pictureView.userInteractionEnabled = YES;
[self addSubview:_pictureView];
}
return self;
}
#end
HousePictureView.h
#interface HousePictureView : UIImageView
- (id)init:(NSString*)url;
#end
Why does it not possible to have an event while userInteractionEnabled form views parents are activated?
Thank you for your help :)
mmmhhh you have created an UIImageView custom class with a property UIImageView added like a subview. Why?
Just use "self".
It does not work because you're adding a tap gesture on a UIImageView that is under another.

UIScrollView dismisskeyboard not working

I have a textfield on UIScrollview.
When the user taps outside of UITextfield, I use UIScrollViewKeyboardDismissModeInteractive to dismiss the keyboard. But it is not dismissing the keyboard.
What is wrong with my code?
m_scrollProfile = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 300, 300)];
m_scrollProfile.backgroundColor = kBGWhiteColor;
m_scrollProfile.userInteractionEnabled = YES;
[self.m_bgImageView addSubview:m_scrollProfile];
m_scrollProfile.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
I encountered the same issue recently. In my header, I added <UITextFieldDelegate> as follows:
#interface YourClass : UIViewController <UITextFieldDelegate>
I added this in my viewDidLoad:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(dismissKeyboard:)];
[self.view addGestureRecognizer:tap];
and
self.myTextField.delegate = self;
and this method down below:
- (void)dismissKeyboard:(UITapGestureRecognizer *)recognizer {
NSLog(#"Dismiss keyboard");
[self.view endEditing:YES];
}
Not sure what else is going on w/ your implementation, but it works in the app I'm currently working on when the user clicks outside the UITextField.

Add a UITapGestureRecognizer to a subview

I have been searching for hours ... Needless to say, I'm rather new in programming.
My goal is to display a subview programmatically and to remove it by tapping on it.
Already working: Displaying the subview and removing it by tapping on the view (code below).
Doesn't work - whatever I try: Removing the subview by tapping exclusively on the subview.
Thanks for your help!
My .h-file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIImageView *canvas;
UIImageView *square;
}
#property (nonatomic, strong) UIImageView *canvas;
#property (nonatomic, strong) UIImageView *square;
#property (nonatomic) NSUInteger numberOfTouchesRequired;
- (void)handleSingleTap: (UITapGestureRecognizer *)singleTapGestureRecognizer;
#end
My .m-file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize canvas;
#synthesize square;
- (void)handleSingleTap: (UITapGestureRecognizer *)singleTapGestureRecognizer {
NSLog(#"tapGesture");
[square removeFromSuperview];
}
- (void)loadView {
canvas = [[UIImageView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame]];
[canvas setImage:[UIImage imageNamed:#"canvas.png"]];
self.view = canvas;
square = [[UIImageView alloc] initWithFrame:CGRectMake(170, 320, 40, 40)];
[square setImage:[UIImage imageNamed:#"square.png"]];
[self.view setUserInteractionEnabled:YES];
[canvas addSubview:square];
NSLog(#"square");
}
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
NSLog(#"initialize");
singleTapGestureRecognizer.numberOfTapsRequired = 1;
NSLog(#"number of taps");
[self.view addGestureRecognizer:singleTapGestureRecognizer];
NSLog(#"square gestureRecognizer");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If you want to remove a subview exclusively, when you tap on that view, then you will need to add tap gesture on that view
[square addGestureRecognizer:singleTapGestureRecognizer];
rather than
[self.view addGestureRecognizer:singleTapGestureRecognizer];
Edit
Also you will need to setUserInteractionEnabled to YES of UIImage because UIImage's setUserInteractionEnabled is default to NO.
[square setUserInteractionEnabled:YES];
Instead of
[self.view addGestureRecognizer:singleTapGestureRecognizer];
you should say
[square addGestureRecognizer:singleTapGestureRecognizer];

Adding action to custom uiview

I have been trying to do this simple thing : adding an action to a simple custom view. I have looked over the internet and found two "easy" solution :
UITapGestureRecognizer
UIButton
I want to do this programmatically and I just need to handle the tap.
Here is my code so far, I've tried both solutions separately and together and it doesn't work !
.m
#import "AreaView.h"
#implementation AreaView
#define GREY 27.0/255.0
#define PINK_R 252.0/255.0
#define PINK_G 47.0/255.0
#define PINK_B 99.0/255.0
- (id) initWithFrame:(CGRect)frame imageName:(NSString *)imageName areaName:(NSString *)areaName minimumSpending:(int)minimumSpending andCapacity:(int)capacity
{
self = [self initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithRed:GREY green:GREY blue:GREY alpha:1];
self.userInteractionEnabled=YES;
//Init variables
_areaName=areaName;
_capacity=capacity;
_minimumSpending=minimumSpending;
//Image view
_logoImageView = [[UIImageView alloc]initWithFrame:CGRectMake(5, 4, 66, 50)];
//_logoImageView.image = [UIImage imageNamed:imageName];
_logoImageView.backgroundColor = [UIColor grayColor];
//Label
_areaNameLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 54, 76, 18)];
_areaNameLabel.textAlignment = NSTextAlignmentCenter;
_areaNameLabel.textColor = [UIColor whiteColor];
_areaNameLabel.font = [UIFont systemFontOfSize:12.0];
_areaNameLabel.text = areaName;
//button
_button = [[UIButton alloc]initWithFrame:self.bounds];
_button.userInteractionEnabled=YES;
_button.backgroundColor=[UIColor yellowColor];
[_button addTarget:self action:#selector(handleTap:) forControlEvents:UIControlEventTouchUpInside];
//tap gesture racognizer
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setDelegate:self];
[self addGestureRecognizer:tapRecognizer];
[self addSubview:_logoImageView];
[self addSubview:_areaNameLabel];
[self addSubview:_button];
}
return self;
}
-(void)handleTap:(UIButton *)button
{
NSLog(#"tapped!");
}
-(void)tapped:(UITapGestureRecognizer *)recognizer
{
NSLog(#"tapped!");
}
#end
.h
#import <UIKit/UIKit.h>
#interface AreaView : UIView <UIGestureRecognizerDelegate>
#property (nonatomic) UIImageView *logoImageView;
#property (nonatomic) UILabel *areaNameLabel;
#property (nonatomic) NSString *areaName;
#property (nonatomic) int minimumSpending;
#property (nonatomic) int capacity;
- (id) initWithFrame:(CGRect)frame imageName:(NSString *)imageName areaName:(NSString *)areaName minimumSpending:(int)minimumSpending andCapacity:(int)capacity;
#property (nonatomic, strong) UIButton *button;
#end
Thanks for your help!
EDIT
The problem is that both handleTap and tapped are never fired even if I comment the button solution or the tap gesture one to test them separately. For the button implementation, I can see it on my interface but clicking on it does nothing.
My UIView is then added programmatically several times (for several views) in a UIScrollview.
EDIT 2
The problem is more complicate than that. The custom view is inside a scrollview which is inside another different custom view whose main function is to rewrite hittest, so that touches on this view are held by the scrollview. (Here is the purpose of all that).
It seems that as long as hittest is involved, it doesn't work.
Implement this delegate method, which will help you.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
id touchedView = gestureRecognizer.view;
if ([touchedView isKindOfClass:[UIButton class]])
{
return NO; //It won't invoke gesture method, But it'll fire button method.
}
return YES;
}
I'm not sure why your UIButton and UITapGestureRecognizer selectors aren't firing. However another option to handle taps on a view is to simply override the touchesEnded:withEvent method:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
//handle a tap
}
That way, you won't have to create a UIButton or a UITapGestureRecognizer object at all.

iOS touchesBegan being overridden by UIScrollView. Not a delay issue. Can't use gesture recognizer in this case

So I read quite a bit, but still I can't find the solution.
I have a UIViewController which is creating (programatically) a UIScrollView, which Contains a UIView and a UIImage. The UIView lies on top of the rest.
This UIView generates some UIImageViews which I need to get feedback from when tapped. I need to know which image was tapped by getting their tags. That's why I can't use gesture recognizer, since it can only be called on one view.
If I call this:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
NSLog(#"tag=%#", [NSString stringWithFormat:#"%i", touch.view.tag]);
}
On the view (called GraphView, which has it's own class) I get what I need. Still, I need to do this from the ViewController side because I have to open modal window, navigation controllers, etc... If I use that same code on the ViewController nothing happens. If I disable User Interaction on the UIScrollView it works. If I disable the delay on the UIScrollView nothing happens. No matter how long you press you get nothing. touchesBegan doesn't get called at all even if the delay is enabled.
Here's the part of the implementation of the ViewController where I generate the Views:
// ScrollView
CGRect frame = CGRectMake(0, 0, 480, 320);
myScrollView = [[UIScrollView alloc] initWithFrame:frame];
myScrollView.backgroundColor = [UIColor blackColor];
myScrollView.showsVerticalScrollIndicator = YES;
myScrollView.showsHorizontalScrollIndicator = YES;
myScrollView.userInteractionEnabled = YES;
myScrollView.contentSize = CGSizeMake(SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
myScrollView.delegate = self;
[self.view addSubview:myScrollView];
// Add UIImage for background
UIImageView *backgroundGraph = [[UIImageView alloc] initWithFrame:CGRectMake (0,0,SCROLLVIEW_WIDTH,SCROLLVIEW_HEIGHT)];
backgroundGraph.image = [UIImage imageNamed:#"graph_background.png"];
backgroundGraph.userInteractionEnabled = YES;
[myScrollView addSubview:backgroundGraph];
//[self.view addSubview:backgroundGraph];
[backgroundGraph release];
// Add View for Graph.
GraphView *graphViewC = [[GraphView alloc] init];
self.graphView = graphViewC;
graphView.tag = 200;
graphView.userInteractionEnabled = YES;
graphView.frame = CGRectMake(0, 0, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
graphView.backgroundColor = [UIColor clearColor];
[myScrollView addSubview:graphView];
//[self.view addSubview:graphView];
.h file on ViewController looks like this:
#import <UIKit/UIKit.h>
#class GraphView;
#interface TrackingViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *myScrollView;
GraphView *graphView;
int someNum;
#define SCROLLVIEW_HEIGHT 273
#define SCROLLVIEW_WIDTH 599
}
#property (nonatomic, retain) GraphView *graphView;
- (void) openModal;
//- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer;
#property (nonatomic, retain) UIScrollView *myScrollView;
#end
As always, I am thankful to everyone who can help with any ideas(and I've gotten a lot of help here always, so thanks in advance :-) ).

Resources