Touch down / touch up in IOS using xcode and swift - ios

I need to implement a thumb print scanner in swift with xcode. I found the gesture recogniser but I am missing the point where I can react to the "onTouchDown" and "onTouchUp" events.
the underlying object is an UIImageView. I am quite new to this and I can't find proper documentation on this.
Thanks a lot

With the current iOS devices, the following hardware is supported:
A screen that is multi-touch aware.
A home button that is able to read thumb-prints.
Therefore its not possible to implement a thumb-print scanner on a UIImageView or any UIView. You can however respond to touches, multi-touches, track acceleration, speed, movement, etc.
Responding to touch events:
There's a few ways to respond to touch events.
UIButton:
You could add a UIButton as a subview or your view. Be sure to size it to take up the parent view's bounds. Then use [button addTarget:self action:#selector(someMethod) controlEvents:UIControlEventTouchUpInside]
Use a UIPanGestureRecognizer:
Add a UIPanGestureRecognizer:
_panHandler = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(panHandle:)];
- (void)panHandle:(UIPanGestureRecognizer *)recognizer;
{
if ([recognizer state] == UIGestureRecognizerStateBegan) {
//do something
}
else if ([recognizer state] == UIGestureRecognizerStateChanged) {
//do something
}
else if ([recognizer state] == UIGestureRecognizerStateEnded) {
//do something
}
}
Lowest level / most flexible / more work:
In your UIView sub-class override:
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
}

Related

Possible to convert UIButton control events to UIGestureRecognizer?

I have a situation where I have to work around a bug in iOS7 and need to convert the UIButton control events:
UIControlEventTouchUpOutside
UIControlEventTouchDown
UIControlEventTouchUpInside
UIControlEventTouchDragOutside
UIControlEventTouchDragInside
UIControlEventTouchDragInside
to UIGestureRecgonizer (I can't use UIView touch methods such as touchesBegan, touchesEnded, etc. either). I'm kind of interested if this is even possible anyway.
For instance, I'm thinking of a way to convert UIControlEventTouchDown and can't think of a way. UITapGestureRecognizer and UIPanGestureRecognizer both would not work.
Anyone know if this is possible?
I've done something similar with a UILongPressGestureRecognizer for a SpriteKit game to implement line segment intersection, pretty sure it would be easily adaptable for mimicking a UIButton too. Keep track of the previous location of your gesture recognizer, I just used a static CGPoint that I updated every time my selector fired. Then, just check the previous position and the current position with CGRectContainsPoint using your button's frame, and depending on those results, do whatever you need to do. If both are inside the frame, that's the same as UIControlEventDragInside, if both are outside, that's UIControlEventDragOutside, if the previous is outside and the current is inside, that's UIControlEventDragEnter, etc etc. Also make sure to check the gesture recognizer's state so you know when to call TouchUpInside/Outside. I'd make sure to have a damn good reason to do this, but it seems workable to me.
- (void) longPress:(UILongPressGestureRecognizer *)longPressGestureRecognizer
{
if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan || longPressGestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint touchedPoint = [longPressGestureRecognizer locationInView: self];
if (CGRectContainsPoint(self.bounds, touchedPoint))
{
[self addHighlights];
}
else
{
[self removeHighlights];
}
}
else if (longPressGestureRecognizer.state == UIGestureRecognizerStateEnded)
{
if (self.highlightView.superview)
{
[self removeHighlights];
}
CGPoint touchedPoint = [longPressGestureRecognizer locationInView: self];
if (CGRectContainsPoint(self.bounds, touchedPoint))
{
if ([self.delegate respondsToSelector:#selector(buttonViewDidTouchUpInside:)])
{
[self.delegate buttonViewDidTouchUpInside:self];
}
}
}
}

Is it possible to know when [UIDynamicItemBehavior addLinearVelocity:forItem:] has finished running?

I'm using a UIPanGestureRecognizer and UIAttachmentBehavior to move a UIView around the screen. When the user ends the gesture I apply the velocity of the gesture recognizer to the view using a UIDynamicItemBehavior and the addLinearVelocity:forItem: method.
Here is the code I use:
- (void)_handlePanGestureRecognized: (UIPanGestureRecognizer *)panGestureRecognizer
{
if (panGestureRecognizer.state == UIGestureRecognizerStateBegan)
{
_attachmentBehavior.anchorPoint = panGestureRecognizer.view.center;
[_dynamicAnimator addBehavior: _attachmentBehavior];
}
else if (panGestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint point = [panGestureRecognizer locationInView: panGestureRecognizer.view.superview];
_attachmentBehavior.anchorPoint = point;
}
else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded)
{
[_dynamicAnimator removeBehavior: _attachmentBehavior];
CGPoint velocity = [panGestureRecognizer velocityInView: panGestureRecognizer.view.superview];
[_dynamicItemBehavior addLinearVelocity: velocity
forItem: self];
}
}
When the view stops moving I would then like to have it snap to the closest edge of the screen but I currently have no way of knowing when it has stopped moving short of polling the view's center with a CADisplayLink.
Have you tried attaching a UIDynamicAnimatorDelegate to your animator, and using the dynamicAnimatorDidPause: method to trigger snapping to the closest edge?
From reading on the developer forums, it sounds like some have had problems with their views staying in motion for a very long time (jiggling back and forth by 1 pixel, for example), but perhaps this will work for your case.

How can I cancel other events when my UIPanGestureRecognizer occurs along side a UIScrollView?

I have a UIPanGestureRecognizer that I added to a UIScrollView, and when certain circumstances with the UIPanGestureRecognizer are met I want to cancel the touch/pan events from going to the UIScrollView, right now I have something like this:
-(void)panRecognized:(UIPanGestureRecognizer *)sender {
if(/* some logic */) {
[sender cancelsTouchesInView];
}
}
however calling [sender cancelsTouchesInView] does not stop scrolling from occurring in my UIScrollView.
I come from a big JavaScript background and I tend to expect events to behave in the same way and I think it's my downfall that they don't. I'm finding it really difficult to understand how events are handled in iOS.
-(void)panRecognized:(UIPanGestureRecognizer *)sender {
if(/* some logic */ && sender.state == UIGestureRecognizerStateBegan) {
[self.scrollView setUserInteractionEnabled:NO];
}
else if(sender.state == UIGestureRecognizerStateEnded)
{
[self.scrollView setUserInteractionEnabled:YES];
}
}

Detect when finger dragging UIButton overlaps UIImageView

I am using UIPanGestureRecognizer to drag a UIButton around the screen. The idea is that the user can drag it over a folder to insert it in the folder (like iOS icons). This code I found works fine if I want to detect when the button overlaps with the image:
-(void) touchesEnded:(NSSet *) touches {
if(CGRectIntersectsRect([imageViewA frame], [imageViewB frame]) {
NSLog(#"Do something.");
}
}
But since the button is big and there are more images one next to another, it may happen that the button overlaps with both of them. I therefore want to detect when the actual user finger holding the UIButton overlaps with the image to trigger the right action. Any ideas?
UIGestureRecognizer will recognize the pan and when it ends, you can use locationInView: to find the finger's position in the button's super view. You can then see if they are overlapping with CGRectContainsPoint(frame, point):
- (void)handlePanGesture:(UIPanGestureRecognizer*)recognizer {
if ([recognizer state] == UIGestureRecognizerStateEnded) {
CGPoint fingerPoint = [recognizer locationInView:someImageView.superview];
if (CGRectContainsPoint(someImageView.frame, fingerPoint)) {
NSLog(#"Do something");
}
}
}

pressGestureRecognizer and touchesBegan

I have the following problem.
I am using a UILongPressGestureRecognizer to put a UIView into a "toggle mode". If the UIView is in "toggle mode" the user is able to drag the UIView around the screen. For dragging the UIView around the screen I am using the methods touchesBegan, touchesMoved and touchesEnded.
It works, but: I have to lift my finger in order to drag it, because the touchesBegan method got already called and therefore is not called again and therefore I can't drag the UIView around the screen.
Is there any way to manually call touchesBegan after UILongPressGestureRecognizer got triggered (UILongPressGestureRecognizer changes a BOOL value and the touchesBegan only works if this BOOL is set to YES).
UILongPressGestureRecognizer is a continuous gesture recognizer, so rather than resorting to touchesMoved or UIPanGestureRecognizer, just check for UIGestureRecognizerStateChanged, e.g.:
- (void)viewDidLoad
{
[super viewDidLoad];
UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[self.view addGestureRecognizer:gesture];
}
- (void)handleGesture:(UILongPressGestureRecognizer *)gesture
{
CGPoint location = [gesture locationInView:gesture.view];
if (gesture.state == UIGestureRecognizerStateBegan)
{
// user held down their finger on the screen
// gesture started, entering the "toggle mode"
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
// user did not lift finger, but now proceeded to move finger
// do here whatever you wanted to do in the touchesMoved
}
else if (gesture.state == UIGestureRecognizerStateEnded)
{
// user lifted their finger
// all done, leaving the "toggle mode"
}
}
I would suggest you to use UIPanGestureRecognizer as it a recommended gesture for dragging.
You can configure the min. and max. number of touches required for a panning, using the following the properties:
maximumNumberOfTouches
minimumNumberOfTouches
You can handle the states like Began, Changed and Ended, like having animation for the required states.
Using the below method translate the point to the UIView in which you want it.
- (void)setTranslation:(CGPoint)translation inView:(UIView *)view
example:
You have to use a global variable to retain the old frame. Get this in UIGestureRecognizerStateBegan.
When the state is UIGestureRecognizerStateChanged. You can use the
-(void) pannningMyView:(UIPanGestureRecognizer*) panGesture{
if(panGesture.state==UIGestureRecognizerStateBegan){
//retain the original state
}else if(panGesture.state==UIGestureRecognizerStateChanged){
CGPoint translatedPoint=[panGesture translationInView:self.view];
//here you manage to get your new drag points.
}
}
Velocity of the drag. Based on the velocity you can provide a animation to show bouncing of a UIView
- (CGPoint)velocityInView:(UIView *)view

Resources