IOS----Custom UIView to draw a UIView

Source: Internet
Author: User
Tags uikit

The most flexible way to draw a uiview is to finish drawing it yourself. In fact, you are not drawing a uiview, you just subclass the UIView and give the child the ability to draw their own. When a uiview needs to perform a drawing operation, theDrawRect: method is called. Overriding this method gives you the chance to get a drawing operation. When the DrawRect: method is called, the current graphics context is also set to belong to the graphical context of the view. You can use the method provided by the core graphics or Uikit to draw the graphic into that context.

You should not call DrawRect manually: Method! If you want to call the DrawRect: method to update the view, simply send the setneedsdisplay method. This will make DrawRect: The method will be called at the next appropriate time. Of course, do not overwrite drawrect: method unless you know it is absolutely legal. For example, overwrite drawrect in the Uiimageview subclass : The method is not legal and you will not get the graphics you draw.

In the DrawRect: method of the UIView subclass, you do not need to call super, because the drawrect of itself UIView : the method is empty. To improve some of the drawing performance, you can call the Setneedsdisplayinrect method to redraw the sub-region of the view, while the rest of the view remains the same.

In general, you should not optimize prematurely. The drawing code may look very cumbersome, but they are very fast. and the iOS drawing system itself is very efficient, and it does not frequently call DrawRect: methods unless forced (or called by the Setneedsdisplay method). Once a view has been drawn by itself, the result of the drawing is cached for reuse, not every time. (Apple will cache a drawing called a view of the bitmap store backfill (bitmap backing store)). You may find drawrect: The code in the method is called only once throughout the application life cycle! In fact, moving code to the DrawRect: method is a common practice for improving performance. This is because the drawing engine renders the screen directly relative to the efficiency of first taking off the screen and then copying the pixels to the screen.

When the view's backgroundcolor is nil and the opaque property is yes, the background color of the view turns black.

Core Graphics Context Property settings

When you draw in the context of a graphic, the relevant property settings for the current drawing context determine the behavior and appearance of the drawing. Therefore, the general process of drawing is to set the graphics context parameters first, and then draw. For example, to draw a red line, and then draw a blue wire. First, you need to set the line Color property of the context to red, then the red line, then set the context line Color property to blue, and then draw the Blue Line. On the surface, the red and blue lines are separate, but in fact, when you draw each line, the line color is the property of the entire context. Whether you're using the Uikit method or the core graphics function.

Because the graphics context has a certain state at each point, the state summarizes the settings for all properties of the graphics context. To facilitate the operation of these States, the graphics context provides a stack to hold the state. Calling the cgcontextsavegstate function, the context pushes the full current state into the top of the stack, invokes the cgcontextrestoregstate function, and the context finds the state at the top of the stack, and sets the current context state to the top state of the stack.

Therefore, the general drawing mode is: Call the cgcontextsavegstate function before drawing to save the current state, then set some context state as needed, then draw, and finally call cgcontextrestoregstate The function restores the current state to the state before the drawing. It is important to note that thecgcontextsavegstate function and the cgcontextrestoregstate function must appear in pairs, otherwise the drawing is likely to have unexpected errors, and there is a simple way to avoid this situation. The code is as follows:

-(void) DrawRect: (cgrect) Rect {

Cgcontextref CTX = Uigraphicsgetcurrentcontext ();

Cgcontextsavegstate (CTX);


Drawing code


Cgcontextrestoregstate (CTX);


But you don't have to do this every time you modify the context state, because your setting for a context property does not necessarily conflict with previous property settings or other property settings. You can set the line color to red first without calling the save and restore functions, and then set to blue. But under certain circumstances, you want your settings for the status to be revocable, and I'll discuss that in the next step.

Many properties make up a graphical context state that determines the appearance and behavior of the graphic as you draw. I have listed some properties and functions that correspond to modifying properties, although these functions are about the core graphics, but remember that Uikit is actually calling these functions to manipulate the context state.

Line width and line dash style


Line caps and line join point styles

Cgcontextsetlinecap, Cgcontextsetlinejoin, Cgcontextsetmiterlimit

Line Color and line mode

Cgcontextsetrgbstrokecolor, Cgcontextsetgraystrokecolor, Cgcontextsetstrokecolorwithcolor, Cgcontextsetstrokepattern

Fill Color and pattern

Cgcontextsetrgbfillcolor,cgcontextsetgrayfillcolor,cgcontextsetfillcolorwithcolor, CGContextSetFillPattern


Cgcontextsetshadow, Cgcontextsetshadowwithcolor

Mixed mode

Cgcontextsetblendmode(determines how your current drawing and existing graphics are synthesized)

Overall transparency

Cgcontextsetalpha(individual colors also have alpha components)

Text properties

Cgcontextselectfont, Cgcontextsetfont, Cgcontextsetfontsize, Cgcontextsettextdrawingmode, Cgcontextsetcharacterspacing

Whether to turn on anti-aliasing and font smoothing

Cgcontextsetshouldantialias, Cgcontextsetshouldsmoothfonts

Some other property settings:

Cropping area: Drawing outside of the cropping area is not actually drawn.

Transform (or "CTM", meaning the current transformation matrix): Changes how points in the drawing commands that you subsequently specify are mapped to the physical space of the canvas.

Many of these property settings will be explained in the next example.

Paths and drawings

Mapping a path by writing code that moves a virtual brush does not constitute a graph. Drawing a path means stroking or populating the path, or both. Similarly, you should get a similar experience from some drawing programs.

A path is composed of a point-to-dot depiction. Imagine that the drawing system is a brush in your hand, you first have to set the current position of the brush, and then give a series of commands telling the brush how to draw each subsequent path. Each new path starts at the current point, and when a path is completed, the end of the path becomes the current point.

The following is a list of the commands that the path depicts:

Position the current point


Draw a line

Cgcontextaddlinetopoint, Cgcontextaddlines

A rectangle is painted

Cgcontextaddrect, Cgcontextaddrects

To depict an ellipse or a circle


To depict an arc

Cgcontextaddarctopoint, Cgcontextaddarc

Depict a Bezier curve from one to two control points

Cgcontextaddquadcurvetopoint, Cgcontextaddcurvetopoint

Close current Path

Cgcontextclosepath This appends a line from the end of the path to the starting point. If you plan to populate a path, you do not need to use the command because the command is automatically called.

Stroke or fill the current path

Cgcontextstrokepath, Cgcontextfillpath, Cgcontexteofillpath, Cgcontextdrawpath. Strokes or fills on the current path clears the path. If you only want to use a single command to complete the stroke and fill tasks, you can use the cgcontextdrawpath command, because if you only use Cgcontextstrokepath to stroke the path, the path is erased. You won't be able to fill it again.

A function that creates a path and strokes a path or fills a path with just one command:cgcontextstrokelinesegments, Cgcontextstrokerect, Cgcontextstrokerectwithwidth, Cgcontextfillrect, Cgcontextfillrects, Cgcontextstrokeellipseinrect, Cgcontextfillellipseinrect.

A path is synthesized, meaning that it is made up of multiple independent paths. For example, a single path may consist of two separate closed shapes: a rectangle and a circle. Call the cgcontextmovetopoint function When you are constructing the middle process of a path (meaning that you have not called a stroke or fill command after you have painted a path, or called the Cgcontextbeginpath function to clear the path) , it's like you pick up the brush and move the brush to a new location so you're ready to start a separate, identical path. If you are concerned that when you begin to paint a path, the existing path and the new path will be considered a synthetic part of the existing path, you can call the cgcontextbeginpath function to specify that the path you are drawing is a separate path There are many examples of Apple doing this, but in real-world development I find it unnecessary.

The function of the cgcontextclearrect function is to erase an area. This function erases all existing drawings within a rectangle and performs clipping on the area. The result is like hitting a hole that runs through all existing drawings.

The behavior of the cgcontextclearrect function depends on whether the context is transparent or opaque. This is especially noticeable and intuitive when drawing in the context of a graphic. If the picture context is transparent (uigraphicsbeginimagecontextwithoptions The second parameter is no), then cgcontextclearrect After the function performs the erase, the color is transparent, and the other is black.

When drawing directly in a view (using drawrect: or Drawlayer:incontext: method), if the background color of the view is nil or if the color is a little bit transparent, Then the rectangular area of the cgcontextclearrect will appear transparent, and the punched hole will pass through the view including its background color. If the background color is completely opaque, then the result of the cgcontextclearrect function will be black. This is because the background color of the view determines whether the graphics context of the view is transparent or opaque.

Figure 5 Application of Cgcontextclearrect function

5, in the left side of the blue Square is dug to leave the portion of black, but on the right side of the blue square is also dug to leave the part to be transparent. But these two squares are all instances of the UIView subclass, using the same drawing code! The difference is the background color of the view, the background color of the left square in the nib file

But this has completely changed the effect of the Cgcontextclearrect function. The drawrect of the UIView subclass: The method looks like this:

Cgcontextref con = Uigraphicsgetcurrentcontext ();

Cgcontextsetfillcolorwithcolor (Con, [Uicolor Bluecolor]. Cgcolor);

Cgcontextfillrect (con, rect);

Cgcontextclearrect (Con, CGRectMake (0,0,30,30));

To illustrate the typical path of the draw command, I will generate an upward arrow pattern, I carefully avoid using the convenience function operation, perhaps this is not the best way to create arrows, but still clearly show the use of various typical commands.

Figure 61 a simple path drawing

Cgcontextref con = Uigraphicsgetcurrentcontext ();

Draw a black vertical black line, as the pole of the arrow

Cgcontextmovetopoint (Con, 100, 100);

Cgcontextaddlinetopoint (Con, 100, 19);

Cgcontextsetlinewidth (Con, 20);

Cgcontextstrokepath (con);

Draw a red triangle arrow

Cgcontextsetfillcolorwithcolor (Con, [[Uicolor Redcolor] cgcolor]);

Cgcontextmovetopoint (Con, 80, 25);

Cgcontextaddlinetopoint (Con, 100, 0);

Cgcontextaddlinetopoint (Con, 120, 25);

Cgcontextfillpath (con);

Cut a triangle off the arrow poles, using clear blending mode

Cgcontextmovetopoint (Con, 90, 101);

Cgcontextaddlinetopoint (Con, 100, 90);

Cgcontextaddlinetopoint (Con, 110, 101);

Cgcontextsetblendmode (Con, kcgblendmodeclear);

Cgcontextfillpath (con);

To be exact, we should use the cgcontextsavegstate and cgcontextrestoregstate functions around the drawing code just in case. For this example, there is no difference between adding or not. Because the context is not persisted in the call DrawRect: method, it will not be destroyed.

If a path needs to be reused or shared, you can encapsulate the path as Cgpath (the specific type is cgpathref). You can create a new Cgmutablepathref object and construct the path with multiple Cgpath functions that resemble a graph-like path function, or use the Cgcontextcopypath function to copy the current path of the graphics context. There are many Cgpath functions that can be used to create paths based on simple geometries (cgpathcreatewithrect, Cgpathcreatewithellipseinrect) or based on existing paths ( Cgpathcreatecopybystrokingpath, Cgpathcreatecopydashingpath, Cgpathcreatecopybytransformingpath).

Uikit's Uibezierpath class is packed with Cgpath. It provides methods for drawing a path to a shape, as well as setting methods for stroke, padding, and access to some of the current context state. Similarly, Uicolor provides the color used to set the stroke and fill of the current context. So we can rewrite the code we used to draw the arrows before:

uibezierpath* p = [Uibezierpath Bezierpath];

[P Movetopoint:cgpointmake (100,100)];

[P Addlinetopoint:cgpointmake (100, 19)];

[P setlinewidth:20];

[P stroke];

[[Uicolor Redcolor] set];

[P removeallpoints];

[P Movetopoint:cgpointmake (80,25)];

[P addlinetopoint:cgpointmake (100, 0)];

[P Addlinetopoint:cgpointmake (120, 25)];

[P fill];

[P removeallpoints];

[P Movetopoint:cgpointmake (90,101)];

[P Addlinetopoint:cgpointmake (100, 90)];

[P Addlinetopoint:cgpointmake (110, 101)];

[P fillwithblendmode:kcgblendmodeclear alpha:1.0];

In this particular case, the same work does not save much code, but Uibezierpath still works. If you need object features, Uibezierpath provides a convenient way:Bezierpathwithroundedrect:cornerradius:, which can be used to draw rectangles with rounded corners, if you are using the core The graphics are rather tedious. You can also just let the fillet appear in the upper-left and upper-right corners.

-(void) DrawRect: (cgrect) Rect {

Cgcontextref CTX = Uigraphicsgetcurrentcontext ();

Cgcontextsetstrokecolorwithcolor (CTX, [Uicolor Blackcolor]. Cgcolor);

Cgcontextsetlinewidth (CTX, 3);

Uibezierpath *path;

Path = [Uibezierpath Bezierpathwithroundedrect:cgrectmake (+, +, +) Byroundingcorners: (Uirectcornertopleft | Uirectcornertopright) Cornerradii:cgsizemake (10, 10)];

[Path stroke];


Figure 7 Rounded rectangle around the corner

IOS----Custom UIView to draw a UIView

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.