How to set touch events in subviews? - iphone

i have a main view controller with two subview in it,one is note-view and other one is share-view . When i click the cell of the tableview that is in the main-view controller ,it popups note-view,there is button in the note-view ,if the user tap the button it pop sup a another subview ,the share-view .But i need to close the share view when the user tap the note-view.Is that possible to implement a touch event in a subview ?
I have done this coding but result is error
in viewdidload
NotesView *label =[[NotesView alloc]init];
UITapGestureRecognizer *tapGesture =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(NoteTap)] autorelease];
[label addGestureRecognizer:tapGesture];
[tapGesture release];
then
-(void)NoteTap
{
UIView *langview = (UIView *)[self.view viewWithTag:120];
//ViewWithTag Number should be same as used while allocating
[langview removeFromSuperview];
}

Inside touchesBegan: of the view controller, you can check to see if a touch event takes places within the frame of the subview like so.
CGPoint touchPoint = [touch locationInView:self];
if (CGRectContainsPoint(label.frame, touchPoint)) {
UIView *langview = (UIView *)[self.view viewWithTag:120];
[langview removeFromSuperview];
}

Related

Hide UITableview when touches on screen except that table view

am having a scroll view with many text fields when we start editing text field displays tableview below.
when we touches anywhere on screen have to hide table view and that is fine and we touch on tableview cell the text in that cell is displayed in textfield
My problem is when i touches on Uitableviewcell not getting the data in uitextfield .
help me please...
my code is
UITapGestureRecognizer *tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismisstable)];
tapGesture1.cancelsTouchesInView = NO;
[testScroll addGestureRecognizer:tapGesture1];
[tapGesture1 release];
-(void)dismisstable
{
self.autocompletetableview.hidden=YES;
}
First just check tableView datasource and delegate
yourTableView.delegate=self;
yourTableView.dataSource=self;
AND
Just add UITapGestureRecognizer
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
[scr addGestureRecognizer:singleTap];
}
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
//Get touch point
//CGPoint touchPoint=[gesture locationInView:scr];
//Hide tableView
[self.yourTableView setHidden:YES];
}
Follow my answer for more dismissing the keyboard from a UITextField,UITextView as a subview of UIScrollView?

how can I distinguish which part of UITableViewCell has been clicked

I have created a UITableView with a custom UITableViewCell. My cell includes one UIImageView on the left and UITextView on the right.
Inside UITableViewController, I set both image and text in tableview cellForRowAtIndexPath.
Everything shows fine but now I need to implement didSelectRowAtIndex and I need to distinguish if UIImageView or UITextView of the cell has been clicked.
Let's say, image clicking is representing delete action and the rest of the cell editing action.
Rather than adding the gesture recognisers to each individual cell, you can add one to the table view and determine which cell was selected from the point of the users touch, and then determine if the user touched the image or the cell.
First make sure your controller adopts the UIGestureRecognizerDelegate protocol.
#interface MyTableViewController() <UIGestureRecognizerDelegate>
#end
Then add the UIGestureRecognizer to the UITableView when the view loads.
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
singleTap.delegate = self;
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self.tableView addGestureRecognizer:singleTap];
}
This delegate method determines if the handleTap: method should be executed. If it can find an indexPath from the users touch, then it returns YES otherwise it returns NO.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
UITableView *tableView = (UITableView *)gestureRecognizer.view;
CGPoint p = [gestureRecognizer locationInView:gestureRecognizer.view];
if ([tableView indexPathForRowAtPoint:p]) {
return YES;
}
return NO;
}
Once we have determined if the user has clicked in a cell, the handleTap: method is called, which then decides if the user touched the image, or any other part of the cell.
- (void)handleTap:(UITapGestureRecognizer *)tap
{
if (UIGestureRecognizerStateEnded == tap.state) {
UITableView *tableView = (UITableView *)tap.view;
CGPoint p = [tap locationInView:tap.view];
NSIndexPath* indexPath = [tableView indexPathForRowAtPoint:p];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGPoint pointInCell = [tap locationInView:cell];
if (CGRectContainsPoint(cell.imageView.frame, pointInCell)) {
// user tapped image
} else {
// user tapped cell
}
}
}
You could subclass UITableViewCell and override touchesEnded.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
UIView *hitView = [self hitTest:location withEvent:event];
if (hitView == myImageView) ...;
if (hitView == myTextView) ...;
}
You need to keep some reference to your UIImageView and UITextView (they should probably be properties of your cell).
You can of course override touchesBegan instead of touchesEnded, depends on what functionality you want to achieve.
a very abstract and general answer is to do the following
For each UIImage and UILabel you add set their tag to be the indexPath.row
//When creating the label and image add a recognizer to them
label.tag = indexPath.row;
imageView.tag = indexPath.row;
Then add a UITapGestureRecognizer on each image and label, like so
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTap:)];
[label addGestureRecognizer:recognizer];
[imageView addGestureRecognizer:recognizer];
}
- (void) handleTap:(UITapGestureRecognizer*)recognizer
{
UIView *view = recognizer.view;
int row = view.tag;
if ([view isKindOfClass:[UILabel class]]) {
//Row is row
//and the label is pressed
}
if ([view isKindOfClass:[UIImageView class]]) {
//Row is row
//and the imageview is pressed
}
}
Make the image a UIButton. When the button's action is triggered, you know the user tapped the image (cell will NOT be selected). If cell is selected, you know the user tapped somewhere else on the row (including text view or label).
Also, set the button's tag property to, e.g. the cell's row index so you can know which row's image was tapped.
you have two option is to implement :-
1--add UITapGestureRecognizer in your "uitableviewcell" and make it point to image view
and pass "indexpath" as parameter to selector and make the delegate pass it to tableviewcell
UILabel *label = =[UILabel alloc]init];
label.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(labelTap)] autorelease];
[label addGestureRecognizer:tapGesture];
-(void)labelTap{
[delegate performselector#selector(labeltapped:)withobject:indexpath];
}
2- Second way is to check the sender of DidSelectRowAtIndexPath of type [imageview or label];
but i prefer the first way

Removing subView from SuperView [duplicate]

I have added a few buttons to self.view. When the user clicks on one button, i will load another view (subView). My code where i am loading the subView is shown below
subView = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.scrollView.contentSize.width, self.scrollView.contentSize.height)];
subView.tag=1;
// and then i add various other components to it
[self.view addSubview:subView]; // and finally add it to the view
When the user touches this view, i detect it and remove the view (i have already done the detection part).
This is how i am removing the view
UIView *v = [self.subView viewWithTag:1];
v.hidden = YES;
[v endEditing:YES];
[v removeFromSuperview];
The view dissapears, but i can't click on the buttons or anything that was on the self.view. When i hold the mouse cursor on a button for awhile i could click it otherwise i can't. How can i solve this ?
Try removing the subview like this:
for (UIView *subView in self.view.subviews) {
if (subView.tag == (int)yourSubViewTag) {
[subView removeFromSuperview];
}
}
Should this line:
UIView *v = [self.subView viewWithTag:1];
really be:
UIView *v = [self.view viewWithTag:1];
?
I think your problem is that you do
[self.subView viewWithTag:1];
but the view you want to remove is "owned" by self.view so it should be
[self.view viewWithTag:1];
But if you have a reference to subView, why search it again? Why not immediately:
self.subView.hidden = YES;
[self.subView endEditing:YES];
[self.subView removeFromSuperview];
Btw you might want to look into your memory management, I see you alloc your subView but I don't see it being released, when the view is removed again. Maybe you do and you just don't show the code, in that case forget my comment.

Removing view from its superview

I have added a few buttons to self.view. When the user clicks on one button, i will load another view (subView). My code where i am loading the subView is shown below
subView = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.scrollView.contentSize.width, self.scrollView.contentSize.height)];
subView.tag=1;
// and then i add various other components to it
[self.view addSubview:subView]; // and finally add it to the view
When the user touches this view, i detect it and remove the view (i have already done the detection part).
This is how i am removing the view
UIView *v = [self.subView viewWithTag:1];
v.hidden = YES;
[v endEditing:YES];
[v removeFromSuperview];
The view dissapears, but i can't click on the buttons or anything that was on the self.view. When i hold the mouse cursor on a button for awhile i could click it otherwise i can't. How can i solve this ?
Try removing the subview like this:
for (UIView *subView in self.view.subviews) {
if (subView.tag == (int)yourSubViewTag) {
[subView removeFromSuperview];
}
}
Should this line:
UIView *v = [self.subView viewWithTag:1];
really be:
UIView *v = [self.view viewWithTag:1];
?
I think your problem is that you do
[self.subView viewWithTag:1];
but the view you want to remove is "owned" by self.view so it should be
[self.view viewWithTag:1];
But if you have a reference to subView, why search it again? Why not immediately:
self.subView.hidden = YES;
[self.subView endEditing:YES];
[self.subView removeFromSuperview];
Btw you might want to look into your memory management, I see you alloc your subView but I don't see it being released, when the view is removed again. Maybe you do and you just don't show the code, in that case forget my comment.

scrollview's subview does not get touch events when scroll view scrolls

I have a scrollView onto which some imageViews are added.
I want that when scrollView scrolls then also the imageViews should get touch events.
But it is not happening in my case.
Only one of the two things happen at a time.
Either the scrollView scrolls but the imageViews do not get touch events
or the imageViews get touch events and the scrollView does not get scrolled.
Can't both of the things happen simultaneously.
Please suggest.
You can use "Tap Gesture Recognizer" to get the events on your images while it's being added to the scroll view.
EDIT
You can refer to this code:
-(void)yourGestureRecognizer
{
UITapGestureRecognizer *yourTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[yourImageView addGestureRecognizer:yourGestureRecognizer];
[yourGestureRecognizer release];
}
You can handle tap here:
-(void)handleTap:(UIGestureRecognizer *)sender{
UIImageView *imageView = (UIImageView *)sender.view;
switch (imageView.tag)
{
case 1:
m_pYourInstance=[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
[self.navigationController pushViewController:XXXXX animated:YES];
break;
}
Hope this helps !!
I know this was posted a while ago, but...
By default, UIImageView objects have their property userInteractionEnabled set to NO. This could be why touches aren't registering. This has tripped me up on more than one occasion and it's one of those little things that only experience will help.
Set it to YES and see if that fixes it.
Use UIGestureRecognizer. Add the recognizer to your image views.
And if you are targeting some old iOS version, have a look at this link.
yes you can do both. you need to customize your uiimageview by sub classing it and have to add Tap Gesture Recognizer like :
in .h file
#interface CustomView : UIImageView
{
// your variables
}
in .m file
//when you create an instants of your image view UITapGestureRecognizer will added in all your instants.
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
// add Gesture for tapping
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tap:)];
tap.numberOfTapsRequired = 1;
[self addGestureRecognizer:tap];
}
return self;
}
then add delegate methods in .m file too
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
UITouch *touch = [touches anyObject];
}
now in your custom cell, add your custom image view with Tap Gesture Recognizer
hope it will help you...
Use UIButtons with background images set on them. Here's the loop you use to layout UIScrollView subviews:
for (int i = 0; i < [images count]; i++) {
CGRect aFrame = ...;
UIButton *button = [[[UIButton alloc] initWithFrame:aFrame] autorelease];
[button setImage:[images objectAtIndex:i] forState:UIControlStateNormal];
button.tag = i;
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
}
And here you process the touch event:
- (void)buttonClicked:(id)sender {
UIButton *button = (UIButton *)sender;
[self performActionWithImageAtIndex:[images objectAtIndex:button.tag]];
}
That will omit the need to create additional gesture recognizers and will lower the amount of boilerplate work.
-- edit
The other reason your UIImageViews are not detecting the touches is because you create them in code and forget to set userInteractionEnabled to YES.