How do we create a bounce effect when user touch a UIView?
User touch and hold the view, the view shrink in size.
When user release it, it pops back and bounce to it's normal size.
I have no idea how to explain this. But i would say It's like the one on the Tinder user's picture when it's pressed..
To have that effect you can you can use UIKit Dynamics and here is a sample code provided by Apple itself. You can use UIDynamicAnimator and UIAttachmentBehavior to achieve what you want.
You can also use UIControlEventTouchDown and UIControlEventTouchUpInside event of UIButton to handle this case, if not UIDynamicBehavior.
Thanks, hope this helps.
For handling the touch gesture i would suggest adding a Long Press Gesture Recogniser to the view in question. Control drag to create a function like this
#IBAction func longPress(sender: AnyObject)
{
if sender.state == UIGestureRecognizerState.Began
{
//Shrink animation
}
else if sender.state == UIGestureRecognizerState.Ended
{
//Bounce animation
}
}
I'm not that familiair with creating my own animations, but I have used this library called Spring (https://github.com/MengTo/Spring) in the past which was really easy to install and use to add good looking animations.
Related
I have a UIView that contains many UIView subviews. When the user tries to pan gesture one of the subviews, I want them to be able to drag it anywhere else on the screen.
However, I can only drag these smaller views within the bigger UIView they are contained in. When the user first tries to pan gesture the smaller view, is there any way to programmatically create a second UIView on top and then drag around the second UIView instead? The second UIView would be completely new from the smaller view that was first touched.
This is the handler function I have so far, just for reference. I don't know where I would programmatically create the second UIView, though. Any help would be greatly appreciated:
#objc func handlePanGesture(sender: UIPanGestureRecognizer) {
// get translation
var translation = sender.translation(in: view)
sender.setTranslation(CGPoint.zero, in: view)
// drag around current UIView
var newView = sender.view as! UIView
newView.center = CGPoint(x: newView.center.x+translation.x, y: newView.center.y+translation.y)
newView.isMultipleTouchEnabled = true
newView.isUserInteractionEnabled = true
if sender.state == UIGestureRecognizer.State.began {
// add something you want to happen when the Label Panning has started
}
if sender.state == UIGestureRecognizer.State.ended {
// add something you want to happen when the Label Panning has ended
}
if sender.state == UIGestureRecognizer.State.changed {
// add something you want to happen when the Label Panning has been change ( during the moving/panning )
} else {
// or something when it's not moving
}
}
Is there any way to be able to drag the smaller views anywhere while maintaining the same layout I have right now
Because of the way touch works, it is impossible by default for a view to be touched when it reaches the boundaries of its superview. But you can overcome that limitation by overriding hitTest in the superview.
A very common pattern that enables dragging of views outside of their superview, is to create a snapshot or clone of the original view as soon as the gesture begins, you can of course hide the original view so to the user it feels like the same UI element is being dragged. It's a pattern used by Apple in their drag and drop sample code here
https://developer.apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_custom_view
Have a look at line 36 in ViewController+Drag.swift for the relevant code.
I would like to programmatically launch a UILongPressGesture when a user touches a button. This was asked years ago at How can I send a UILongPressGesture programmatically? but I'm wondering if there's a cleaner or more modern solution.
My existing UILongPressGestureRecognizer code (which maps actual user interactions to functionality) works as follows:
view.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(longPress)))
where longPress is defined as:
#objc func longPress(sender: UILongPressGestureRecognizer) {
switch sender.state {
case .began:
// Display a 'hover' animation for a specific UIView
....
case .changed:
// Move existing hover animation
...
default:
// Complete the hover animation
...
}
}
Desired Functionality
I am using this long press to display a 'hovering' effect for whatever UIView is selected by the user. I also want to provide a button to start the long press automatically (bypassing the longPress where sender.state == .began). My projected solution is programmatically creating the .began long press, creating a gesture object that users can drag around the screen (possibly even translating the UILongPressGestureRecognizer to a UIPanGestureRecognizer if possible), and then continuing the hover animation logic with that new gesture.
I found a much cleaner solution to the problem at hand - Replacing the desired button with a UIView containing its own UILongPressGestureRecognizer. I set this gesture's minimumPressDuration to 0 so it behaves equivalently to a button's touchDown event. This new gesture uses the same longPress function from the original question without requiring any additional code to trigger.
I want to make my UIView swipeable by X-axis and by Y-axis separately. For example if user swipes view vertically it triggers one action and if user swipes view horizontally it triggers another action. I don't know how to implement this correctly so I'm thinking of attaching two UIPanGestureRecognizers to my view. Is it wrong?
Just use a single UIPanGestureRecognizer and use its translation(in: UIView?) and velocity(in: UIView?) functions to determine which direction the user is swiping.
Don't use two Gesture use only single UIPanGestureRecognizer and call this method with your panGesture:
-(void)moveVerticallyAndHorizentally:(UIPanGestureRecognizer *)gesture{
CGPoint velocity = [gesture velocityInView:self.view]; // you can use your own view
if (fabs(velocity.y) > fabs(velocity.x)) {
// vertical motion
}
else if (fabs(velocity.x) > fabs(velocity.y)){
// Horizental motion
}
}
Hope this will help you.
I use a ImageScrollView from here, which is basically a UIScrollView to allow pinch to zoom into a picture. I now wanted to add the possibility to swipe down the picture to dismiss the view controller. I created a UIPanGestureRecognizer and it works fine if zoom scale is at the minimum value (so the whole picture is visible without zoom). But how can I skip the pan gesture recognizer if the zoom scale is above the minimum value? Because it lays on top of the ImageScrollView, I can't scroll in the picture because scrolling gesture is fetched by the UIPanGestureRecognizer. Any idea how to solve this?
For show image like whatsApp imageView functionality you go with the apple framework QuikLook. It will automatically handle Zoom, Dismiss the image while Swipe etc.
It also support for the documents. It will reduce your effort a lot
It's too easy to handle this operation by adding a trigger on swipe action (gesture calling method).
When zoomScale > minimumValue; set returnstatement
A simple example with Swift 4:
let zoomScale: 1.0
let minimumValue: 0.5
func handlePanGesture(gesture: UIPanGestureRecognizer) {
if (#<set pan gesture down moving condition>#) {
if (zoomScale > minumumValue) {
return
}
}
// perform your next operations
}
I am trying to achieve an effect in an application I am writing and maybe you can help.
The view hierarchy is reasonably complicated at this point so for simplicity let’s just say I have a UILabel with it’s Alpha value set to 0.
Currently I’m using a UILongPressGestureRecognizer which is after a couple of seconds, calling a method that updates the text of the UILabel and executes a UIView Animation block to display it nicely (set's the Alpha back to 1 over the course of 1 second - fading it in).
This Block fades in the newly updated label, then in it’s completion block fades it back out over the course of another second.
This is OK, but what I really want is to have the label fade in (via UIView Animations or whatever) after a long press (say 3 seconds). Then stay on screen while the press is still active, then fade out a second after the touch is lifted.
How can I achieve this effect?
Should I forget about gesture recognizers and move to UIView animation blocks and pole the various touch up touch down states?
Thanks for reading,
Regards,
John
Every UIGestureRecognizer have state. When handle long press, just check state.
- (void)handleLongPress:(UILongPressGestureRecognizer*)longPress
{
if(longPress.state == UIGestureRecognizerStateEnded){
//do what you want
NSLog(#"%#", #"end");
}
}
The long press recogniser will work, you just need to check the state to know what to do. When the gesture is first recognised, start the fade in. When the gesture is completed, start the fade out, but using the method which allows you to set the start delay.
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender
{
if (sender.state == UIGestureRecognizerStateEnded) {
// fade out, delayed
}
else if (sender.state == UIGestureRecognizerStateBegan) {
// fade in
}
}