Dragging UICollectionViewCell relative to finger - ios

I'm trying to drag a UICollectionViewCell relative to finger. This does not mean reordering the CollectionView, I just want the cell to be dragable. The current code works on a UIView, but not on a cell.
Here is what I add to the cell:
UIPanGestureRecognizer* drag;
drag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragging:)];
[cell addGestureRecognizer:drag];
And here is the method that is invoked. The method is definitely activated, but it does not drag the cell.
-(void)dragging:(UIPanGestureRecognizer *)gesture
{
NSLog(#"dragging");
CGPoint panCoord;
if(gesture.state == UIGestureRecognizerStateBegan)
{
NSLog(#"Received a pan gesture");
panCoord = [gesture locationInView:gesture.view];
}
CGPoint newCoord = [gesture locationInView:gesture.view];
float dX = newCoord.x-panCoord.x;
float dY = newCoord.y-panCoord.y;
gesture.view.frame = CGRectMake(gesture.view.frame.origin.x+dX, gesture.view.frame.origin.y+dY, gesture.view.frame.size.width, gesture.view.frame.size.height);
}

Related

Gesture recognizer with Voice Over active

I developed an application which allows to the user to draw his finger signature in a canvas.
This feature is implemented using UIPanGestureRecognizer with a specific target action to draw a line in a UIView, but when the “Voice Over” is active the gesture recognizer action is not triggered anymore.
Gesture initialize code
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pan:)];
pan.maximumNumberOfTouches = pan.minimumNumberOfTouches = 1;
[self addGestureRecognizer:pan];
Gesture action code
- (void)pan:(UIPanGestureRecognizer *)pan {
CGPoint currentPoint = [pan locationInView:self];
CGPoint midPoint = midpoint(previousPoint, currentPoint);
if (pan.state == UIGestureRecognizerStateBegan)
{
[path moveToPoint:currentPoint];
}
else if (pan.state == UIGestureRecognizerStateChanged)
{
[path addQuadCurveToPoint:midPoint controlPoint:previousPoint];
}
previousPoint = currentPoint;
[self setNeedsDisplay];
}
Is there any way to draw a line in a view using gesture with “Voice Over” active?
Thanks and regards!
I resolved my problem setting both isAccessibilityElement and accessibilityTraits properties for UIView canvas:
canvasView.isAccessibilityElement = YES;
canvasView.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction;

UITapGestureRecognizer and UIPanGestureRecognizer

I want to create and see a uiimageview when i tap the screen.
Before i lift the finger, i want to move the uiimageview around the screen and the image set only when i take the finger off. Heres what i did:
- (IBAction)tap:(UITapGestureRecognizer *)recognizer {
CGPoint location = [recognizer locationInView:self.view];
UIImageView *circle = [[UIImageView alloc] initWithFrame:CGRectMake(location.x, location.y, 50, 50)];
circle.userInteractionEnabled = YES;
[circle setImage:[UIImage imageNamed:#"monkey_1.png"]];
[self.view addSubview:circle];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:circle action:nil];
[recognizer requireGestureRecognizerToFail:pan];
CGPoint translation = [pan translationInView:circle];
pan.view.center = CGPointMake(pan.view.center.x + translation.x, pan.view.center.y + translation.y);
[pan setTranslation:CGPointMake(0, 0) inView:self.view];
}
You can do this with just an UIPanGestureRecognizer or an UILongPressGestureRecognizer. In the gesture handling method, check the state property of the recognizer, and show your image when it's UIGestureRecognizerStateEnded (i.e. when the user lifts the finger from the screen). E.g.:
- (void)handleGesture:(UILongPressGestureRecognizer *)recognizer {
if(recognizer.state == UIGestureRecognizerStateEnded) {
// gesture ended: show the image
}
else if(recognizerState == UIGestureRecognizerStateBegan) {
// this code runs when the gesture is started.
}
else if(recognizerState == UIGestureRecognizerStateChanged) {
// gesture is in progress
}
}

iOS: dragGesture don't move element

In my app I have this code to drag an object
I set my gesture:
UILongPressGestureRecognizer *downwardGesture = [[UILongPressGestureRecognizer new] initWithTarget:self action:#selector(dragGestureChanged:)];
downwardGesture.minimumPressDuration = 0.2;
[grid_element addGestureRecognizer:downwardGesture];
for (UILongPressGestureRecognizer *gestureRecognizer in self.view.gestureRecognizers)
{
[gestureRecognizer requireGestureRecognizerToFail:downwardGesture];
}
and in my method:
- (void) dragGestureChanged:(UILongPressGestureRecognizer*)gesture{
UIImageView *imageToMove;
CGPoint pointInSelfView;
if (gesture.state == UIGestureRecognizerStateBegan)
{
dragging = TRUE;
CGPoint location = [gesture locationInView:grid_element];
NSIndexPath *selectedIndexPath = [grid_element indexPathForItemAtPoint:location];
if (selectedIndexPath==nil) {
dragging = FALSE;
return;
}
indexToHide = selectedIndexPath.row;
imageToMove = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"image_1.png"]];
[self.view addSubview:imageToMove];
pointInSelfView = [gesture locationInView:self.view];
[imageToMove setCenter:pointInSelfView];
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
pointInSelfView = [gesture locationInView:self.view];
[imageToMove setCenter:pointInSelfView];
}
else if (gesture.state == UIGestureRecognizerStateEnded ||
gesture.state == UIGestureRecognizerStateCancelled ||
gesture.state == UIGestureRecognizerStateFailed)
{
dragging = FALSE;
}
}
it work in UIGestureRecognizerStateBegan, then imageToMove is added in self.view in the correct position but imageToMove don't drag in UIGestureRecognizerStateChanged; I show a NSLog for pointInSelfView in UIGestureRecognizerStateChanged and it changes correctly; where is the problem?
EDIT
if I use imageToMove as IBOutlet it work fine, but I don't understand the difference.
If you are using ARC, the iOS system is releasing object-imageToMove.
Creating a property with retain attribute, makes system retains the object and hence it moves.
The only thing I am confused is why there is no error in [imageToMove setCenter:pointInSelfView];. There should be an error saying - message is sent to deallocated instance. But I am pretty sure that the problem is due to memory release of imageToMove.

UIPanGestureRecognizer in a UITableViewCell not recognizing left Pan

Right now I am developing an iPad app that uses a subclass of UITableviewCell that uses UIPanGestureRecognizer to slide left and right, However it only slides right and dosent slide left... This is the code I am usuing:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
pan.delegate = self;
[self addGestureRecognizer:pan];
}
return self;
}
This is my handlePan: method,
CGPoint translation = [gesture locationInView:self];
self.center = CGPointMake(self.center.x + translation.x,
self.center.y);
if (self.center.x > 700) {
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:self.tag],#"number",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"right" object:nil userInfo:dic];
dic = nil;
}
if (self.center.x < 0){
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:self.tag],#"number",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"left" object:nil userInfo:dic];
dic = nil;
NSLog(#"Left Called");
}
[gesture setTranslation:CGPointZero inView:self];
No matter what I try, i cant seem to get the console to say "Left Called" , i.e. The cell slides left. I am really struggling with this issue and would appreciate any help at all.
The trick is to react to the changed state of the pan, and the center calculation can be much simpler...
- (void)handlePan:(UIPanGestureRecognizer *)gesture {
if ((gesture.state == UIGestureRecognizerStateChanged) ||
(gesture.state == UIGestureRecognizerStateEnded)) {
CGPoint newCenter = CGPointMake([gesture locationInView:self.superview].x, self.center.y);
self.center = newCenter;
// To determine the direction of the pan, check the sign of translation in view.
// This supplies the cumulative translation...
if ([gesture translationInView:self.superview].x > 0) {
NSLog(#">>>");
} else {
NSLog(#"<<<");
}
}
}
I think the way that you are determining left/right might be flawed.
CGPoint translation = [gesture locationInView:self];
self.center = CGPointMake(self.center.x + translation.x,
self.center.y);
self.center.x will always be positive since "translation" is the location in the view which is positive.
What you probably want to keep track of the original touch position and then compare that with the location when swiping/moving. Try something like this:
- (void)handlePan:(UIPanGestureRecognizer *)panRecognizer {
if (panRecognizer.state == UIGestureRecognizerStateBegan)
{
// create a local property for the original point and assign the position on first touch
self.originalPanTouchPoint = [panRecognizer locationInView:self.view];
// create a local property for cell's center prior to pan
self.initialCellCenter = self.center;
} else {
CGPoint currentTouchPoint = [panRecognizer locationInView:self.view];
CGFloat xTranslation = self.originalPanTouchPoint.x - currentTouchPoint.x;
self.center = CGPointMake(self.initialCellCenter.x + xTranslation, self.initialCellCenter.y);
}
}

How to detect or define the orientation of a pinch gesture with UIPinchGestureRecognizer?

I'm using UIPinchGestureRecognizer to detect pinch gestures, something like:
- (void) initPinchRecon {
UIPinchGestureRecognizer *pinchRecognizer = [[[UIPinchGestureRecognizer alloc]
initWithTarget:self
action:#selector(Perform_Pinch:)] autorelease];
[self addGestureRecognizer:pinchRecognizer];
[pinchRecognizer setScale:20.0f];
}
- (void) Perform_Pinch:(UIPinchGestureRecognizer*)sender{
NSLog(#"PINCH");
}
And it works well to detect a simple pinch gesture: It's possible to determine (or define myself) the angle or orientation of the pinch gesture ?, for example, to differentiate between an horizontal and an vertical pinch gesture ?
A very simple solution is to implement the gesture handler like this:
-(void)handlePinchGesture:(UIPinchGestureRecognizer *)recognizer {
if (recognizer.state != UIGestureRecognizerStateCancelled) {
if (recognizer.numberOfTouches == 2) {
CGPoint firstPoint = [recognizer locationOfTouch:0 inView:recognizer.view];
CGPoint secondPoint = [recognizer locationOfTouch:1 inView:recognizer.view];
CGFloat angle = atan2(secondPoint.y - firstPoint.y, secondPoint.x - firstPoint.x);
// handle the gesture based on the angle (in radians)
}
}

Resources