I want to switch between a couple views with a flick gesture using two fingers. If anyone can tell me what I need to do please help.
Without actually writing the code for you, here's what you'll need to do to track a multi-finger swipe:
First, set your view's multipleTouchEnabled property to YES so that you'll be able to track multiple touches.
In touchesBegan, store the each touches' locationInView property (this is a CGPoint).
Define a "swipe window" that limits the amount of off-axis motion you'll accept and still consider the gesture a swipe. If, for instance, you're looking to track horizontal stripes, perhaps you'd want a "swipe window" of 12x6 -- that is, if your touches move at least 12 horizontal pixels while moving fewer than 6 vertical pixels, you'll consider it a swipe.
In touchesMoved, compare the current location of the touches with the stored starting locations from step 2. If they're still in the "swipe window," do nothing. If one or both of the fingers has moved outside of its "swipe window," then cancel the swipe checking. If they've both met the requirements for a swipe, fire whatever method you want to have called when you've detected a multi-finger swipe.
In 'touchesEnded', stop tracking the swipe, since if the touches have ended but you still haven't fired the swipe method from #4, then they must not have constituted a swipe.
Hope this helps.
Related
I am trying to create a menu for my app with a few icons in a circle. User should be able to spin this menu, making the icons change their positions around this circle path, but not rotating themselves. I read this earlier http://www.raywenderlich.com/9864/how-to-create-a-rotating-wheel-control-with-uikit so I can see how to follow the finger movement, but I need this menu to have inertial spin after the touch ends. I have 2 questions about how to do this.
First one, what's the best way to make animation with icons moving around in a circle? It should be slowing down until it stops and, if user moves his finger fast enough, should be able to do more than one full circle.
Second, how do I measure speed of finger movement at the end of it? I tried to use locationInView and previousLocationInView and just spin it by difference of angles between them multiplied by some constant. Problem is, when I keep my finger in one place for a while and take it up, I still get inertial movement of the circle and in this case I don't want it to move at all.
You want to use a scroll view. Specifically you want a hidden scroll view where you attach the pan gesture recogniser from the scroll view to your custom menu view. Then you implement the delegate methods of the scroll view to redraw your menu. This WWDC video has a good overview of the process. The benefit of this approach is that you get true iOS style acceleration and deceleration for free. You don't need to worry about finger position or speed, only the content offset of the scroll view.
Unless you want to spin your finger round in a circle with the menu items. That's a different ball game...
In theory, the same approach as above can be used for spinning your finger in a circle. You would need to ensure that directionalLockEnabled was set to NO on the scroll view. The problem is that the calculations to determine the rotation of your menu view are a lot more complex. Probably you would want to be modal and check if the scroll view is dragging in the callbacks. If it is dragging you would use the touches on the pan gesture to find the exact finger location to set the rotation. You'd also want to maintain data on the instantaneous direction of finger movement so that when the touch is released... If it isn't dragging then you use the scroll view content offset to apply the deceleration effect on the rotation (using the scroll direction just before the touch was released to know how to use the content offset changes).
I'm looking for a way to slide a partially concealed tool panel from off screen like the JetBlue iPhone app does. I know how to do this with regular swipe gesture recognizers, but that app has a certain threshold, after which the panel "snaps" to the on-screen position, otherwise it hides back offscreen.
How can I implement this kind of swipe-to show, but with a threshold kind of gesture recognizer? Are there any open source projects that do this kind of UI manipulation?
I have a similar interface element in an app I've written. My interface element is a UIViewController for the entire tool panel. I put a UIButton over the gripper illustration, change the button's type to custom so it visually disappears. I connect Touch Drag Inside and Touch Drag Outside to an IBAction that adjusts the position of the panel according to where the drag moves. I connect Touch Up Inside and Touch Up Outside to an IBAction that finalizes the positioning of the view. If the touch up event happens too close to the bottom, I just close the panel. If it happens anywhere higher than that threshold I open the panel. I use UIView's animation methods to smooth out these transitions. The over extension element seen in the JetBlue app can be accomplished in the drag event handler. As the panel gets closer and closer to the limit, open the view a smaller and smaller amount with each move of the touch higher. Then in the finalization, just animate the panel back down into it's preferred ending position.
The JetBlue app differs from my app in that I have a small gripper area, but JetBlue's app allows you to swipe the whole panel to adjust position. To match that functionality, I would adjust my implementation to totally cover the panel with buttons. Each would respond to my drag events with the addition that dragging would set a flag. Then my touch up event handler would check if the flag was set. If so, finalize the dragging of the panel. Otherwise, perform the appropriate action associated with each button.
If you can already implement the basics with gestures, then you're almost there!
To be honest, while I've done exactly this in my application, I use the old fashioned touchesBegan, touchesMoved, etc.
In terms of gestures, you'll have to use UIPanGestureRecognizer so you can have full control of the drag. UISwipeGestureRecognizer only recognizes swipes.
Anyway, after a certain point, you simply translate the panel only a fraction of the distance the person dragged.
CGRect newPanelFrame = panel.frame;
if (newPanelFrame.origin.y + dragOffset > 275) {
newPanelFrame.origin.y += dragOffset / 2.0;
}
panel.frame = newPanelFrame;
In touchesEnded:withEvent: or if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
CGRect newPanelFrame = panel.frame;
if (newPanelFrame.origin.y > 275) {
newPanelFrame.origin.y = 275;
}
panel.frame = newPanelFrame;
The reason why I've never bothered with the UIPanGestureRecognizer is because I could never figure out how to get the non-cumulative translation (translationForView: is cumulative), which is necessary if you want to essentially slow down the drag after the threshold.
I was just doing some research into achieving a similar effect, stumbled across this post, and as a result decided to give JetBlue a try.
After playing with the sliding panel for a bit, I'm actually thinking the JetBlue guys actually went about this in a slightly more different manner.
The motions of the slider in the JetBlue app seem to handle much nicer than what you could do with a collection of UIGestureRecognizers; it's capable of animating at different velocities depending how quickly the user swipes it, and the rubber-banding compensates for this properly too.
So on that note, I actually think that they're not using UIGestureRecognizers, but that panel is actually just a standard UIScrollView aligned to the bottom of the app window, and with a bit of extra logic (probably applied via the delegate) that just makes sure it isn't possible for the scroll view to stop animating between the 'open' and 'shut' state.
I must rotate an image but I can't use the gestures or the slider, so I have thinked about using 2 buttons, one for clockwise rotation and the other for couterclockwise rotation of my UIImageView.
But I'm getting notified only one time for touch down event so my image rotate only one time.
There is a way to get continous touch down event when I press my button?
Is there isn't such opportunity, how can I implement this continous rotation with the two buttons?
Sorry if I've said something wrong I'm new to iOS development.
There's a couple of ways you could do this - UIButtons have touchDown and touchUp events, so you could start a process on touchDown and end it on touchUpInside. This discussion might be useful.
Alternatively, rather than using UIbuttons you might want to try detecting a touchesBegan in a particular area (say on a UIImageView containing a button-lie image), then running the rotation animation until the touchesEnded event occurs?
I know I can use UIControlEventTouchDragEnter in order to tell when I have touched a button dragged my touch outside its bounds and then re-entered those bounds. However I was wondering would it be possible to touch the screen, not on a button, and detect when I have dragged over/inside that button?
Also could someone tell me the difference between UIControlEventTouchDragExit UIControlEventTouchDragOutside
Thanks!
You would have to observe touch events on the button's superview and whenever the user's fingers move, call hitTest:withEvent: to check whether the touch coordinates lie on top of the button.
I believe the difference between UIControlEventTouchDragExit and UIControlEventTouchDragOutside is this: when the finger moves from inside the control to the outside, UIControlEventTouchDragExit fires once. Then, as long as the finger remains outside, UIControlEventTouchDragOutside fires on each move. But you should test this yourself.
I'm trying to have a sort of gesture that will seamlessly switch between a group of images this part I have sorted. The part that is catching me up is the gesture to do so and how I might introduce acceleration.
Basically the user would swipe as normal and after the swipe is registered it would change the image displayed and the faster once swiped the faster the image would change ideally it would then keep that speed until the users finger was lifted leaving the possibility to just scroll repeatedly through the images.
Any direction someone could give me would be great.
Thanks.
Assuming you would be using a UIScrollView for this, setting the scrollView.decelerationRate property would allow you to manipulate the deceleration rate/scroll speed. To calculate the "swipe speed", take a look here: Detecting Special touch on the iphone for some pointers.