This question already has an answer here:
Resizing a rectangle drawn in drawRect
(1 answer)
Closed 9 years ago.
I have a rectangle drawn using drawRect method. I need to update this rectangle.
But I don't know how to create an instance of it.
I need to delete the previously drawn rectangle (or) change the frame of the previously drawn rectangle.
How can I do this?
The system keeps track of which part of your view it thinks is “dirty” (needs to be drawn). When the view is first created, the entire view is dirty. When you send setNeedsDisplay to the view, that marks the entire view dirty. If you send setNeedsDisplayInRect:, the specified CGRect is added to the part of the view that is considered dirty.
Before the system sends your view the drawRect: message, it clears the entire dirty region of the view to the view's background color. So if you send setNeedsDisplay to your view when you want to erase the previously drawn rectangle, you don't need to worry about erasing your rectangle in drawRect:; the system has already erased it for you. But it also means that if there was anything in the dirty region that you didn't want erased, you must draw it again before returning from drawRect:.
Related
My question might be answered somewhere but I just couldn't find solution after a long research.
I need to draw visually shapes (curves, lines, rectangles etc.) on iPhone one on top of the previous. I did that using CGContext to draw over an image and it's working fine. However in my app the drawing view resizes on device rotation and the lines become blurred because of the different image size.
That's why I subclassed UIView and to call setNeedsDisplay from touchesMoved and touchesEnded. In drawRect I'm passing the point and... almost everything works OK.
However I have two problems:
1. Every time drawRect is called it clears previous drawing and starts over so I can't add a new shape.
2. Second is followed by same thing - I can't make a curve as on every move drawRect is called and the previous point is dismissed and a line is added from the starting point to the current.
So am I doing the whole thing wrong and is there some other better approach to this.
Thanks in advance!
My question is very similar to this one Not drawing outside bounds when clipToBounds=NO which received no clear answer.
Basically I have a UIView, and I want to draw a line from the center of it, to the edge of the screen. Calculating where these points are is easy, using [self convertPoint:(CGPoint){0,0} fromView:[self superview]]; (which finds the origin with respect to my view's superview. But when I draw a line from my view's drawRect: it gets clipped at my view's bounds.
Is there a way to draw outside of my view's bounds? I've tried changing the clipsToBounds property, but it doesn't seem to have any effect.
I can't draw my lines from the superview because I need to do this with multiple views and some will be in front of others... figuring out the layer from the superview's drawRect seems like a bad idea.
Similarly, I don't think I can just resize my view's bounds to include the entire screen, because my views need to be dynamically re-sizable... the bounds would have to be HUGE (>20,000 points square) for this to work.
I wouldn't recommend ever drawing outside of a view's bounds. Either your view needs to resize automatically to include your drawing or you need to have transparent overlapping views. Or both. I can't think of a situation that either of these cases wouldn't cover, but I may lack imagination. =)
Likely what is happening currently is that when the super view gets redrawn it tells the super view that it needs redrawn, resulting in erasing the drawing you are doing outside. It's been a while, anyone more knowledgeable can (should!) correct me here if I'm wrong.
I don't know if "Quartz Debug" (from the standard apple developer tools install, /Developer/Applications/Performance Tools/Quartz Debug) works in the simulator, but it's worth a try. It has a mode that will show you when and how often redrawing takes place, with a border and optional delay on the refreshes.
You can do what you are asking, but you need to force redraw your sub-views every time you go outside the sub-view's bounds, meaning that your super-view needs to manually draw it's children inside of it's draw function. Essentially you would be throwing out apple's drawing paradigm and simply causing your sub-views to act like a drawing extension of your main view anyway.
Additionally, if your ranges are so dynamic you may want to consider drawing in percentages of the screen or super-view rather than in points, it may make more sense to code.
I created line chart. Now I need to display point on this chart when I tap the screen.
What would be the best method? Do I need to call drawRect method again, draw whole chart with marked point?
I'm thinking about something like transparent layer over the chart UIView.
Can I create another transparent UIView and put it on the position of my chart?
Since all drawing is done in a view's drawRect: you can only optimize your chart's drawing so it can be made to update only a part of it and use setNeedsDisplayInRect: (passing the area where the marker should be).
Or you create another UIView subclass that is layered atop of your chart and that does nothing but drawing the markers on a transparent background. Probably easier and faster to implement. It also would have another benefit:
If you make that view only as big as the bounding box of the marker you could also easily animate it, like fading it in and out. Or letting it rotate a little (to see the effect I have in mind, select the "Help" menu in Mac OS X, type something in the search field like "a", and see the marker next to a menu item move a little around a spot).
You can draw a portion of your view using setNeedsDisplayInRect:.
How would I go about drawing a view offscreen in order to perform some calculation before the view's draw is actually done? Can this be done by drawing to a temporary layer?
I am not getting your exact problem... But you can use
-(void)viewWillAppear:(BOOL)animated
this method will be called every time before your view will appear on the screen... you can do the calculation and make some changes here before view appear on the screen...
Everytime UIView's drawRect is called, the content drawn by previous drawRect (using Core Graphics) is cleared out. How can I make it so that the paths rendered from previous drawRect calls stay until I explicitly clear it?
You basically need to clip the 'dirty' part of your rect where changes have been made, and only this part will be re-drawn.
- (void)setNeedsDisplayInRect:(CGRect)invalidRect
I'm fighting this issue myself right now. The problem is there is a property on the UIView called "clearsContextBeforeDrawing" that according to the documentation is supposed to fix this problem, however it doesn't work that way in my experience.
I think ultimately the solution to this is going to be to allocate an offscreen buffer and do all my drawing there, then blt it over to the UIView in the drawRect method.
I'm pretty certain there's no way around this; it's how UIView is designed to work. If asked to, your custom view should be able to draw any part of itself at any time. This is partly because views can do more than just appear onscreen. e.g. on the desktop they can be printed, and even on the iPhone, you might wish to capture the contents of a view to a bitmap.