iOS-кварцевый рисунок проблема с родительскими / дочерними представлениями


Сценарий

У меня есть два мнения. Один из них-это "родительский" вид, который содержит "дочерний" вид, выполняющий чертеж. Я ссылаюсь на ребенка, как QuartzView в код, чтобы следовать. QuartzView знает, как нарисовать квадрат в его собственном контексте.

Выпуск

Когда я говорю QuartzView, что это self нарисовать квадрат, он делает это, как и ожидалось. Когда я использую Родительский вид, чтобы сказать QuartsView нарисовать квадрат на нем self, он рисует квадрат в левом нижнем углу экрана примерно на 1/5 от ожидаемого размера.

Вопрос

Я предполагаю, что здесь есть некоторые проблемы родителя/ребенка или контекста, но я не уверен, что они есть. Как я могу заставить оба квадрата рисовать в одном и том же месте с одинаковым размером?

Родитель 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]];

}

Ребенок 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);
}

Примечание

  • непрозрачности одинаковы для обоих квадратов
  • я выключил "подпанелей автоматического изменения размеров" без заметного разница
  • view.contentScaleFactor = [[UIScreen mainScreen] scale]; не помогло

Edit

Я замечаю, что значения x/y квадрата при рисовании родителя начинаются с нижнего левого угла как 0,0, тогда как обычно 0,0 будет верхним левым.

2 2

2 ответа:

Возвращаемое значение из UIGraphicsGetCurrentContext() допустимо только внутри метода drawRect. Вы не можете и не должны использовать этот контекст в любом другом методе. Таким образом, свойство self.context должно быть просто локальной переменной.

В методе drawRectWithCenter следует сохранить все параметры в свойствах, а затем запросить обновление представления с помощью [self setNeedsDisplay]. Таким образом, фреймворк вызовет drawRect с новой информацией. Метод drawRectWithCenter должен выглядеть примерно так

- (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];
}

И, конечно, функция drawRect должна возьмите эту информацию и сделайте соответствующий рисунок.

Я предполагаю, что здесь есть некоторые проблемы родителя/ребенка или контекста, но я не уверен, что они есть. Как я могу заставить оба квадрата рисовать в одном и том же месте с одинаковым размером?
Обычно вам не нужно беспокоиться о графическом контексте в вашем методе -drawRect:, потому что Cocoa Touch настроит контекст для вас перед вызовом -drawRect:. Но ваш метод -drawASquare в контроллере вида вызывает -drawRectWithCenter:... для рисования вне обычного процесса рисования, поэтому контекст не настроен для ваш взгляд. Вы действительно должны иметь вид сделать его рисунок в -drawRect:. Если ваш контроллер вида хочет сделать вид перерисованным, он должен вызвать -setNeedsDisplay, например:
[qv setNeedsDisplay];

Это добавит вид в список чертежей, а графическая система настроит графический контекст и вызовет вид -drawRect: для вас.

Я замечаю, что значения x/y квадрата при рисовании родителя начинаются снизу слева как 0,0, тогда как обычно 0,0 было бы верхним левый.

UIKit и Core Animation используют верхний левый источник, но Core Graphics (a.k.A. Quartz) обычно использует нижний левый источник. В документах говорится:

система координат по умолчанию, используемая Core Graphics framework, основана на LLO.