Slide button back and forth between two points - ios

I'm trying to use UIPanGestureRecognizer to slide a button between two points (like a volume slider). The following code allows me to slide the button back and forth, but the button doesn't stop at the same point every time (i.e., when I slide it to the right, sometime it stops where it's supposed to, sometimes it stops +/- 10 pixels from where it's supposed to). What am I doing wrong?
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
CGPoint location = [recognizer locationInView:self];
// 1
if (recognizer.state == UIGestureRecognizerStateBegan) {
// if the gesture just started, record current center location
_originalCenter = self.sliderButton.center;
}
// 2
if (recognizer.state == UIGestureRecognizerStateChanged) {
// move the checkmarks and main label based on touch
//CGPoint translation = [recognizer translationInView:self];
// move slider button
if (location.x < 70 + 178 && location.x > 70) {
self.sliderButton.center = CGPointMake(location.x, _originalCenter.y);
}
// determine whether the item has been dragged far enough to initiate a removal
if (location.x > 170 + 70) {
_draggedToEnd = YES;
} else {
_draggedToEnd = NO;
}
}
// 3
if (recognizer.state == UIGestureRecognizerStateEnded) {
if (_draggedToEnd) {
// notify the delegate that this item should be deleted
[self buttonDraggedToEnd];
}
}
}

Related

Custom Gesture for Increase the size of the view

How can i write custom gesture for increase the size of the view in all the direction (i.e) in origin side and size of the view.
Example:
the user should touch the view in any one of the corner. either near to origin side or view end side.
Example: View frame size is (100,100,200,200). and minimum touch distance is 15 pixel from any side.
so, if the user touch location is (X=15,Y=40) in
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
method means that touch near to the origin side.
same if the user touch location is (X=15, Y=190) in
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
method means the touch is near to the size side.
My code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if([touches count] != self.touchMinimumCount ||
[[touches anyObject] tapCount] > self.tapMinimumCount)
{
self.state = UIGestureRecognizerStateFailed;
return;
}
self.startPoint = [[touches anyObject] locationInView:self.view];
self.viewFrame = self.view.frame;
if(((self.startPoint.x - self.view.bounds.origin.x) <= self.minimumTouchDistance) ||
((self.startPoint.y - self.view.bounds.origin.y) <= self.minimumTouchDistance) ||
((ABS(self.startPoint.x - self.view.bounds.size.width)) <= self.minimumTouchDistance) ||
((ABS(self.startPoint.y - self.view.bounds.size.height)) <= self.minimumTouchDistance))
{
self.state = UIGestureRecognizerStatePossible;
if(((self.startPoint.x - self.view.bounds.origin.x) <= self.minimumTouchDistance) ||
((self.startPoint.y - self.view.bounds.origin.y) <= self.minimumTouchDistance) )
{
self.currentTouchPosition = touchPositionIsOrigin;
}
else if(((ABS(self.startPoint.x - self.view.bounds.size.width)) <= self.minimumTouchDistance) ||
((ABS(self.startPoint.y - self.view.bounds.size.height)) <= self.minimumTouchDistance))
{
self.currentTouchPosition = touchPositionIsSize;
}
}
else
{
self.state = UIGestureRecognizerStateFailed;
}
}
My gesture possible state setting if the touch in side the touch distance only.
Now i want to resize the view frame according to the user finger move.
if the user touch the origin side and move towards the left direction means, want to change the origin.x of the view and the width also want to increase.
if the user touch the origin side and move towards the top direction means, want to change the origin.y of the view and the width also want to increase.
if the user touch the origin side and move towards the right direction means, want to change the origin.x of the view.
if the user touch the origin side and move towards the bottom direction means, want to change the origin.y of the view.
if the user touch the size side and move towards the left direction means, want to reduce the width of the view.
if the user touch the size side and move towards the top direction means, want to reduce the height of the view.
if the user touch the size side and move towards the right direction means, want to increase the width of the view.
if the user touch the size side and move towards the bottom direction means, want to increase the height of the view.
this all change according tho the user finger in that view while moving.
My code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if(self.state == UIGestureRecognizerStateFailed) return;
direction currentDirection;
CGPoint currentLocation = [[touches anyObject] locationInView:self.view];
if(self.state == UIGestureRecognizerStatePossible ||
self.state == UIGestureRecognizerStateChanged)
{
if((currentLocation.x - self.startPoint.x) > 0)
{
currentDirection = directionRight;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginX = // need to implement.
distanceInSizeX = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeX = // need to implement.
}
}
else if((currentLocation.x - self.startPoint.x) < 0)
{
currentDirection = directionLeft;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginX = // need to implement.
distanceInSizeX = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeX = // need to implement.
}
}
else if((currentLocation.y - self.startPoint.y) >= 0)
{
currentDirection = directionBottom;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginY = // need to implement.
distanceInSizeY = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeY = // need to implement.
}
}
else if((currentLocation.y - self.startPoint.y) < 0)
{
currentDirection = directionTop;
self.state = UIGestureRecognizerStateChanged;
if(self.currentTouchPosition == touchPositionIsOrigin)
{
distanceInOriginY = // need to implement.
distanceInSizeY = // need to implement.
}
else if(self.currentTouchPosition == touchPositionIsSize)
{
distanceInSizeY = // need to implement.
}
}
else
{
currentDirection = directionUnknown;
}
self.originPoint = CGPointMake(distanceInOriginX, distanceInOriginY);
self.sizePoint = CGPointMake(distanceInSizeX, distanceInSizeY);
}
}
i mentioned the // need to implement. where ever i want the code for to achieve the functionality which i mentioned in that points. so, kindly help to go ahed.
if my was is wrong means, share the best way to do the same type of gesture.
any example is there also kindly share here. thanks in advance....
If you want to scale the size of a view, then use UIPinchGestureRecognizer. An example code is given here
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:#selector(scale:)];
pinchRecognizer.delegate = self;
[self addGestureRecognizer:pinchRecognizer];
handler method is
#pragma mark - Gesture handling functions
-(void)scale:(UIPinchGestureRecognizer*)recognizer {
if ([recognizer state] == UIGestureRecognizerStateBegan) {
_lastScale = 1.0;
}
CGFloat scale = 1.0 - (_lastScale - [recognizer scale]);
CGAffineTransform currentTransform = self.imgView.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
self.imgView.transform = newTransform;
_lastScale = [recognizer scale];
}

Objective C: trigger method at pan value

What is the best way to trigger a method based on Pan gesture value?
I want to trigger a method when my pan location x is between 500 to 600. How do people normally handle this??
You need to override gestureRecognizerShouldBegin. Then you can detect translation.x and see where the values fall between.
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint translation = [panGestureRecognizer translationInView:self.view];
if (translation.x > 500 && translation.x < 600)
[self callCustom];
return true;
}
- (void) callCustom {
//do what you need to do
}
I assume you have a method that handles the pan gesture. Make that method look something like this.
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint movement = [recognizer translationInView:self.view];
if (movement.x >= 500 && movement.x <= 600) {
[self methodToCall];
}
}
}

ios - UIPanGestureRecognizer how to get the touched coordinate relative to [gestureRecognizer view]

In my code I need to find the coordinate a user touched and is currently panning.
I've set up the following code based on - Touch Coordinates from UIPanGestureRecognizer
It looks as following:
CGPoint pos = [gestureRecognizer locationInView:[gestureRecognizer view]];
However the values returned by this method are either negative, or larger than the view's own frame. How can that be? What am I doing wrong?
Thanks
Try this one its giving me the coordinates of x and y
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint touchPoint = [gestureUp locationOfTouch:0 inView:gestureUp.view];
if (touchPoint.y <= 160)
{
if (gestureUp.direction == UISwipeGestureRecognizerDirectionUp)
{
NSLog(#"the location x...%f",touchPoint.x);
NSLog(#"the location y...%f",touchPoint.y);
}
else
{ }
}
return YES;
}

UIPanGestureRecognizer stop calling the selector

I'm having trouble to work with UIPanGestureRecognizer as it just calls the selector when I have my finger moving, I want it to keep calling the selector even my finger is standing at the same place.
There are 4 objects on the screen one at the top, one at the right side, one at the left side and one at the bottom. I have an object at the center of the screen (this is the one I'm moving with the panGesture). When this object touches the others I want it to give me a Log, it works when it touches but if I keep my finger at the same place it stops to give me logs, if I move a little it starts to give me logs again.
Is there anyway I can keep calling the selector even with my finger at the same place?
here is a code example:
- (void)moveObject:(UIPanGestureRecognizer *)sender
{
CGPoint translation = [sender translationInView:self.limiteDirecional];
[sender setTranslation:CGPointMake(0, 0) inView:self.limiteDirecional];
CGPoint center = sender.view.center;
center.y += translation.y;
int yMin = 0;
int yMax = self.limiteDirecional.frame.size.height;
if (center.y < yMin || center.y > yMax )
return;
sender.view.center = center;
center.x += translation.x;
int xMin = self.limiteDirecional.frame.size.width;
int xMax = 0;
if (center.x > xMin || center.x < xMax)
return;
sender.view.center = center;
if (CGRectIntersectsRect(sender.view.frame,self.Top.frame)) {
NSLog(#"TOP");
}
if (CGRectIntersectsRect(sender.view.frame,self.Botton.frame)) {
NSLog(#"BOTTON");
}
if (CGRectIntersectsRect(sender.view.frame,self.Right.frame)) {
NSLog(#"RIGHT");
}
if (CGRectIntersectsRect(sender.view.frame,self.Left.frame)) {
NSLog(#" LEFT");
}
if (sender.state == UIGestureRecognizerStateEnded) {
sender.view.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
}
}
I'm not entirely following the logic of your routine, so I'll provide a generic template of what a solution might look like when you want continuous events in the middle of a gesture, whether the user is moving their finger or not. Hopefully you can adapt this technique for your own purposes.
This uses CADisplayLink, which is considered a better technique for animation than the older technique of using a NSTimer. To use CADisplayLink, though, you need to add the needed framework, QuartzCore.framework, to your project, if you haven't already. Also note that in my gesture recognizer, I'm checking the state of a gesture, to know whether we're starting a gesture, in the middle of one, or ending one:
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface ViewController ()
#property (nonatomic, strong) CADisplayLink *displayLink;
#property (nonatomic) CGPoint translationInView;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(handleGesture:)];
// I'm adding to the main view, but add it to whatever you want
[self.view addGestureRecognizer:gesture];
}
- (void)startDisplayLink
{
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(handleDisplayLink:)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)stopDisplayLink
{
[self.displayLink invalidate];
self.displayLink = nil;
}
- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
NSLog(#"%s translationInView = %#", __FUNCTION__, NSStringFromCGPoint(self.translationInView));
// Do here whatever you need to happen continuously while the user is in the
// middle of the gesture, whether their finger is moving or not.
}
- (void)handleGesture:(UIPanGestureRecognizer *)gesture
{
self.translationInView = [gesture translationInView:gesture.view];
if (gesture.state == UIGestureRecognizerStateBegan)
{
[self startDisplayLink];
// Do whatever other initialization stuff as the user starts the gesture
// (e.g. you might alter the appearance of the joystick to provide some
// visual feedback that they're controlling the joystick).
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
// Do here only that stuff that actually changes as the user is moving their
// finger in the middle of the gesture, but which you don't need to have
// repeatedly done while the user's finger is not moving (e.g. maybe the
// visual movement of the "joystick" control on the screen).
}
else if (gesture.state == UIGestureRecognizerStateEnded ||
gesture.state == UIGestureRecognizerStateCancelled ||
gesture.state == UIGestureRecognizerStateFailed)
{
[self stopDisplayLink];
// Do whatever other cleanup you want to do when the user stops the gesture
// (e.g. maybe animating the moving of the joystick back to the center).
}
}
#end
You can achieve a similar effect if you use NSTimer, too. Whatever works better for you.

Setting position of UIView using IF statement

In the application I am creating, I have a UIView named AdvancedView1. The user can drag the view around the screen. The user needs to drag the view to a certain position on the screen. If the view is dropped into a certain area, then the view would "snap" into a defined location. When trying to use IF AND statements, I am getting an error. Any suggestions?
Also "origin" is a CGPoint declared in the .h file.
- (void)pan:(UIPanGestureRecognizer *) gesture
{
if (gesture.state == UIGestureRecognizerStateChanged)
{
CGPoint origin = [gesture locationInView:[self superview]];
[self bringSubviewToFront:[self superview]];
[self setCenter:origin];
}
if (gesture.state == UIGestureRecognizerStateEnded)
{
if (origin.x >= 574.0 && origin.x <= 724.0 ) {
self.frame = CGRectMake(574.0, 184.0, self.frame.size.width, self.frame.size.height);
}
}
}
I am getting the following error for "origin.x >= ...."
"Request for member "x" in something not a structure or union"
origin variable scope is limited to the 1st if block and it is not visible in the 2nd one. Move its declaration to the function scope:
- (void)pan:(UIPanGestureRecognizer *) gesture
{
CGPoint origin = [gesture locationInView:[self superview]];
if (gesture.state == UIGestureRecognizerStateChanged)
{
[self bringSubviewToFront:[self superview]];
[self setCenter:origin];
}
if (gesture.state == UIGestureRecognizerStateEnded)
{
if (origin.x >= 574.0 && origin.x <= 724.0 ) {
self.frame = CGRectMake(574.0, 184.0, self.frame.size.width, self.frame.size.height);
}
}
}

Resources