简体   繁体   中英

iOS - Quartz drawing issue with parent/child views

Scenario

I have two views. One is the "parent" view which contains a "child" view that does the drawing. I refer to the child as QuartzView in the code to follow. QuartzView knows how to draw a square to it's own context.

Issue

When I tell the QuartzView on it's self to draw a square it does so as expected. When I use the parent view to tell QuartsView to draw a square on it's self it draws the square in the lower left corner of the screen at about 1/5 the expected size.

Question

I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?

Parent ViewController

- (void)drawASquare {

    // this code draws the "goofy" square that is smaller and off in the bottom left corner
    x = qv.frame.size.width / 2;
    y = qv.frame.size.height / 2;
    CGPoint center = CGPointMake(x, y);
    [qv drawRectWithCenter:center andWidth:50 andHeight:50 andFillColor:[UIColor blueColor]];

}

Child QuartzView

- (void)drawRect:(CGRect)rect
{
    self.context = UIGraphicsGetCurrentContext();
    UIColor *color = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5];

    // this code draws a square as expected
    float w = self.frame.size.width / 2;
    float h = self.frame.size.height / 2;
    color = [UIColor blueColor];
    CGPoint center = CGPointMake(w, h);
    [self drawRectWithCenter:center andWidth:20 andHeight:20 andFillColor:color];
}

- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
    CGContextSetFillColorWithColor(self.context, color.CGColor);
    CGContextSetRGBStrokeColor(self.context, 0.0, 1.0, 0.0, 1);

    CGRect rectangle = CGRectMake(center.x - w / 2, center.x - w / 2, w, h);

    CGContextFillRect(self.context, rectangle);
    CGContextStrokeRect(self.context, rectangle);
}

Note

  • The opacities are the same for both squares
  • I turned off "Autoresize subviews" with no noticeable difference
  • view.contentScaleFactor = [[UIScreen mainScreen] scale]; has not helped

Edit

I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.

I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?

You normally don't need to worry about the graphics context in your -drawRect: method because Cocoa Touch will set up the context for you before calling -drawRect: . But your -drawASquare method in the view controller calls -drawRectWithCenter:... to draw outside the normal drawing process, so the context isn't set up for your view. You should really have the view do its drawing in -drawRect: . If your view controller wants to make the view redraw, it should call -setNeedsDisplay , like:

[qv setNeedsDisplay];

That will add the view to the drawing list, and the graphics system will set up the graphics context and call the view's -drawRect: for you.

I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.

UIKit and Core Animation use an upper left origin, but Core Graphics (aka Quartz) normally uses a lower left origin. The docs say:

The default coordinate system used by Core Graphics framework is LLO-based.

The return value from UIGraphicsGetCurrentContext() is only valid inside the drawRect method. You can not and must not use that context in any other method. So the self.context property should just be a local variable.

In the drawRectWithCenter method, you should store all of the parameters in properties, and then request a view update with [self setNeedsDisplay] . That way, the framework will call drawRect with the new information. The drawRectWithCenter method should look something like this

- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
    self.showCenter = center;
    self.showWidth = w;
    self.showHeight = h;
    self.showFillColor = color;
    [self setNeedsDisplay];
}

And of course, the drawRect function needs to take that information, and do the appropriate drawing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM