I'm trying to recreate the double tap to zoom in and two finger tap to zoom out on a map, and I'm having some weird animation slowness specifically when I two finger tap to zoom out. (I have to do this because I'm anchoring the center point on zooming, which is not possible with the default double tap and two finger tap gestures)
When I'm at a close zoom level it's not a problem, but once I get to a city zoom level and farther out, the animation takes an extremely long time. If I set animated to NO on setRegion it jumps to the zoom level I want without delay, which leads me to believe there's no trouble loading the bigger region.
In viewDidLoad I set zoomEnabled = NO and add a two finger tap gesture recognizer and double tap gesture recognizers. (double tap gesture recognizer has the same problem)
My two finger tap code is simply this:
- (void)mapTwoFingerTapped:(UITapGestureRecognizer *)doubleFingerTapRecognizer
{
double zoomScale = 2;
MKCoordinateSpan span = MKCoordinateSpanMake(self.map.region.span.latitudeDelta * zoomScale,
self.map.region.span.longitudeDelta * zoomScale);
[self.map setRegion:MKCoordinateRegionMake(self.map.region.center, span) animated:YES];
}
Which means all I do is double the latitude and longitude and set the new region. What's causing the animation to slow down and how do I bring it back to regular speed?
EDIT: I discovered this is only happening on iOS 7 devices. iOS 6 seems to be unaffected.
Just based on some experience, it sounds like you might have an open animation block from some other part of your code which is affecting the duration of the setRegion: animation. Can you walk through some of the other code beginning with the gesture?
Related
I have a ViewController with 3 UIImageView with its images. I am using Pinch, Pan and Rotate gesture on all three images. While doing Pinch or Rotation i got two finger point with opt+mouse_click. There in the finger point, if two images are pointed with each finger point, both images are moving around.
I actually don't want that move(pan) while doing opt+mouse_click, just need to rotate or zoom the images with two finger points.
Help me to resolve, Thanks in advance
You can try to limit the UIPanGestureRecognizer 's finger that touch on screen to 1 to avoid it. Rotate or zoom will need 2 fingers.
More information from Apple's doc
The maximum number of fingers that can be touching the view for this gesture to be recognized.
https://developer.apple.com/documentation/uikit/uipangesturerecognizer/1621208-maximumnumberoftouches
I'm taking the first steps in Swift
What is the best method to move UIView along X coordinate for UIPanGestureRecognizer?
Usually Programmers use translationInView for pan gesture
But I suppose the locationInView is more convenient for this purpose
translationInView provides the change in coordinates that the view has moved within the view it is contained in. That is given in the form of a CGPoint.
If you drag it to the left, it might provide the coordinates:
(-20.0, 0)
locationInView provides the location of the view in the form of a CGPoint.
If you drag it to the left and print the locationInView throughout the gesture, you will see a slur of logs with changing coordinates with the final one being its current resting place.
To move a UIView with the touch's location, you would want to set the frame property of the UIView to the gesture's locationInView in the gesture's delegate method.
A pan gesture is composed from individual touches on the screen, locationInView gives you the current position of the touch on the screen, translationInView gives you the movement relative to the previous touches.
When panning, you are usually interested more in the movement (e.g. when scrolling, you don't want to know where the scroll began and where it ended) and not in the current position. If you are using the pan recognizer for example for drag and drop, then the location will interest you in the final position (you want to know where to drop).
Let me first introduce you to the node hierarchy:
SKView->SKScene->SKNode
I've added a UIPinchGestureRecognizer to the view so that I can zoom in and out my content. Here's the code in SKScene object:
-(void)handlePinch:(UIPinchGestureRecognizer*)pinchRecognizer{
[self runAction:[SKAction scaleBy:pinchRecognizer.scale duration:0]];
pinchRecognizer.scale = 1;
}
Everything's OK except for two things:
In my node's touch events I check the position of the touch and act accordingly. Everything works fine as long as the scale of the scene is untouched. But if I zoom in or out I can no more do this. It's because even if I seem to touch the same point on the screen it's actually different before and after zooming. In Cocos2D I had exactly the same problem. But I could solve this problem by just converting the touch point to node space with convertToNodeSpace method. There should be an equivalent in Sprite Kit. What is it?
When pinching, anchor point is the lower left corner. Is there a way to make it zoom from where the pinching occurs?
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 have an imageView nested inside of a scrollView that allows me to view an image, pinch to zoom, and pan around if I am zoomed in enough. Using a custom GestureRecognizer, I have (per the request of the person I'm building this app for) overridden the default behavior of the one finger pan so that it does something other than pan. This works perfectly.
Now the problem is that I still need the ability to pan around the image like I could with the one finger pan, I just need this to now be with two fingers. Is there a solution that can be implemented to utilize the already available features of the nested imageView? Or do I need to go through and after the two finger gesture is recognized, write my own custom pan-logic?
Any thoughts here are greatly appreciated!
Thanks
With the newer versions if iOS you can merely adjust the parameters of the 'default' UIPanGenstureRecognizer that is already attached to the scrollView
for (UIGestureRecognizer *gestureObj in scrollView.gestureRecognizers) {
if ([gestureObj isKindOfClass:[UIPanGestureRecognizer class]])
{
UIPanGestureRecognizer *panObj = (UIPanGestureRecognizer *) gestureObj;
panObj.minimumNumberOfTouches = 2;
panObj.maximumNumberOfTouches = 2;
}
}
That should 'shift' the behavior to the 2 finger level