I am trying to make a UILabel that if I click I can edit it. I have a hidden textfield.
Per this answer: How to customize UILabel clickable
I tried the following:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
tapInput = [[UIGestureRecognizer alloc] initWithTarget:self action:#selector(didTapLabel)];
[lblInput setUserInteractionEnabled:YES];
[lblInput addGestureRecognizer:tapInput];
}
-(void)didTapLabel
{
[txtHidden becomeFirstResponder];
}
But my break point inside didTapLabel is not firing. Everything is hooked up correctly on the storyboard.
Use this code, It's worked. Tested.
UILabel * clickMeLbl=[[UILabel alloc] initWithFrame:CGRectMake(75,30,170,30)];
clickMeLbl.text = #"Click Me";
clickMeLbl.font = [UIFont fontWithName:#"Helvetica-Bold" size: 18.0f ];
clickMeLbl.textAlignment = NSTextAlignmentCenter;
clickMeLbl.textColor = [UIColor blackColor];
[self.view addSubview:clickMeLbl];
clickMeLbl.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(didTapLabelWithGesture:)];
[clickMeLbl addGestureRecognizer:tapGesture];
- (void)didTapLabelWithGesture:(UITapGestureRecognizer *)tapGesture {
NSLog(#"Click Me Label Clicked");
}
Try enabling user interaction here for label,Worked for me, and please use UITapGesture instead of UIGesture
And Textfield should be below uilabel because if the textfield is above label then uilabel's user interaction won't be considered
Related
I added custom UIView with XIB. I just tried to perform button actions and tapgestures , nothing is working eventhough user interaction enabled for all elements including ContentView.
Intializing UIView
-(void)initializeSubviews {
self.backgroundColor = [UIColor clearColor];
[[[NSBundle mainBundle]loadNibNamed:#"DatesView" owner:self options:nil]firstObject];
[self addSubview:self.contentView];
// self.contentView.frame = self.bounds;
[self.fromDateButton addTarget:self action:#selector(tapOnfromDate:) forControlEvents:UIControlEventTouchUpInside];
self.fromDateButton.backgroundColor = [UIColor redColor];
}
Tap gestures
UITapGestureRecognizer *fromDateTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnfromDate)];
[datesView.contentView addGestureRecognizer:fromDateTapRecognizer];
[datesView.fromMonthYearLabel addGestureRecognizer:fromDateTapRecognizer];
[datesView.fromDayLabel addGestureRecognizer:fromDateTapRecognizer];
Button Action
[datesView.fromDateButton addTarget:self action:#selector(tapOnfromDate) forControlEvents:UIControlEventTouchUpInside];
UIView interface
Couple things...
1) By commenting out this line in your view subclass:
// self.contentView.frame = self.bounds;
the view ends up with a frame of 0,0. The button and labels etc are visible because the view defaults to .clipsToBounds = NO, but the objects do not receive user interaction.
2) A UITapGestureRecognizer is a single instance. If you add it to one view, then try to add it to additional views, it will only exist on the last view to which is was added.
Try it like this (be sure to un-comment the above line):
- (void)viewDidLoad {
[super viewDidLoad];
// do all the loading stuff here...
// local declaration
UITapGestureRecognizer *tapRecognizer;
// Optional --- make *sure* user interaction is enabled
[datesView.contentView setUserInteractionEnabled:YES];
[datesView.fromMonthYearLabel setUserInteractionEnabled:YES];
[datesView.fromDayLabel setUserInteractionEnabled:YES];
// new recognizer
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnfromDate:)];
// add it to contentView
[datesView.contentView addGestureRecognizer:tapRecognizer];
// new recognizer
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnfromDate:)];
// add it to fromMonthYearLabel
[datesView.fromMonthYearLabel addGestureRecognizer:tapRecognizer];
// new recognizer
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnfromDate:)];
// add it to fromDayLabel
[datesView.fromDayLabel addGestureRecognizer:tapRecognizer];
// add target action to fromDateButton
[datesView.fromDateButton addTarget:self action:#selector(fromDateButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) tapOnfromDate: (UITapGestureRecognizer *)recognizer {
NSLog(#"Tapped! %#", recognizer.view);
}
- (void) fromDateButtonTapped: (id)sender {
NSLog(#"Button Tapped! %#", sender);
}
I added tapGesture for self.view and UILabel (subview of mainView), each performs different selectors.
But the only main view tapGesture is being called and label tapgesture is not being called. How it is handled?
Here is the code:
UITapGestureRecognizer *tapGesForSelf = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesForSelf:)];
[self.view addGestureRecognizer:tapGesForSelf];
UITapGestureRecognizer *tapLblClick = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesForLbl:)];
[lbl addGestureRecognizer:tapLblClick];
For two selectors only one method is called tapGesForSelf.
Here lbl is the subview of self.view.
Try this
- (void)viewDidLoad {
[super viewDidLoad];
[_lbl setUserInteractionEnabled:YES];
UITapGestureRecognizer *tapGesForSelf = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesForSelf:)];
[self.view addGestureRecognizer:tapGesForSelf];
UITapGestureRecognizer *tapLblClick = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGesForLbl:)];
[_lbl addGestureRecognizer:tapLblClick];
[tapGesForSelf requireGestureRecognizerToFail:tapLblClick];
}
- (void)tapGesForSelf:(UITapGestureRecognizer *)gesture
{
NSLog(#"self");
}
- (void)tapGesForLbl:(UITapGestureRecognizer *)gesture
{
NSLog(#"label");
}
I post answer for your question now once I tried and it worked well.
First see the label in design.I set label text as "Tap Me"
Now I set the code for view and label
- (void)viewDidLoad
{
[super viewDidLoad];
//TapGesture for Label
UITapGestureRecognizer *tapLabel = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(actionTapLabel:)];
tapLabel.delegate = self;
tapLabel.numberOfTapsRequired = 1;
lblTapMe.userInteractionEnabled = YES;
[lblTapMe addGestureRecognizer:tapLabel];
//TapGesture for View
UITapGestureRecognizer *tapMainView = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(actionTapMainView:)];
tapMainView.delegate = self;
tapMainView.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapMainView];
}
//Action method for Label
-(void)actionTapLabel:(UITapGestureRecognizer *)gestureOnLabel{
UILabel *label = (UILabel *)gestureOnLabel.view;
NSLog(#"Lable text is - %#",label.text);
}
//Action method for View
-(void)actionTapMainView:(UITapGestureRecognizer *)gestureOnMainView{
NSLog(#"The Main view is tapped");
}
Output Screenshot
Please setUserInteractionEnabled:YES for interact the TapGesture
[lbl setUserInteractionEnabled:YES];
I am using the following code to attach gesture recognizers to a custom view. But for some reason I am not able to get the gestures to work.
for(NSString *option in _options) {
UIView *blind = [self createBlind:option];
blind.userInteractionEnabled = YES;
blind.tag = index;
[self addSubview:blind];
[self addGravityBehaviorToBlind:blind];
[self addCollisionBehaviorToBlind:blind];
[self addElasticityBehaviorToBlind:blind];
[self registerGestureRecognizer:blind];
_spacingY += 44;
index++;
}
}
-(void) registerGestureRecognizer:(UIView *) blind {
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(blindTapped:)];
[blind addGestureRecognizer:tapGestureRecognizer];
}
-(void) blindTapped:(UITapGestureRecognizer *) recognizer { <-- THIS NEVER GETS CALLED
NSLog(#"blindTapped");
}
For some reason the blindTapped method never gets called even if I tap on the blind view.
UPDATE:
Yes, I see the views on the screen. The views (blind) is a subview in another view. The parent view gets added to the controller.view. There is no place where I have disabled interaction.
Here is the createBlind method:
-(UIView *) createBlind:(NSString *) option {
UIView *blind = [[UIView alloc] initWithFrame:CGRectMake(0, _spacingY, 200, 44)];
blind.layer.borderWidth = 1.0f;
blind.layer.borderColor = [UIColor whiteColor].CGColor;
UILabel *optionTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, blind.bounds.size.width, blind.bounds.size.height)];
optionTitleLabel.text = option;
optionTitleLabel.font = [UIFont fontWithName:#"GillSans" size:17];
optionTitleLabel.textColor = [UIColor whiteColor];
optionTitleLabel.textAlignment = NSTextAlignmentCenter;
[blind addSubview:optionTitleLabel];
return blind;
}
I have removed all the gravity and UIKit methods but still I am not able to trigger the tap gesture.
SOLUTION:
When adding the custom view to my controller.view I was not setting the frame. Once the frame was setup everything worked.
All Boxes is UITextFields. I want change background color when user long press on UITextField.
Which TextField had a long press that UITextField color is change, not all UITextFields.
Try to use like this...
- (void)viewDidLoad
{
[super viewDidLoad];
UILongPressGestureRecognizer *gs = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:#selector(changeBackground:)];
[textFld addGestureRecognizer:gs];
}
- (void)changeBackground:(UIGestureRecognizer *)gs
{
[self.view endEditing:YES]; // Edited
UITextField *txtFld = (UITextField *)gs.view;
[txtFld setBackgroundColor:[UIColor redColor]];
}
You can use UILongPressGestureRecognizer. Please note that one gesture recognizer can be attached to one view.
Here is code example
- (void)viewDidLoad
{
[super viewDidLoad];
//Array that holds your textfields
NSArray *myTextFields;
for (UITextField *textField in myTextFields) {
//Creating UILongPressGestureRecognizer
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
//Attaching it to textfield
[textField addGestureRecognizer:longPressGestureRecognizer];
}
}
//Handling long press
- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
UITextField *textField = (UITextField *)gestureRecognizer.view;
textField.backgroundColor = [UIColor greenColor];
}
I have a UIScrollView and inside this I have UILabels. I need to detect touch events for the UILabels. At the moment, it is detecting the touch inside the second label only. It ignores the first.
I have the code -
Creating the UIScrollView
backGroundView = [[UIScrollView alloc] init];
backGroundView.frame= self.view.frame;
backGroundView.userInteractionEnabled = YES;
[backGroundView setScrollEnabled:YES];
backGroundView.showsVerticalScrollIndicator = YES;
backGroundView.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
backGroundView.delegate = self;
[self.view addSubview:backGroundView];
Creating the UILabel
UILabel *OneDay = [[UILabel alloc] initWithFrame:CGRectMake(15, stockChart.bounds.origin.y + stockChart.bounds.size.height + 35, 40, 30)];
OneDay.text = #"1d";
OneDay.tag = 1;
OneDay.userInteractionEnabled = YES;
OneDay.layer.borderColor = [UIColor grayColor].CGColor;
OneDay.layer.borderWidth = 1.0f;
OneDay.textAlignment = UITextAlignmentCenter;
[OneDay addGestureRecognizer:detectTimeFrameChange];
[backGroundView addSubview:OneDay];
UILabel *FiveDay = [[UILabel alloc] initWithFrame:CGRectMake(45, stockChart.bounds.origin.y + stockChart.bounds.size.height + 35, 40, 30)];
FiveDay.text = #"5d";
FiveDay.tag = 2;
FiveDay.userInteractionEnabled = YES;
FiveDay.layer.borderColor = [UIColor grayColor].CGColor;
FiveDay.layer.borderWidth = 1.0f;
FiveDay.textAlignment = UITextAlignmentCenter;
[FiveDay addGestureRecognizer:detectTimeFrameChange];
[backGroundView addSubview:FiveDay];
Creating the gesturerecognizer
UITapGestureRecognizer *detectTimeFrameChange = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(timeFrameLabelTapped:)];
detectTimeFrameChange.numberOfTapsRequired = 1;
[backGroundView addGestureRecognizer:detectTimeFrameChange];
Handling gesture
-(void)timeFrameLabelTapped:(UITapGestureRecognizer*)recognizer{
if (recognizer.view.tag == 1) {
NSLog(#"One pressed");
}
else if (recognizer.view.tag == 2){
NSLog(#"2 pressed");
}
}
You can use this :
UITapGestureRecognizer *labelTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(labelTapped)];
labelTap.numberOfTapsRequired=1;
[yourLabel addGestureRecognizer:labelTap];
handle the touch tap event inside labelTapped method:
-(void)labelTapped
{
//your code to handle tap
}
Touch events are not detected on UIScrollview for getting your requirement add tap gestures to your label.
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured)];
[OneDay addGestureRecognizer:singleTap];
-(void)singleTapGestureCaptured{
NSLog(#"touch detected");
}
You can find using tapgesturerecogniser like that...
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[self.scrollview addGestureRecognizer:singleFingerTap];
//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
if(recognizer.view.tag == 1){}
//Do stuff here...
}
Where have you written the touchesBegan?
If you want to detect the touches in the label you'll have to create a subclass of label and write your touchesBegan there to detect the touch events
The problem here is that you are trying to use the same gesture recognizer for multiple views. A gesture recognizer can only be attached to a single view at once. You are only receiving events from the last view, because that is the view the recognizer is currently attached to. To fix the issue, simply create a gesture recognizer for each view you want to detect touches in.