2009-08-09 11 views
5

J'ai un problème vraiment étrange avec UIImageView. J'ai une image (un png RVB) 45x45 pixels que j'ajoute à la vue. Je peux voir que l'image est floue après avoir ajouté à la vue. Voici la même image dans le simulateur (à gauche) et dans Xcode (à droite):Pourquoi mon UIImageView est-il flou?

alt text http://partywithvika.com/iconinsim.pngalt text http://partywithvika.com/iconinxcode.png

J'ai classe UIImageView personnalisé avec ce code initWithImage:

- (id) initWithImage:(UIImage*) image { 
    self = [super initWithImage:image]; 

    self.frame = CGRectMake(0, 0, 45, 45); 
    self.contentMode = UIViewContentModeScaleAspectFit; 

    self.quantity = 1; 
    if (self) { 
     self.label = [[UITextField alloc]initWithFrame:CGRectMake(0,40,45,25)]; 
     self.label.font = [UIFont systemFontOfSize:16]; 
     self.label.borderStyle = UITextBorderStyleNone; 
     self.label.enabled = TRUE; 
     self.label.userInteractionEnabled = TRUE; 
     self.label.delegate = self; 
     self.label.keyboardType = UIKeyboardTypeNumbersAndPunctuation; 
     self.label.textAlignment = UITextAlignmentCenter; 
    } 
    self.userInteractionEnabled = TRUE; 

    // Prepare 3 buttons: count up, count down, and delete 
    self.deleteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    self.deleteButton.hidden = NO; 
    self.deleteButton.userInteractionEnabled = YES; 
    self.deleteButton.titleLabel.font = [UIFont systemFontOfSize:20]; 
    self.deleteButton.titleLabel.textColor = [UIColor redColor]; 
    [self.deleteButton setTitle:@"X" forState:UIControlStateNormal]; 
    [self.deleteButton addTarget:self action:@selector(deleteIcon:) forControlEvents:UIControlEventTouchUpInside]; 

    self.upCountButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    self.upCountButton.hidden = NO; 
    self.upCountButton.userInteractionEnabled = YES; 
    [self.upCountButton setTitle:@"+" forState:UIControlStateNormal]; 
    [self.upCountButton addTarget:self action:@selector(addQuantity:) forControlEvents:UIControlEventTouchUpInside]; 

    self.downCountButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    self.downCountButton.hidden = YES; 
    self.downCountButton.userInteractionEnabled = YES; 
    [self.downCountButton setTitle:@"-" forState:UIControlStateNormal]; 
    [self.downCountButton addTarget:self action:@selector(removeQuantity:) forControlEvents:UIControlEventTouchUpInside]; 
    return self; 
} 

Je crée comme ça :

UIImage *desertIcon = [UIImage imageNamed:@"desert.png"]; 
IconObj *desertIconView = [[IconObj alloc] initWithImage:desertIcon]; 
desertIconView.center = CGPointMake(265,VERTICAL_POINT_ICON); 
desertIconView.type = [IconObj TYPE_DESERT]; 
[self.view addSubview:desertIconView]; 
[desertIconView release]; 

Pourquoi l'image affichée est-elle identique à celle stockée dans un fichier?

+0

Ceci est probablement sans rapport avec le problème, mais votre méthode init serait plus conventionnel si, après avoir attribué 'self = [super initWithImage: image]', vous vérifiez si le moi est nul, et si c'est le cas, retournez immédiatement à zéro. Si self si jamais nul, c'est soit parce que (1) l'initialiseur du parent ne peut pas s'initialiser correctement, soit (2) alloc retourné nul en raison d'une condition de mémoire étrange (extrêmement rare). C'est une bonne pratique de programmation défensive. –

+0

Merci pour la note, je vais essayer ça. –

Répondre

0

Essayez d'aligner votre vue IconObj sur les pixels de l'écran. Si c'est vraiment 45x45 alors vous devriez mettre le centre à quelque chose comme CGPointMake (x + 0.5f, y + 0.5f).

Vous devez également vérifier la taille de l'image en pixels (par exemple, dans Preview.app Command-I).

+0

Nikolai, je n'ai pas compris ce que tu veux dire par 'x' et 'y' dans ton commentaire. La chose intéressante est que UIImageView est très net s'il est initialisé avec une plus grande image avec le même code. –

+0

Avec x et y, je veux dire des coordonnées entières. Alors que le cadre, les limites et les propriétés du centre des vues utilisent des types basés sur CGFloat pour toutes les coordonnées, il est généralement recommandé d'aligner les vues sur l'écran. –

1

Ce que je fini par faire est de charger plus grande image dans 45x45 UIImageView, bien sûr, avec

contentMode = UIViewContentModeScaleAspectFit; 
+0

Je vous ai dit de vérifier la taille de l'image. –

+0

Nikolai, mon image était 45x45 et le cadre pour le UIImageView était également 45x45. Où voyez-vous une possibilité de mal interpréter cette configuration? –

+1

Avez-vous essayé d'aligner les pixels de l'image sur les pixels de l'écran? –

3

J'ai eu ce problème et il me rend dingue. Après quelques recherches, il s'est avéré que mon image était plus petite que le cadre, et donc la mise à l'échelle l'a brouillé. Une fois que j'ai mis en haute résolution des images le problème est parti.

Assurez-vous que la taille de votre image est supérieure à la taille de votre image UIImageView.

8

En général, tout ce que vous faites sur l'iPhone avec UIKit doit être aligné sur les pixels. Les problèmes d'alignement des pixels se manifestent généralement par du flou (c'est en particulier vrai avec du texte et des images). C'est pourquoi quand je trouve une vue floue, je vérifie d'abord si je règle la propriété center. Lorsque vous définissez center, les valeurs x, y, height et width du cadre sont ajustées autour de ce point central ... ce qui entraîne fréquemment des valeurs fractionnaires.

Vous pouvez essayer d'utiliser CGRectIntegral sur le cadre comme indiqué:

desertIconView.center = CGPointMake(265,VERTICAL_POINT_ICON); 
desertIconView.frame = CGRectIntegral(desertIconView.frame); 

Cela peut fonctionner, mais si elle ne le fait pas, essayez de régler manuellement la frame, sans utiliser center propriété pour faire en sorte que aucune valeur ne fractionnelle .

Editer: Oups! N'a pas remarqué que le PO avait répondu à sa propre question ... Je vais laisser cela pour des raisons informatives de toute façon.

+1

La plupart des autres réponses (en dehors de l'affiche originale) reconnaissent qu'il s'agit d'un problème d'alignement des pixels, mais +1 pour cela, car c'est le but le plus propre et le plus général. Solution – MrCranky

3

Votre IconObj mesure 45 pixels de large. Vous déplacez votre centre IconObj à 265 ce qui fait sa trame à (242.5, VERTICAL_POINT_ICON - 25 * 0.5, 45, 25). L'image sera toujours floue si certains paramètres d'image ne sont pas des entiers.

Solution, calculez le paramètre de cadre vous-même (n'utilisez pas le centre). Et toujours le rendre entier (cast à NSInteger, utilisez ceil, floor ou round).

desertIconView.frame = CGRectMake((NSInteger)(265 - 45*0.5), 
            (NSInteger)(VERTICAL_POINT_ICON - 25*0.5), 
            45, 25); 
1

J'ai juste eu le même problème. D'abord je pensais wtf ai-je besoin de lunettes?Puis j'ai réalisé qu'il n'est tout simplement pas possible de centrer une image (ou une étiquette) lorsque vous lui donnez un nombre impair. Vous devez redimensionner votre image, par exemple. 46 * 46 si vous voulez le centrer et rester précis. Ou vous pouvez le laisser à 45 * 45 mais vous devez décider si vous voulez que votre image soit mal centrée 1 pixel vers la droite, ou 1 pixel vers la gauche. (ou laissez-le flou).

0

source pour le problème offset:

contentImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; 

    UIImage *cImage = [UIImage imageNamed:image]; 
    self.contentImage.image = cImage; 

    [self.contentImage setFrame:CGRectMake(0, 0, cImage.size.width, cImage.size.height)]; 

    CGFloat offset = 0.0f; 

    if (((int)cImage.size.width % 2) && ((int)cImage.size.height % 2)) { 
    offset = 0.5f; 
    } 

    [self.contentImage setCenter:CGPointMake(256.0f + offset, 256.0f + offset)];