How to synchronise UIView moving with swipe gesture of UIPageViewController - ios

Ok, here is the thing:
I need to have few animations happening on every screen change in my PageViewController.
So, when a user swipes, an image should fly in from the top left corner, from example.
I can make that animation to happen over time when user swipes and changes the page, but what I need is to that animation to be synchronised with the swipe movement itself.
So if a user presses the screen and starts swiping, the animation should follow user's finger and animate it's translation with the finger movement.
How can I achieve that?
I guess I need some sort of swipe gesture listener, but I failed to find any solution online. I guess I'm not using the right keywords.

You can use a UIPanGestureRecognizer to get the number of pixels swiped:
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panRecognizer_Panned:)];
[self.myViewToSwipe addGestureRecognizer:panRecognizer];
...
- (void) panRecognizer_Panned:(UIPanGestureRecognizer *)recognizer {
CGFloat pixelsMovedHoriz = [recognizer translationInView:self.vwRelativeTo].x;
}

Related

UISwipeGestureRecognizer interferes with slider

I have a view in an iOS application (Obj-C) which has an image view in the centre, and immediately below that a slider.
The image view shows album artwork, and the slider can be used to adjust the now-playing track position.
There is also a pair of left and right Swipe Gesture Recognizers. These are used to skip to the next or previous tracks.
The problem is that the swipe gesture recognizers seem to over-ride the users moving the slider thumb.
In my gesture recognizer code I check that the point touched was inside the image view, but it still stops the slider from being moved. (The thumb moves, but jumps back to it's original position when you remove your finger).
This is the code I use to reject the gesture if it's not inside the image view.
- (IBAction)swipeLeftGestureAction:(UISwipeGestureRecognizer *)sender {
// Get the location of the gesture.
CGPoint tapPoint = [sender locationInView:_artworkImageView];
// Make sure tap was INSIDE the artwork image frame.
if( (tapPoint.x <0)
|| (tapPoint.y < 0 )
|| (tapPoint.x > _artworkImageView.frame.size.width)
|| (tapPoint.y>_artworkImageView.frame.size.height))
{
NSLog(#"Outside!");
return;
}
NSLog(#"Swipe LEFT");
[_mediaController skipNext];
}
So my question is, how do I limit the gesture to work ONLY when swiped across the image view?
Try to put the code that restricts the gesture's area in gestureRecognizer:shouldReceiveTouch: and return NO in case you don't want the gesture to receive this touch. It should prevent the gesture from over taking the slider interaction.
If you're only interested in swipes that are inside the image view, then you should add the swipe gesture recognizer to the image view instead of adding it to your entire view. Then you won't need any special logic.
There is a dedicated method for checking if a point is inside a view
BOOL isPointInsideView = [_artworkImageViewpointInside:tapPoint withEvent:nil];
But I think what is happening is that if you will look at the tapPoint is that it actually outside of your imageView
And if your slider is really close to the imageView so the slider captures the movement, what you should do is check on the slider if it is intended for the slider and propagate on to the imageView if needed
Or inherit the UISlider and reduce its response rect

Give swipe gesture priority over button

I have two UIButtons in a view (one is YES, the other NO). I now want to add a "did not answer", which would be indicated by a downward swipe on the view.
The problem is that the user may swipe down on the view, but in the process hit one of the buttons. When this happens I want to ignore the button press if there was a swipe underway. If it is just a tap on a button, the answer is recorded.
So, if the swipe occurs, I want to call the swipe gesture's action method. If it is determined no swipe occurred but one of the two buttons was touched I want to call their respective action methods. But if a button was touched in the process of a swipe, I want to call only the swipe gesture's action method.
I know there is a way but I'm wondering whether there is an EASY way of doing this. TIA for suggestions.
Since UISwipeGestureRecognizer is a "discrete" gesture, it just triggers a single action when recognized and it won't allow you to detect the end of the gesture.
So to prevent other touches during the gesture, I'd recommend using a UIPanGestureRecognizer instead since it can track your gesture from beginning to end. Then you can try setting your gesture's cancelsTouchesInView property to YES to cancel all other touches in the view that happen while that pan gesture is recognized, ex:
gesture.cancelsTouchesInView = YES;
gesture.delaysTouchesBegan = YES;
Your buttons should be registering touch up in view, so that someone who taps on the button can drag off if they decide not to proceed.
For your other swipe gesture, your buttons will not register a touch up in view during a swipe gesture, even if the swipe passes over the button or ends on it.
Okay, this seems to work. On the gesture recognizer, I used:
UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(didSwipeDown:)];
swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
swipeDown.delaysTouchesBegan = YES;
swipeDown.delegate = self;
[self addGestureRecognizer:swipeDown];
They delaysTouchesBegan = YES allows it to determine whether the swipe has occurred before passing the touches on to the buttons. So, if you swipe, it calls the swipe GR, and if you touch either button, you get that. Thanks for your answers...

Delay the scrolling in a UIScrollView by changing the required finger offset

I want to make my scrollview less sensitive. This means that I want the user to have to move the finger a bit more before the view starts scrolling. Does anyone knows how to achieve this? I remember seeing a property that would let me set a required number of pixels before a scroll is detected. But it could just be my imagination. Perhaps what is required is to modify the underlying UIPanGestureRecognizer inside the scroll view?
The reason for this is that I am detecting a press on the view, so as long as the user has the finger there a function is constantly running. This function has to have the absolute priority, but the user might want to scroll the view instead, so I am canceling the function by detecting if the scrollview was scrolled. Everything works perfectly, except when the user is moving his hand/arm, his finger "might slip" a little bit, thus canceling the function since the scrollview starts scrolling.
Edit: (to address some of the confusion in the question)
How do I delay the scrolling in a scrollview by requiring the user to move the finger more before the scrollview starts scrolling?
I write an Answer so i can write code, but i am not entirely sure why you want the finger-offset. Lets assume you have an Area on your scrollview in which the user can longpress. During longpress you want to do some calculating and you do not want the scrollview to move. In my opinion there are two possibilties: Either you want the longpress to cancel if the finger moves a certain amount ("difficult to archive") or you want to supress the scrollview movement as long as the finger is pressed down, no matter what the movement is ("simple to archive").
Simple Solution:
- (void)yourUIBuilder {
...
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressChanged:)];
[recognizer setDelegate:self];
[recognizer setMinimumPressDuration:0.3];
[yourScrollView addGestureRecognizer:recognizer];
}
- (void)longPressChanged:(UIGestureRecognizer *)recognizer {
switch (recognizer.state) {
case UIGestureRecognizerStateBegan:
// start your calculations
break;
case UIGestureRecognizerStateChanged:
break;
default:
// stop your calculations
break;
}
}

Modifying screen swiping functionality for use in a slider (iOS7)

I am interested in trying to modify the functionality that allows full-screen swiping from one view to another in order to create a "slider" that is the size of the entire page -- i.e. dragging/swiping/sliding anywhere on the page has an effect of some kind.
It doesn't need to be visible. For example, I might have a solid red screen that I can change the colour of by dragging to the right anywhere, having it gradually change to blue.
Is this possible?
Using a UIPanGestureRecognizer, you can track finger movement on the screen, then use translationInView to find out how much the user's finger moved by, and change the color somehow based on that number
UIPanGestureRecognizer* pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.view addGestureRecognizer:pan];
And handle it:
-(void)handlePan:(UIPanGestureRecognizer*)sender
{
CGFloat xMovement = [sender translationInView:sender.view].x;
// Do something with the movement
// Then reset the translation
[sender setTranslation:CGPointZero inView:sender.view];
}

Detect sliding up gesture on iOS

Which gesture am I looking to capture if I want to detect when the user slides his/her finger upwards (think of scrubbing through a song, that kind of motion, but up) and adjust a setting as a result (I don't want to use a UISlider).
What would you guys recommend for this? Is that a pan gesture recognizer or a swipe?
Try this:
UISwipeGestureRecognizer *swipeRecognizer =
[[UISwipeGestureRecognizer alloc]
initWithTarget:self
action:#selector(swipeDetected)];
swipeRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
[self.view addGestureRecognizer:swipeRecognizer];
A swipe is one-time simple motion; observe that it happened, and you respond afterwards. A pan gesture is a continuous movement that you want to able to track while it happens. Which of those do you want?

Resources