Simple Tappable Non-Rectangular Shape - objective-c

I have to create a very simple GUI for an iPad application.
I have a 1024x768 png and I want to use this file for the GUI. I have to make an area of this png tappable and able to run some action. This area is not a rectangle (it's a trapezoid) so I can't create a button. Is it possible somehow?

you can do it in code by overriding - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event and - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event in the view that's displaying the image. that'll mean you have to decide whether a point is within the touch area of the image.

Make a UIImageView that displays an image which shows the trapezoid and is otherwise transparent.
Turn on the UIImageView's userInteractionEnabled to make it tappable.
Put a UITapGestureRecognizer on the UIImageView to respond to the tap.
In the tap gesture recognizer's action handler, respond only if the point where the user tapped is non-transparent. To learn whether the point the user touched is transparent, see Retrieving a pixel alpha value for a UIImage.

Related

How do I forward touch events to a view behind a uicollectionview?

I have a uicollectionviewcontroller which I use to create a small toolbar at the bottom of the screen. I add the view of the uicollectionviewcontroller to another viewcontroller's view. My problem is that it won't forward touch events to a view underneath it. I did move it to the bottom and that worked for a while but now I need to use 2 uicollection views.
How am I supposed to forward touch events to views beneath a uicollectionviewcontroller's view?
In case the question is still relevant, the following can be used to achieve touch forwarding.
Subclass UICollectionView
Overwrite - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesEnded:touches withEvent:event];
[self.yourCustomDelegate forwardTouches:touches withEvent:(UIEvent *)event];
}
That is how UICollectionView can keep its ability to respond to user interaction, and the same time forward received touches.
As i think you can add your toolbar as footer of UICollectionView and it will work
have a look into this link How to Add Header and Footer View in UICollectionView

Freeform Container UIView

I am trying to understand if something like this is possible and if yes how can i go about achieving this.
i want to create a UIView that it is a container for other views that respond based on the below picture. i know that a UIView is a container of other UIViews. what i want to be able to do is to be able to touch on a UIImageView and when i am dragging it in the main View, if it gets out of bounds on one side, to be shown on exactly the opposite direction like shown on the image. i hope i managed to explain the question correctly.
Click Here for the Description
You can achieve that very easily by implementing the container UIView's touch methods:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
In touchesMoved you can check for your UIImageView's origin. If it crosses the boundaries (x, y less than 0 or bigger than the container's dimensions) then simply reposition its frame by your desired offset.

ContinueTrackingWithTouch:withEvent: method is not being called?

I have a custom UIView class. Inside that view, there is an image view. (I'm making a UISlider from scratch).
I am trying to get the image view -- the thumb of the slider -- to move across the view. Below is the code from the UIView class
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
if ( CGRectContainsPoint(self.thumb.frame, touchPoint))
self.thumb.center = CGPointMake(touchPoint.x, self.thumb.center.y);
return YES;
}
When I place my finger on the thumb of the slider and try to drag it, nothing happens. However, when I touch outside the thumb of the slider, drag my finger to the thumb without letting go, and then try dragging the thumb, it works fine.
How can I modify my code so that the method will be called when someone holds the thumb and tries to drag it?
My guess is that you have user interaction enabled on your image view, which is in turn not relaying the touch events to the backing logic view. Do something like this:
self.thumb.userInteractionEnabled = NO
Put that in whatever init method you are using and the thumb view will not interrupt the touch events anymore.

UIScrollView decide between drag and tap

I am trying to determine a Single Tab on a View inside of a UIScrollView. The Problem is that The UIScrollview catches all the gestures.
What I tried so far:
I override the following method in my UIScrollView:
-(BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
UITouch *touch = [touches anyObject];
if([touch tapCount]== 2) return YES;
return NO;
}
This works fine, I can now reach the UITapGestureRecognize on my UIView, unfortunately I can only detect double-taps because the [touch tapCount] == 1 is always beeing called (dragging or zooming in the UIScrollView). But actually the UIScrollview does not need the "Single-Tap-Function"
Is there a way to decide between a drag (Scroll or zoom) and a single Tap inside this method? I cant find it..
-(BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
Thanks in advance
Fabi
It sounds like you only want the tap recognizer to succeed if the touch doesn't scroll the scroll view. This is pretty easy because the scroll view uses a pan gesture recognizer for scrolling. On iOS 5, you can just do this:
[self.tapRecognizer requireGestureRecognizerToFail:self.scrollView.panGestureRecognizer];
If you want to support older versions of iOS, you have to do this:
for (UIGestureRecognizer *recognizer in self.scrollView.gestureRecognizers) {
if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]])
[self.tapRecognizer requireGestureRecognizerToFail:recognizer];
touchesShouldBegin: is a delegate method on UIView. It is not part of a UIGestureRecognizer.
You'll need to create a UITapGestureRecognizer, set the number of taps you want to trigger the recognizer and add it to your view.
Here is the documentation for UITapGestureRecognizer
I'm assuming you meant "single tap"--your scrollView belongs to the UIView tied to your controller. Assign the tap gesture recognizer to the that UIView. It gets first picks on all gestures and then passes down the ones it isn't interested in.

Drag event in subview of UIScrollView

How can I add a drag event to a subview of a UIScrollView? The structure is the following:
-UIView
-UIScrollView
-UIView
-UIView
...
I tried to start with the following:
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGPoint location = [aTouch locationInView:self.superview.superview];
[UIView beginAnimations:#"Dragging A DraggableView" context:nil];
self.frame = CGRectMake(location.x, location.y,
self.frame.size.width, self.frame.size.height);
[UIView commitAnimations];
}
But nothing happens! Help would be very much appreciated.
Thanks
Just incase anyone finds this question like I did, I solved this problem by adding a gesture recognizer to the subviews in the scrollview. The gesture recognizer will handle the touch event itself.
Bruno, one possibility is to use the gesture recognizers, as Scott mentions.
Another possibility is to use the touchesMoved: method you mention. Using the touchesMoved: method requires you to implement another three methods, touchesBegan:, touchesEnded:, touchesCancelled:. They cover the phases of the finger touching the screen:
First contact (touchesBegan) allows you to set up variables as needed.
Continuous move (touchesMoved) allows you to track the move and move your content continuously.
And finally removing the finger (touchesEnded) where you can finalize any changes you want to keep.
touchesCancelled is required for clean-up if the gesture is interrupted (by phone call, or some other controller grabbing the touch event).
You need all four methods on the same class, otherwise a superclass implementing the method will grab the touch processing and your code won't run as expected.
Regards, nobi