Я изо всех сил пытаюсь заставить мой собственный код рисования отображаться в надлежащем масштабе для всех устройств iOS, то есть для старых iPhone, тех, которые имеют дисплеи Retina и iPad.
У меня есть подкласс UIView
, в котором есть собственный класс, отображающий векторную графику. У него есть свойство scale
, которое я могу установить. Я делаю масштабирование в initWithCoder
, когда загружается UIView
, и я сначала создаю экземпляр векторной графики. Это UIView
отображается, когда пользователь нажимает кнопку на главном экране.
Сначала я попробовал это:
screenScaleFactor = 1.0;
if ([UIScreen instancesRespondToSelector:@selector(scale)]) {
screenScaleFactor = [[UIScreen mainScreen] scale];
}
// and then I multiply stuff by screenScale
... который работал для перехода между обычными айфонами и айфонами с сетчаткой, но давился на iPad. Как я уже сказал, вы можете перейти к UIView
, нажав кнопку на главном экране. При запуске на iPad, если вы отображаете UIView
в 1X, он работает, но в 2X я получаю векторную графику, которая в два раза больше, чем должна быть.
Так что я попробовал это вместо:
ОБНОВЛЕНИЕ: Это тот блок, который является правильным. (с исправленной орфографией, конечно!)
screenScaleFactor = 1.0;
if ([self respondsToSelector:@selector(contentScaleFactor)]) { //EDIT: corrected misspellng.
screenScaleFactor = (float)self.contentScaleFactor;
}
// again multiplying stuff by screenScale
, который работает как в 1, так и в 2 раза на iPad и на старых iPhone, но на сетчатке дисплея векторная графика вдвое меньше, чем должна быть.
В первом случае я запрашиваю UIScreen
его свойство scale
, а во втором случае я запрашиваю у родительского элемента view
векторной графики его contentsScaleFactor
. Похоже, что ни один из них не позволяет мне достичь желаемого результата во всех случаях.
Есть предложения?
UPDATE:
Вот метод в моем подклассе UIView
(он называется GaugeView):
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGAffineTransform t0 = CGContextGetCTM(context);
t0 = CGAffineTransformInvert(t0);
CGContextConcatCTM(context, t0);
[needle updateBox];
[needle draw: context];
}
needle
относится к классу VectorSprite
, который является подклассом Sprite
, который является подклассом из NSObject
. Это из книги по программированию, через которую я работаю. needle
имеет свойство масштаба, которое я установил.
updateBox
происходит от Sprite
и выглядит так:
- (void) updateBox {
CGFloat w = width*scale;
CGFloat h = height*scale;
CGFloat w2 = w*0.5;
CGFloat h2 = h*0.5;
CGPoint origin = box.origin;
CGSize bsize = box.size;
CGFloat left = -kScreenHeight*0.5;
CGFloat right = -left;
CGFloat top = kScreenWidth*0.5;
CGFloat bottom = -top;
offScreen = NO;
if (wrap) {
if ((x+w2) < left) x = right + w2;
else if ((x-w2) > right) x = left - w2;
else if ((y+h2) < bottom) y = top + h2;
else if ((y-h2) > top) y = bottom - h2;
}
else {
offScreen =
((x+w2) < left) ||
((x-w2) > right) ||
((y+h2) < bottom) ||
((y-h2) > top);
}
origin.x = x-w2*scale;
origin.y = y-h2*scale;
bsize.width = w;
bsize.height = h;
box.origin = origin;
box.size = bsize;
}
Sprite
также имеет методы draw
и drawBody
:
- (void) draw: (CGContextRef) context {
CGContextSaveGState(context);
// Position the sprite
CGAffineTransform t = CGAffineTransformIdentity;
t = CGAffineTransformTranslate(t,x,y);
t = CGAffineTransformRotate(t,rotation);
t = CGAffineTransformScale(t,scale,scale);
CGContextConcatCTM(context, t);
// draw sprite body
[self drawBody: context];
CGContextRestoreGState(context);
}
- (void) drawBody: (CGContextRef) context {
// Draw your sprite here, centered
// on (x,y)
// As an example, we draw a filled white circle
if (alpha < 0.05) return;
CGContextBeginPath(context);
CGContextSetRGBFillColor(context, r,g,b,alpha);
CGContextAddEllipseInRect(context, CGRectMake(-width/2,-height/2,width,height));
CGContextClosePath(context);
CGContextDrawPath(context,kCGPathFill);
}