I set brush pattern using CGContext and Bezierpath on UIImageView.
Is this a good approach?
Do we have any other best practices to set brush pattern, to create different paint brush pattern.
Does anybody have different design pattern that I can use when implementing my brush?
Yes, it's fine if that's what you want to do. All a "brush" means in this context is how you want to stroke a line. If you're just trying to set the stroke pattern for a bezier path on some UIImageView then yes, it sounds like what you're doing is appropriate.
Now, depending on what your end goal is, there may be different ways to approach it. Your method might have complications when interacting with the higher level drawing in UIKit. Since you asked this 7 months ago though, I'm hoping you already figured it out.
If you are using bezierpath then you can use patternImage code in bezierpath. If you are using CGContext then adjust your strokewidth and use kcglinecap methods to get different points.
In bezierpath you can also use dashpattern so you can draw dash lines.
Related
I'm basically trying to achieve this effect. It can be done with pretty much a PNG with a transparent hole cut through it, then stacked on top of a photo.jpg UIView. OR, I've also seen a method where you can directly create a mask with CGImageMaskCreate. I don't want to use that feature because I want the user to be able to interact with the photo.jpg layer (by moving it, rotating it, etc.):
Its essentially two UIViews stacked directly on top of each other.
However, what if rather than using blue, I wanted to use another color, or even pattern an image with [UIColor colorPatternWithImage:] for the masking layer? I wouldn't want to make a million different PNGs for each case.
Would I need some way to programmatically recreate my mask? Is there some way to convert my mask shapes into code? Any help is appreciated. Thanks
CALayer has a property called mask, which is another CALayer that defines the mask to use. You could use a CAShapeLayer to define the mask, then set that as the mask of another layer that renders your obscuring image/color/pattern/whatever. You could also use a regular CALayer as the mask with your semi-transparent image as the contents, it depends on whether or not you want the ability to customize the size/shape of the hole.
Caveats: CAShapeLayer is slower than normal layers, and mask is slower than non-masking as well. You may need to make sure performance is acceptable for you. You may also want to try out the shouldRasterize flag, though this will only improve performance (at the cost of memory) as long as the layer is static (i.e. not animating).
Good day, friends.
There is a task: to draw repeating objects (UIImageView and UILabel) along the curve (if more exactly, it's an arc).
What classes should be used for it?
As an alternative to Android's Path, you can use either UIBezierPath or CGPath. The former is Objective-C, the later pure C. I recommend going with UIBezierPath as it's easier to use.
To rotate a view, use the transform property of UIView (see this question for an example on how to use it). But note that you then need to ignore the frame (it's undefined) and need to move the view by modifying the center instead.
I am trying to create a pseudo-3D square (like a scrabble tile) and I was thinking of faking it with borders. But then I couldn't find a way to set different width for different side.
Is this possible at all? If not, does anyone have any recommendation on how to do this in CALayer?
Oh, one caveat, I am already using shadow, so can't use that to fake the bevel.
Not possible with ordinary CALayer properties. You'd have to inset your layer and draw the different borders in the drawing method, or add a second larger layer to take care of that inside its drawing.
You could possibly do it with the layer's shadow properties, using -shadowOffset to only render it on two sides. However, to make it really nice you probably have to draw it yourself.
I'm trying to make a little iPad tool's for drawing simple geometrical objects (rect, rounded rect, ellipse, star, ...).
My goal is to make something very close to Keynote (drawing feature), i.e. let the user add a rect (for instance), resizing it and moving it. I want too the user can select many objects and move them together.
I've thought about at least 3 differents ways to do that :
Extends UIView for each object type, a class for Rect, another for Ellipse, ... With custom drawing method. Then add this view as subview of the global view.
Extends CALayer for each object type, a class for Rect, another for Ellipse, ... With custom drawing method. Then add this layer as sublayer of the global view layer's.
Extends NSObject for each object type, a class for Rect, another for Ellipse, ... With just a drawing method which will get as argument a CGContext and a Rect and draw directly the form in it. Those methods will be called by the drawing method of the global view.
I'm aware that the two first ways come with functions to detect touch on each object, to add easily shadows,... but I'm afraid that they are a little too heavy ? That's why I thought about the last way, which it seems to be straight forward.
Which way will be the more efficient ??? Or maybe I didn't thought another way ?
Any help will be appreciated ;-)
Thanks.
I'd use the UIKit classes to do your drawing, then profile and optimise your code from there.
Apple/iPad info: link text
My first feeling was to make the 3rd way, but to be convinced, just after I've posted my message, I did some tests with just a global view and over 200 geometrical forms (Rect, Rounded Rect and Ellipse) on it and I move only a half with touchMoved event. I did this test with the way 1 (Subclassing UIView) and the way 3 (Subclassing NSObject), the way 2 seems to me too restrictive and not help me at all.
The resuslt is that the way 1 seems to be more efficient... There is no lag when I move 60 objects together ! Moreover using this way would probably help me because using view comes which some interesting functions like touch detection on complex path (see UIBezierPath), object hierarchy handled by the UIView classe...
So I will use that way and come back here to share my results ;-)
Regards
It's better to use CGLayer objects. The benefits are:
It's much faster and more memory efficient. For simple objects, adding a view is much more expensive and complicates the view hierarchy. For complicated objects, the caching done on CGLayers can boost performance.
It's easy to group objects together. you just put everything in a new layer, and voila! There's almost no overhead.
Using CGLayer and other Quartz objects gives you a lot more flexibility.
The only drawback is that you have to directly use Quartz 2D. It's not really difficult, but needs some learning if you haven't used it before.
CAShapeLayer pretty much handles your option 2. It does rect and rounded rect (see cornerRadius) by default, or you can give it a path for any arbitrary shape. For your option 1, you can use a CAShapeLayer with a UIView instead of implementing drawRect and it may be faster.
Currently, I have a UIView subclass that "stamps" a single 2px by 2px CGLayerRef across the screen, up to 160 x 240 times.
I currently animate this by moving the UIView "up" the screen 2 pixels (actually, a UIImageView) and then drawing the next "row".
Would using multiple CALayer layers speed up performance of rendering this animation?
Are there tutorials, sample applications or code snippets for use of CALayer with the iPhone SDK?
The reason I ask is that most of the code snippets I find that demonstrate simple examples of CALayer employ method calls that do not work with the iPhone SDK. I appreciate any advice or pointers.
Okay, well, if you want something that has some good examples of CA good that draws things like that and works on the phone, I recommend the GeekGameBoard code that Jens Aflke published (it is an improved version of some Apple demo code).
Based on what you are describing I think you are doing somthing way more complicated than it needs be. My impression is you want basically a static view that you are animating by shifting its position so that it is partially off screen. If you just need to set some static content in your drawRect going through layers is not going to be faster than just calling CGFillRect() with your color. After that you could just use implicit animations and the animator proxy on UIView to move the view. I suspect you could even get rid of the custom drawRect: implementation with a patterned UIColor, but I honestly have not benchmarked the difference between the two.
What CALayer methods are you seeing that don't work on iPhone? Aside from animation features tied to CoreImage I have not noticed much that is missing. The big thing you are likely to notice is that all views are layer backed (so you do not need to do anything special to use layers, you can just grab a UIView's layer through the layer accessors methos), and the coordinate system has a top left origin.
In any event, generally having more things is slower than having fewer things. If you are just repeating the same pattern over and over again you are likely to find the best performance is implementing a custom UIView/CALayer/UIColor that knows how to draw what you want, rather than placing visually identical layers or views next to each other.
Having said that, generally layers are lighter weight than views, so if you have a lot of separate elements that you need to keep logically separated you will find that moving to layers can be a win over using views.
You might want to look at -[UIColor initWithPatternImage:] depending on exactly what you are trying to do. If you are using this two pixel pattern as a background color you could just make a UIColor that draws it and set the background.
What CALayer methods are you seeing that don't work on iPhone?
As one example, I tried implementing the grid demo here, without much luck. It looks like CAConstraintLayoutManager and CAConstraint are not available in QuartzCore.h.
In another attempt, I tried a very simple, small 20x20 CALayer object as a sublayer of my UIView's layer property, but that didn't show up.
Right now, I have a custom UIView of which I override the drawRect method. In drawRect I grab a context and render two types of CGLayerRefs:
At "off" cells I draw the background color across the entire 320x480 canvas.
At "on" cells, I either draw a single CGLayerRef across a grid of 320x480 pixels (initialization) or across a 320x2 row (animation).
During animation, I make a UIImageView clip view from 320x478 pixels, and draw a single row. This "pushes" my bitmap up the screen two pixels at a time.
Basically, I'd like to test whether or not using CALayer will accomplish two things:
Make my rendering faster, if CALayer has less overhead than what I'm doing now
Make my animation smoother, by letting me transition a layer up the screen smoothly
Unfortunately, I can't seem to get a basic CALayer working at the moment, and haven't found a good chunk of sample code to look at and play with.