I have this app using which one can draw basic shapes like rectangle, eclipse, circle, text etc.
I also allow free form drawing, which is stored as set-of-points, on the canvas.
Also a user can resize and move around these objects by operating on the selection handles that appear when an object is selected.
In addition the user should be able to zoom and pan the canvas.
I need some inputs on how to efficiently implement this drawing functionality.
I have following things in mind -
Use UIView's InvalidateRect and drawRect
Have a UIView for the main canvas and for each inserted object - invalidate the correspoding rect and redraw all the objects which intersects that rect in the drawRect function of the UIView.
Have a UIView and use CALayer ?
every one keep mentioning about the CALayer , I dont have much idea on this, before I venture into this I wanted a quick input on whether this route is worth taking.
like, https://developer.apple.com/library/ios/#qa/qa1708/_index.html
Have a UIImageView as canvas and when drawing each object, we do this
i) Draw the object into offscreen CGContext, basically, create a new CGContext by using UIGraphicsBeginImageContext, draw the shape, extract the image out of this CG context and use that as source of UIImageView's image property, but here how do I invalidate only a part of the UIImageView so that only that area gets refreshed.
Could you please suggest what is the best approach?
Is there any other efficient way to get this done?
Thanks.
Using a UIImage is more efficient for rendering multiple objects. But Using a CALayer is more efficient when moving and modifying a single object because you don't have to modify the other objects. So I think the best approach is to use a UIImage for general drawing and a CALayer for the shape that is being modified. In other words:
use a CALayer to draw the shape being added or modified, but don't draw it on the UIImage
use a UIImage to draw the other shapes
But OpenGL is still the most efficient solution, but don't bother with that if you don't have too many objects to draw.
If you want to draw polygons, you'll have to use Quartz framework, and have your drawing methods based on CALayer. It doesn't really matter which view you'll put your CALayers in, UIImageView or UIView. I'll say UIView since you won't be needing UIImageView's properties or methods for drawing.
Related
So I just discovered QuartzCore, and I am now considering to replace a UIImageView containing a bitmap with a UIView subclass doing things like
CGContextFillEllipseInRect(contextRef, rect);
They would look exactly the same: the bitmap is just a little filled circle.
The very view I'm replacing is playing an important role in my app: it's being dragged around a lot.
Question: performance wise: should I bother? I can imagine that the vector circle is being recalculated all of the time, while the bitmap is just buffered. Or that the vector is easier to digest than a bitmap.
Can anyone advise?
thanks ahead
All UIView's on iOS are layer backed. So drawRect will only be called once and you will draw to the CALayer backing the view. You can have it draw again by calling setNeedsDisplay. When you are dragging the view around and drawing it, the view will render from the layer backing. Using a UIImageView is also layer backed and so the end result should be two layer backed views. The one place where you may see a difference is in low memory situations when the view is not visible (though I am not sure).
On my table view, I want to display small circles of certain colors that will provide context for the information. The circles should be in the location that the image would usually be in (the left hand side). Is there an easy way to do this? I was thinking that I could create a new image view and simply draw on it using some drawing routines. The problem is I don't know any of these drawing routines, or at least I don't know how to use them outside of a drawRect function.
Well, the easiest way would be to include the different images in your bundle and conditionally set them to the cell's imageView's image property in cellForRowAtIndexPath:.
However, if you're looking for alternative's you could subclass UITableViewCell, and use CAShapeLayers to draw them programmatically and add them to the cells layer in what ever position you want.
Here's an example of how to use CAShapeLayer to draw a circle:
iPhone Core Animation - Drawing a Circle
i have a subclass of UIView that displays own content. I'd like to animate the content.
The content is self-drawn in an own drawRect:, i wonder what possibilities are there to animate it. The content itself consists of graphical shapes that change their form.
I don't see a way to construct the content with subviews that can then be animated themselves.
Is there a way to use an UIView animation block?
Are there other possibilities? I would not want to animate this using OpenGL ES, this would be my last choice.
Thanks for any hints
Torsten
are you sure you can't use CALayer? They are made for this! You can create complex frames/textures (you wrote you have geometric shapes) and apply animated transforms to them.
Consider that if your shapes don't fit in the (really wide array of possibility) of shapes, you can basically draw any line using a CALayer: you create a layer of the proper length and width then simply translate and rotate it as needed (and of course translation an rotation are "animatable").
I have a custom view with some drawing on it.
I want to resize it to a new proportion and I want the pattern I drew in it's drawRect to also be resized by the same proportion.
Is there anyway I can accomplish this without refreshing and redrawing everything.
This should be happening for you automatically with the default contentMode, which is UIViewContentModeScaleToFill. contentMode determines how to adjust the cached bitmap without forcing a new call to drawRect:. Also see contentStretch which allows you to control which part of the view is scaled.
you will have to redraw it for the new proportion.
For that you have to store the points that made the CGPath and scale the points according to the new proportion and render it again.
Redrawing CGPath needs attention.
If you have used simple moveTopoint / AddlinePoint you can do it just by storing points in an array. You can scale and redraw it later.
If you can used functions like addcurveTopoint etc., storing points in array won't work.A general purpose way is needed.For that you have to use the CGpathApply function. You can see an example it here. http://www.mlsite.net/blog/?p=1312
If you need to zoom and no interation neeeded you can take a scrrenshot and and zoom the image.
I am trying to draw zoomable graphics onto the screen. I currently have a UIView inside of a ScrollView and I'm wondering what the best way is to go about handling/implementing zooming of the graphics I've drawn on the screen.
You'll probably want to use something along the lines of what I describe in my answer here.
During the pinch-zooming event, a transform will be applied to your UIView, which will zoom the content but will lead to blurring. Once the zooming event is finished, use the -scrollViewDidEndZooming:withView:atScale: delegate method to determine the new scale factor and resize and re-render your UIView appropriately. If you're doing your drawing using Core Graphics within the -drawRect: method of your UIView, this should be pretty easy to manage.