Je me bats pour que mon code de dessin personnalisé soit rendu à la bonne échelle pour tous les appareils iOS, c'est-à-dire les anciens iPhones, ceux avec écran rétine et l'iPad.Mise à l'échelle du code de dessin personnalisé pour différentes résolutions iOS
J'ai une sous-classe de UIView
qui a une classe personnalisée qui affiche un graphique vectoriel. Il a une propriété scale
que je peux définir. Je fais la mise à l'échelle dans initWithCoder
lorsque les charges UIView
et je instancie d'abord le graphique vectoriel. Ce UIView
est affiché lorsque l'utilisateur appuie sur un bouton de l'écran d'accueil.
Au début, j'essayé ceci:
screenScaleFactor = 1.0;
if ([UIScreen instancesRespondToSelector:@selector(scale)]) {
screenScaleFactor = [[UIScreen mainScreen] scale];
}
// and then I multiply stuff by screenScale
... qui a travaillé pour aller entre iPhones normaux et iPhones rétine, mais selfs sur l'iPad. Comme je l'ai dit, vous pouvez accéder au UIView
en question en appuyant sur un bouton sur l'écran d'accueil. Lorsque vous utilisez l'iPad, si vous affichez le UIView
à 1X, cela fonctionne, mais à 2X, j'obtiens un graphique vectoriel deux fois plus grand qu'il devrait l'être.
donc j'ai essayé ceci:
MISE À JOUR: Ce bloc est celui qui est juste. (Avec l'orthographe corrigée, bien sûr!)
screenScaleFactor = 1.0;
if ([self respondsToSelector:@selector(contentScaleFactor)]) { //EDIT: corrected misspellng.
screenScaleFactor = (float)self.contentScaleFactor;
}
// again multiplying stuff by screenScale
qui fonctionne à la fois 1X et 2X sur l'iPad et sur les anciens iPhones, mais sur un écran de la rétine, le graphique vectoriel est la moitié de la taille, il devrait être.
Dans le premier cas, je la requête UIScreen
pour sa scale
propriété et dans le second cas, je demande au parent view
du graphique vectoriel pour son contentsScaleFactor
. Aucun d'entre eux ne semble me trouver où je veux pour tous les cas.
Des suggestions?
MISE À JOUR:
est ici la méthode dans mon sous-classé UIView
(il est appelé 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
est de classe VectorSprite
qui est une sous-classe de Sprite
qui est sous-classé de NSObject
. Ceux-ci proviennent d'un livre de programmation que je suis en train de travailler. needle
a la propriété d'échelle que j'ai définie.
updateBox
vient de Sprite
et ressemble à ceci:
- (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
a aussi les draw
et drawBody
méthodes qui sont:
- (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);
}
Donc, après avoir ajouté tout le code ci-dessus, j'ai également corrigé la faute d'orthographe de 'contentScaleFactor'. Cette version semble fonctionner maintenant avec tout le matériel! Je pense que parce que je l'ai mal orthographié dans la méthode 'respondsToSelector: @selector()', il n'a tout simplement pas répondu à ce sélecteur, car ce n'est pas un sélecteur. Mais Xcode ne vous dit pas qu'un sélecteur n'existe pas, juste que l'objet message ne répond pas. Sournois. Merci d'avoir répondu! – Steve
GCC * peut * vous indiquer qu'un sélecteur n'a pas été défini avant utilisation, mais vous devez activer l'avertissement avec '-Wundeclared-selector'. Recherchez-le dans les paramètres de construction. S'il y a un tickybox correspondant, utilisez-le, sinon ajoutez-le à "flags supplémentaires" ou quoi que ce soit. –