How to pull a view from one corner of the app? - iphone

I would like to create view that could be pulled from one corner to take full screen (like the iphone status bar that can be pulled from top).
Could you just give me an idea how to accomplish that.
Thanks

Put a small view into the corner of the screen that acts as your handle.
Add a UIPanGestureRecognizer to that view.
When the gesture recognizer's action method gets called, move the handle and the view you want to present according to the movement of the user's finger.
When the gesture ends (because the user has lifted their finger off the screen), decide whether the movement was large enough to bring in the new view or not (e.g. if the user dragged the view over >30% of the screen, you move it in, otherwise you move it back out).
Animate the view into its final position.

Related

Slide view while touching button - IOS

I'm trying to implement a view that includes social buttons.In normal state, it will be partially hide and only the "Opciones" button and the upper line is shown. This view will be shown when user touches button "Opciones" (touch gesture), then it will unhide and be shown using sliding effect until the final position that is included in the attached image.
I'm wondering which kind of control and animation I have to use.
Many thanks.

How to gently drag panel from offscreen like JetBlue iPhone app

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.

Drag a UIView part-way, then it moves on its own

I have an app with a draggable UIView placed at the bottom. The draggable view isnt totally offscreen and it has a "pull tab" that the user can drag upwards or downwards. Dragging up and down currently works, but I would like to give it the same behavior as the Apple notifications slide out drawer.
For example, if I drag the view out 50% upwards and remove my finger from the screen, then I'd like the draggable view to continue to move upwards on its own. Likewise, if the user only dragged the view out, say 30% upwards, then the view should drop back down to its default position.
Ideally, while I can do the dragging up/down, the motion isnt very "organic"....
Right now, I'm accomplishing the dragging upwards and downwards via UIPanGestureRecognizer, just in case that's relevant to the question.
Is it perhaps something along the lines of some clever math with the Y position of the draggable view, then doing the rest of the moving with some CAAnimations?
It might be a bit hard to visualize, so I've added some screens below.
Default screen with the a view at the bottom
The view dragged up via the tab on the right
Thank you!
When your UIPanGestureRecognizer's state becomes UIGestureRecognizerStateEnded, use the velocityInView: message to find the velocity of the gesture.
If the velocity is close to zero, open or close the view based on the position of the view and the previous state of the view. For example, if the view was closed and it has been pulled out more than 10%, open it. If it was open and has been pulled in more than 10%, close it. Otherwise, move it back to its pre-gesture position.
If the velocity is not close to zero, use the sign of the Y component to determine the new state of the view. If the sign is positive, close the view. If the sign is negative, open the view.
You will have to experiment to figure out exactly what definition of “close to zero” feels best.
In any case, you will want to animate the view to its final position after the gesture ends, using a short duration (probably between .1 and .25 seconds). You may want to choose the duration based on the velocity and the distance the view needs to travel. The system notifications panel does this. (Try dragging it partway down slowly vs. rapidly. It animates to its final position at different speeds depending on how fast you were dragging it when you let go.)
You will want to experiment to find the best animation curve (UIViewAnimationOptionCurveEaseOut, etc.), and you may want to use a different curve depending on whether you're opening or closing the view and the velocity of the gesture.

Nested UITapGestureRecognizers

If I have several views stacked one on top of the other (all subviews of each other) where each one has a UITapGestureRecognizer attached to it.
How can I make sure that the highest visible view received the gesture and not the furthest ancestor?
The tap gesture is only valid for the current view. Further the frame of your current view(-controller). You can create a blank view over the hole screen and put in there your current view lets say 200x200 px. (essentially it is both in the same view)
Now all gestures should respond to your topmost view-controller. The bad thing about that: you can't access the views below anymore.

custom slide to reveal toolbar

i want to do a custom toolbar, something like the slide to unlock of android phones. In idle state, the user can see a button of the bottom left of the page. the user would then tap it, drag towards the right. When the user reaches the right end, the toolbar will then 'lock'. Buttons would be located at the toolbar.
I'm think of using a customview and touchmoved functions, but what I don't know how is how to make the view move with the touch, and how to actually lock the bar.
Everytime you move your finger the touchmoved function is called. In the touchmoved function you have to redraw the whole view or just set a new frame for this view. It pretty simple as you already know how to detect touches and react on them.