2010-09-12 6 views
1

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); 
}  

Répondre

1

Comment, exactement, vous rendant le graphique?

Cela doit être géré automatiquement dans drawRect: (le contexte que vous obtenez devrait déjà être 2x). Cela devrait également être géré automatiquement avec UIGraphicsBeginImageContextWithOptions(size,NO,0); si disponible (si vous avez besoin de revenir à UIGraphicsBeginImageContext(), supposons une échelle de 1). Vous ne devriez pas avoir à vous en préoccuper à moins que vous ne dessiniez vous-même le bitmap.

Vous pouvez essayer quelque chose comme self.contentScaleFactor = [[UIScreen mainScreen] scale], avec les contrôles appropriés d'abord (cela pourrait signifier que si vous l'affichez dans un iPad à 2x, vous obtiendrez des graphiques haute résolution).

Fondamentalement, il n'y a pas beaucoup de différence entre un iPad en mode 2x et un «écran rétine», sauf que l'iPad peut basculer entre 1x et 2x.

Enfin, il y a une faute de frappe: @selector (contentsScaleFactor) a un s supplémentaire.

+0

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

+0

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. –

Questions connexes