Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Beginning iOS5 Development.pdf
Скачиваний:
7
Добавлен:
09.05.2015
Размер:
15.6 Mб
Скачать

584

CHAPTER 16: Drawing with Quartz and OpenGL

we also set that to the appropriate value for each selection. Since all the drawing code will be in the view itself, we don’t need to do anything else in this method.

Next, look for the existing implementation of changeShape:, and add the following code to it:

- (IBAction)changeShape:(id)sender {

UISegmentedControl *control = sender; [(BIDQuartzFunView *)self.view setShapeType:[control

selectedSegmentIndex]];

if ([control selectedSegmentIndex] == kImageShape) colorControl.hidden = YES;

else

colorControl.hidden = NO;

}

In this method, all we do is set the shape type based on the selected segment of the control. Do you recall the ShapeType enum? The four elements of the enum correspond to the four toolbar segments at the bottom of the application view. We set the shape to be the same as the currently selected segment, and we hide and unhide the colorControl based on whether the Image segment was selected

NOTE: You may have wondered why we put a navigation bar at the top of the view and a toolbar at the bottom of the view. According to the Human Interface Guidelines published by Apple, navigation bars were specifically designed to be placed at the top of the screen and toolbars are

designed for the bottom. If you read the descriptions of the Toolbar and Navigation Bar in

Interface Builder’s library window, you’ll see this design intention spelled out.

Make sure that everything is in order by compiling and running your app. You won’t be able to draw shapes on the screen yet, but the segmented controls should work, and when you tap the Image segment in the bottom control, the color controls should disappear.

Now that we have everything working, let’s do some drawing.

Adding Quartz 2D Drawing Code

We’re ready to add the code that does the drawing. We’ll draw a line, some shapes, and an image. We’re going to work incrementally, adding a small amount of code, and then running the app to see what that code does.

Drawing the Line

Let’s do the simplest drawing option first: drawing a single line. Select BIDQuartzFunView.m, and replace the commented-out drawRect: method with this one:

www.it-ebooks.info

CHAPTER 16: Drawing with Quartz and OpenGL

585

- (void)drawRect:(CGRect)rect {

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetLineWidth(context, 2.0);

CGContextSetStrokeColorWithColor(context, currentColor.CGColor);

switch (shapeType) { case kLineShape:

CGContextMoveToPoint(context, firstTouch.x, firstTouch.y); CGContextAddLineToPoint(context, lastTouch.x, lastTouch.y); CGContextStrokePath(context);

break;

case kRectShape: break;

case kEllipseShape: break;

case kImageShape: break;

default:

break;

}

}

We start things off by retrieving a reference to the current context so we know where to draw.

CGContextRef context = UIGraphicsGetCurrentContext();

Next, we set the line width to 2.0, which means that any line that we stroke will be 2 pixels wide.

CGContextSetLineWidth(context, 2.0);

After that, we set the color for stroking lines. Since UIColor has a CGColor property, which is what this method needs, we use that property of our currentColor property to pass the correct color on to this function.

CGContextSetStrokeColorWithColor(context, currentColor.CGColor);

We use a switch to jump to the appropriate code for each shape type. As we mentioned earlier, we’ll start off with the code to handle kLineShape, get that working, and then we’ll add code for each shape in turn as we make our way through this example.

switch (shapeType) { case kLineShape:

To draw a line, we tell the graphics context to create a path starting at the first place the user touched. Remember that we stored that value in the touchesBegan: method, so it will always reflect the starting point of the most recent touch or drag.

CGContextMoveToPoint(context, firstTouch.x, firstTouch.y);

Next, we draw a line from that spot to the last spot the user touched. If the user’s finger is still in contact with the screen, lastTouch contains Mr. Finger’s current location. If the user is no longer touching the screen, lastTouch contains the location of the user’s finger when it was lifted off the screen.

www.it-ebooks.info

586

CHAPTER 16: Drawing with Quartz and OpenGL

CGContextAddLineToPoint(context, lastTouch.x, lastTouch.y);

Then we stroke the path. This function will stroke the line we just drew using the color and width we set earlier:

CGContextStrokePath(context);

After that, we finish the switch statement.

break;

case kRectShape: break;

case kEllipseShape: break;

case kImageShape: break;

default:

break;

}

And that’s it for now. At this point, you should be able to compile and run the app once more. The Rect, Ellipse, and Shape options won’t work, but you should be able to draw lines just fine using any of the color choices (see Figure 16–11).

Figure 16–11. The line-drawing part of our application is now complete. Here, we are drawing using the color red.

www.it-ebooks.info

CHAPTER 16: Drawing with Quartz and OpenGL

587

Drawing the Rectangle and Ellipse

Let’s write the code to draw the rectangle and the ellipse at the same time, since Quartz implements both of these objects in basically the same way. Add the following bold code to your existing drawRect: method:

- (void)drawRect:(CGRect)rect {

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetLineWidth(context, 2.0);

CGContextSetStrokeColorWithColor(context, currentColor.CGColor);

CGContextSetFillColorWithColor(context, currentColor.CGColor); CGRect currentRect = CGRectMake(firstTouch.x,

firstTouch.y,

lastTouch.x - firstTouch.x, lastTouch.y - firstTouch.y);

switch (shapeType) { case kLineShape:

CGContextMoveToPoint(context, firstTouch.x, firstTouch.y); CGContextAddLineToPoint(context, lastTouch.x, lastTouch.y); CGContextStrokePath(context);

break;

case kRectShape:

CGContextAddRect(context, currentRect); CGContextDrawPath(context, kCGPathFillStroke); break;

case kEllipseShape:

CGContextAddEllipseInRect(context, currentRect); CGContextDrawPath(context, kCGPathFillStroke); break;

case kImageShape: break;

default:

break;

}

}

Because we want to paint both the ellipse and the rectangle in a solid color, we add a call to set the fill color using currentColor.

CGContextSetFillColorWithColor(context, currentColor.CGColor);

Next, we declare a CGRect variable. We do this here because both the rectangle and ellipse are drawn based on a rect. We’ll use currentRect to hold the rectangle described by the user’s drag. Remember that a CGRect has two members: size and origin. A function called CGRectMake() lets us create a CGRect by specifying the x, y, width, and height values, so we use that to make our rectangle.

The code to create the rectangle is pretty straightforward. We use the point stored in firstTouch to create the origin. Then we figure out the size by getting the difference between the two x values and the two y values. Note that depending on the direction of the drag, one or both size values may end up with negative numbers, but that’s OK. A

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]