iOS : detect UIImageView for UITouch Events - iphone

I've added some UIImageView dynamically and filled it with different images, what I am trying to do is "Allow user to set position for any UIImageView", for that I used
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//Here I want the object of particular UIImageView on which user touched.
}
In that method I'm doing,
NSLog(#"%#",[touches anyObject]);
It returns output
<UITouch: 0x68b95e0> phase: Began tap count: 1 window: <UIWindow: 0x68875d0; frame = (0 0; 320 480); layer = <UIWindowLayer: 0x68b6470>> view: <UIImageView: 0x6a74cf0; frame = (83.7763 83.7763; 182.447 182.447); transform = [0.968912, -0.247404, 0.247404, 0.968912, 0, 0]; alpha = 0.8; opaque = NO; tag = 3; layer = <CALayer: 0x6a74980>> location in window: {161, 230} previous location in window: {161, 230} location in view: {52.7761, 105.448} previous location in view: {52.7761, 105.448}
Note, in above output, it showing my UIImageView object on which I touched. But I want that object from it!!!
I want my UIImageView on which user touched?, I have already set property userInteractionEnabled=YES so the problem isn't with it!
I used below code to get it so, but it wont work.
NSInteger tag=[[[touches anyObject] view] tag]; //It only returns tag of UIView tag
I Google it but doesn't come with solution!
Thank you in advance for any help!

Here you go:
this is only for one imageview you can detect the other by the same if statement.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touch_point = [touch locationInView:self.view];
if (![imageView pointInside:touch_point withEvent:event])
{
NSLog(#"point inside imageview");
}
}
or you can also do this :p
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if (touch.view == iv)
{
NSLog(#"i got you");
}
}
like this: (iv and iv2 are 2 different UIImageView`s)
if (touch.view == iv)
{
NSLog(#"i got you");
}
if (touch.view == iv2)
{
NSLog(#"i got you too :p");
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=[touches anyObject];
if([[touch valueForKey:#"view"] isKindOfClass:[UIImageView class]])
{
UIImageView *viewSelected=(UIImageView *)[touch valueForKey:#"view"]; //it returns touched object
//for further differences can user viewSelected.tag
}
}

Code to get only the X and Y coords from the UIImageView:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touch_point = [touch locationInView:self.imgView];
if ([imgView pointInside:touch_point withEvent:event])
{
NSLog(#"point inside imageview");
cords=[NSString stringWithFormat:#"%f,%f",touch_point.x,touch_point.y];
NSLog(#"cords are%#",cords);
}
}

You can use UIButton with Image properties instead of UIImageView.
If you would like to call your own function ,It's pretty easy to handle many event like Touch up inside or Touch Cancel by adding selector.
UIButton *yourBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
/* Depend on your dynamic programming handle */
yourBtn.frame = CGRectMake(40, 140, 240, 30);
/* If you prefer just only image ,no need to set Title name */
[yourBtn setTitle:#"Your Button Title" forState:UIControlStateNormal];
/* choose yourFunction for each UIButton */
[yourBtn addTarget:self action:#selector(yourFunction) forControlEvents:UIControlEventTouchUpInside];
/* your button will be appear in the position that you have define */
[self.view addSubview:yourBtn];
Hope It helps you!

1 Subclass UIImageView and implement:
Responding to Touch Events
– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:
Responding to Motion Events
– motionBegan:withEvent:
– motionEnded:withEvent:
– motionCancelled:withEvent:
or:
2 Add UIGestureRecognizer to each UIImageView.

You could add the View that you add into an NSMutableArray and then just compare like this:
I am not in my mac, but It's something similar to this:
NSInteger viewID = [_views indexOfObject:[[touches anyObject] view]];
This return and number if not isn't exist do this:
if (viewID != NSNotFound) {
//it exist the view and its in the array
}

Related

Manually passing touches Began to a newly created instance

I want an object to be created when I touch an UIView. But I want the new object to be able to moved without the finger having to be raised. I tried passing the touched event to the new object but it doesn't work.
Is there any way to do it?
You'll have to derive a subclass of the UIView, which will serve as a HolderView for all newly generated views. Also, once a new view is generated, the new view will move along with the finger even if its not raised.
Following code will do it, tweak it later as per your needs:
#interface HolderView : UIView
#property(nonatomic,retain)UIView *newView;
#end
#implementation HolderView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
if (CGRectContainsPoint(self.bounds, touchPoint)) {
CGRect r = CGRectMake(touchPoint.x-50, touchPoint.y-50, 100, 100);
self.newView = [[[UIView alloc] initWithFrame:r]autorelease];
self.newView.backgroundColor= [UIColor cyanColor];
[self addSubview:self.newView];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (self.newView!=nil) {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
self.newView.center = touchPoint;
}
}
#end
i think the touch is creating a problem at your end while you touch at some other object the view is also present so touch can not identified on your movable object for that you need to use one UIImageview over your UIView and then detect the touch and then you'll be able to achieve your desired output
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint imgPop = [touch locationInView:imgPopup];
if ([imgPopup pointInside:imgPop withEvent:event])
{
CGPoint imgReply = [touch locationInView:viewComment];
if ([viewComment pointInside:imgReply withEvent:event])
{
} else {
viewPopup.hidden = TRUE;
}
}
}
this is how i manage this code is for dismissing the view on touch but you can modify and use for your purpose.

Touch to hide tool bar

I want to hide and show tool bar when touch in The area CGRectMake(130, 0, 60, 480)
without using UIGestureRecognizer because its effect my other views
if touch once in the area , tool bar should hide and if tool bar is hidden , should show the tool bar
i have tried this
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (mainToolbar.hidden == YES) {
mainToolbar.hidden=NO;
}
else if(mainToolbar.hidden == NO){
[mainToolbar setHidden:YES];
}
}
but its hide tool bar when touch in to tool bar only
thanks......
Write your code in the view where you added tool bar. You will get location of touch using this code:
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView: touch.view];
And then check if touch is inside your rect using CGRectContainsPoint: function.
Another approach is simply put an button on the required area. Hope this helps
The method gives you an NSSet of all touches on the screen. You can use this to customize your behavior for touches. For example:
//This will change the state of whether mainToolbar is hidden or not. In the case of multiple touches, it will change the property if any touch is in the CGRect area.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGRect testRect = CGRectMake(130, 0, 60, 480);
for (UITouch *touch in touches) {
if (CGRectContainsPoint(testRect, [touch locationInView:self.view])) {
mainToolbar.hidden = !mainToolbar.hidden;
}
}
}
Or if you only want the action to happen if one touch is made and ignore it if the user is touching with multiple fingers, you would check for that:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGRect testRect = CGRectMake(130, 0, 60, 480);
if ([touches count] == 1) {
//If there is only one touch, we check for that. Otherwise, we ignore it.
UITouch *touch = [touches anyObject];
if (CGRectContainsPoint(testRect, [touch locationInView:self.view])) {
mainToolbar.hidden = !mainToolbar.hidden;
}
}
}
You can do some really cool things with just the four functions touchesBegan: touchesMoved: touchesEnded: and touchesCanceled:.

Get event on UIslider track

How to get an event on UISlider track? I am able to get the events on UISlider's button but not on track. How should I go about it?
Thanks
For doing this you need to subclass the UISlider and implement the touches event like: touchesBegan, touchesEnd,touchesCancelled,touchesMoved etc.
#interface yourSlider:UISlider
#end
#implementation yourSlider
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
#end
Subclass the UISlider and override its touchesBegan:withEvent: method. Get the point value from the touch event and calculate it's percentage by the point's .x value relative to the width of the slider.
Answers are correct but there is a workaround here , you can simply add a clear button equal to slider coordinations on your slider and detect the touch point on it then convert the X position to a slider value.
- (IBAction)buttonPressed:(id)sender forEvent:(UIEvent*)event
{
UIView *button = (UIView *)sender;
UITouch *touch = [[event touchesForView:button] anyObject];
CGPoint location = [touch locationInView:button];
NSLog(#"Location in button: %f, %f", location.x, location.y); \\ use this x to determine slider's value
}
Another workaround :
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(sliderTapped:)];
gr.delegate=self;
[Slider addGestureRecognizer:gr];
-(void)sliderTapped:(UIGestureRecognizer*)g{
UISlider* s = (UISlider*)g.view;
if (s.highlighted)
return;
CGPoint pt = [g locationInView: s];
CGFloat value = s.minimumValue + pt.x / s.bounds.size.width * (s.maximumValue - s.minimumValue);
[s setValue:value animated:YES];
}

touchesMoved reaching out of my view bounds

I have subclassed UIView and there initially my view will be in a default color and i need to fill some different color on touch (from x axis = 0 to user touched point),here the problem is touchesMoved even if i drag out of my self view bounds it is getting those points,how to restrict it to only for my self view bounds.
I googled & tried below snippets but of no luck
if([self pointInside:point withEvent:nil]){
[self fillColor];
}
My touchesMoved method is as below,
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
endPoint = point;
NSLog(#"moved x: %f,y: %f",point.x,point.y);
if(CGRectContainsPoint([self frame], endPoint)){ // this also not working
[self fillColor];
}
}
Any help is appreciated in advance.
just set tag in viewDidLoad: method and use bellow logic..
fillColorView.tag = 111;
and use bellow logic in touchesMoved: method like bellow..
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *tap = [touches anyObject];
CGPoint pointToMove = [tap locationInView:fillColorView];
if([tap.view isKindOfClass:[UIView class]])
{
UIView *tempView=(UIView *) tap.view;
if (tempView.tag == 111){
[self fillColor];
}
}
}
hope this help you...
In your touchesMoved method, CGPoint point = [touch locationInView:self]; replcae self by the view in which you wants the touch to be worked.
self will get the complete view, you should pass your drawingView at there, so that it will detetc touch only on that view.

How would I drag UITextView around the view screen?

I have a project where a UITextView (for multilines) can be dragged around the screen. So far my solution to this has been an overlay of an invisible UIButton which when dragged its center is the same as the UITextView's center.
However I've seen apps that seem to just allow the UITextView to be dragged and edited on the fly so it seems there might not be an overlay in those but I'm not sure.
Thoughts?
By the way, c in this code is the UIButton and this is how I have moved it thus far:
- (void) draggedOut: (UIControl *) c withEvent: (UIEvent *) ev
{
if(self.interfaceOrientation == UIInterfaceOrientationPortrait)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
else if(self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
else if(self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
else if(self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
}
- (void)panTextView:(UIPanGestureRecognizer *)recognizer {
NSLog(#"panning");
location1 = [recognizer translationInView:draggableTextView];
recognizer.view.center = CGPointMake(recognizer.view.center.x + location1.x,
recognizer.view.center.y + location1.y);
[recognizer setTranslation:CGPointMake(0,0) inView:draggableTextView];
location1 =[recognizer locationInView:draggableTextView];
NSLog(#"tranlation %#",NSStringFromCGPoint(location1));
[_imgpic addSubview:recognizer.view];
appDelegate.txt=draggableTextView.text;
}
call this method after creating textview.
Well have not been able to manipulate the actual uitextview.
First tried making a button overlay that could be moved and could be pressed to start editing, but it wasn't centered properly.
Then tried the above method to move the UITextView itself. But it would only work on touches or drags. (Note this was a modified form of touchesBegan & touchesMoved)
Ended up with a UIScrollView with the UITextView as a subview. Now it can move smoothly just that it can be moved from any place on the screen. Not optimal but is the best result to thus keep everything else intact.
Does the textView need to support scrolling? If so, this could get complicated.
But if not, there are two approaches. 1) subclass the textview and override touchesBegan, touchesMoved, touchesEnded. 2) write a gesture recognizer that processes the same messages and attach it to the textview.
Here's an example of a Gesture recognizer that will do the job:
#interface TouchMoveGestureRecognizer : UIGestureRecognizer
{
CGPoint _ptOffset;
}
#end
#implementation TouchMoveGestureRecognizer
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* t = [touches anyObject];
_ptOffset = [t locationInView: self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* t = [touches anyObject];
CGPoint pt = [t locationInView: self.view.superview];
pt.x -= _ptOffset.x;
pt.y -= _ptOffset.y;
CGRect r = self.view.frame;
r.origin = pt;
self.view.frame = r;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
_ptOffset = CGPointMake(-1, -1);
}
#end
and, how to use it:
- (void)viewDidLoad {
[super viewDidLoad];
_textView.scrollEnabled = NO;
TouchMoveGestureRecognizer* gr = [[[TouchMoveGestureRecognizer alloc] init] autorelease];
[_textView addGestureRecognizer: gr];
}