I have drawn 5 circles in in my app one above the other . But i want to perform different operations when i touch each circle and there is only one touches began where I can perform touches for the entire view.. can anyone help me how to do that.
Either process the coordinates of the touch to "grab" a specific circle (you know their coordinates if you have the origins and radii), or put each circle into its own view, and make five subviews/circles of a parent view. Pass the touch down the view chain until the coordinates overlap.
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 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).
How can pixels be drawn at a touch location?
If the user touches a certain area of a view, how are the locations used to draw/mark the location with e.g black color?
What kind of view is this or how is this drawing done?
Generally, if you're using Quartz you'll:
handle your touch events
store the points that are streaming in in some datastructure
invalidate your view so it draws
override drawRect and draw the points you stored in 2.
UIBezierPath is a class that can help with this. You can essentially "draw into" an instance of UIBezierPath when you receive the touch events, then render the object in drawRect.
Anyone who has gone through the Stanford CS193P class on iTunes will recognize this from Assignment 3 (HelloPoly). For those not familiar:
I have a custom view called polyView, an instance of PolygonView, a subclass of UIView. On this view, I use CGContextDrawLinearGradient to paint a color gradient over the entire rectangular view. Then I use CGContextDrawPath to stroke and fill a polygon within the bounds of polyView. And I have a UILabel called nameLabel in the center of the view (and polygon) that displays the name of the polygon (triangle, quadrilateral, pentagon, etc.). All of this works fine, and the code to do all this is in the -(void)drawRect method of the PolygonView class.
Where I ran into trouble is with an additional requirement to rotate the polygon within the view in response to user gestures. I used CGAffineTransformRotate() in response to touchesBegan() and touchesMoved() events within the PolygonView class, and this basically works, too. But I can only rotate the entire polyView, not just the polygon drawn on it. I'm sure I could go back and recalculate the path of the polygon and redraw/fill the path in response to each touchesMoved() event, but that would be expensive and can't be the best method. How can I use CGAffineTransformRotate to rotate just the polygon, without rotating the gradient-filled view or the label in the center?
Or is there some way to create the polygon on a layer that I can place over the background polyView at the desired rotation angle?
Thanks for any help you can give a beginner here!
Duane
You can do a CGContextSaveGState(...) just before doing the rotation transformation, then drawing the polygon and restoring the drawing state with a CGContextRestoreGState(...) afterwards, so as not to affect any other drawing in the view later.
I'm writing an application that uses your finger to draw simple diagrams. I have it working for the most part but now I'm trying to optimize its performance. When the user swipes their finger fast, I can't capture enough touch events to draw a smooth path.
Here's my current approach:
1) I subclassed a UIView and added a poroperty to a CGLayer (gets created lazily and is the same size as my UIView).
2) My UIView subclass responds to touch events by storing the current and last touch points in instance variables.
3) My view's setNeedsDisplay is called and in the draw rect , do the following:
- draw a line from the previous touch location to the current touch location to the CGLayer
- draw the entire CGLayer to my views context in one go
The main problem is when a user swipes fast I get relatively few touch events, so the lines I draw between the touches are long and makes the path look jagged not smooth.
My questions:
1) Does drawRect (on my UIView subclass) and my touch event handlers on my UIView subclass get called in the same thread? I.e. could I have to threads executing (one in a touch event and the second in my draw rect)?
If no - do touch events get queued up while drawRect is being called? And how can I improve performance - simply improve performance of drawRect?
If yes - how can I get more touch events to happen so I can draw a smoother path?
Thanks.
Another approach is to interpolate the curve between the sample points. When the finger drag starts, begin collecting sample points. As the number of points increase, redraw the line. With two points, draw a straight line, with three or more draw a curve. You can re-start the process when two points are sampled that lie within a defined distance. This would allow you to draw two arcs (like a 'm') in one motion - you naturally pause in the middle as you change direction, possibly long enough for two or more samples.
drawRect gets called on the main thread. But you don't have to do this. You can use the main thread to collect UI events and do the drawing on a background thread. The background thread gets notified whenever there are new touches and starts a drawing operation in its own CGBitmapContext. Then you create a CGImage and hand it over to the View: view.layer.contents = drawingImage.
If you need even more performance, consider drawing using OpenGL.
Aloo, did you have find a solution to his as I've got the same problem. I also found agreat tutorial http://www.ipodtouchfans.com/forums/showthread.php?t=132024 but it also has the same problem that if you draw fast, say a circle, the drawing isn't very smooth. It;s almost like the iPhone just can't keep up, unfortunately this has to use the core graphics stuff.
Have you tried this?
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007328-Intro-DontLinkElementID_2
I tried adding
CGContextSetLineJoin(UIGraphicsGetCurrentContext(), kCGLineJoinRound);
but this did nothing. Looks like we'll have to figure out bezier curves