2010-09-24 4 views
4

J'écris un remplacement personnalisé UITabBar, et je voudrais savoir comment recréer le filtre que l'implémentation intégrée fait avec l'image UITabBarItem - ce bleu qui brille sur les onglets sélectionnés et le dégradé de gris sur ceux non sélectionnés. Je suppose qu'il s'agit d'utiliser la valeur alpha de l'image source comme un masque et de la superposer avec une image bleue pré-fabriquée (ou de toute autre couleur) et une autre grisée, mais j'aimerais savoir quelle est la meilleure approche d'un point de vue du code.Comment recréer le filtre d'image UITabBarItem?

Best,

+0

vous pouvez simplement utiliser deux images différentes (avec du contenu grisé et surligné) pour chaque onglet et basculer entre elles en cliquant sur le bouton de l'onglet ... (bien sûr cela est valide si vous créez ce remplacement de barre d'onglets personnalisé pour votre application et non comme un composant réutilisable) – lukya

+0

Salut lukya, merci pour vos commentaires. Utiliser deux images pour chaque élément est la solution évidente, mais je veux l'accomplir dans le sens du code pour le rendre réutilisable, comme vous l'avez dit. – boliva

Répondre

11

Edit: Fixe le filtre bleu un peu
Edit2: Nettoyé le filtre gris

I code désiré faire ces effets, donc je l'ai écrit un couple fonctionne pour eux:

UIImage *grayTabBarItemFilter(UIImage *image) { 
    int width = image.size.width, height = image.size.height; 
    UIImage *result = image; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    if (colorSpace == NULL) { 
     return result; 
    } 
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast); 
    if (context == NULL) { 
     CGColorSpaceRelease(colorSpace); 
     return result; 
    } 
    CGFloat colors[8] = {80/255.0,80/255.0,80/255.0,1, 175/255.0,175/255.0,175/255.0,1}; 
    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2); 
    CGContextDrawLinearGradient(context, gradient, CGPointMake(0,-(32-height)/2.0), CGPointMake(0,height+(32-height)/2.0), 0); 
    CGGradientRelease(gradient); 
    CGContextSetBlendMode(context, kCGBlendModeDestinationIn); 
    CGContextDrawImage(context, CGRectMake(0,0,width,height), image.CGImage); 
    CGImageRef newImage = CGBitmapContextCreateImage(context); 
    if (newImage != NULL) { 
     result = [UIImage imageWithCGImage:newImage]; 
     CGImageRelease(newImage); 
    } 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 
    return result; 
} 

struct RGBA { 
    unsigned char red; 
    unsigned char green; 
    unsigned char blue; 
    unsigned char alpha; 
}; 

#define BLUE_ALPHA_THRESHOLD 128 
#define BLUE_BRIGHTNESS_ADJUST 30 

UIImage *blueTabBarItemFilter(UIImage *image) { 
    int width = image.size.width, 
     height = image.size.height; 
    UIImage *result = image; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    if (colorSpace == NULL) { 
     return result; 
    } 
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast); 
    if (context == NULL) { 
     CGColorSpaceRelease(colorSpace); 
     return result; 
    } 
    UIImage *gradient = [UIImage imageNamed:@"selection_gradient.png"]; 
    CGContextDrawImage(context, CGRectMake(-(gradient.size.width - width)/2.0, -(gradient.size.height - height)/2.0, gradient.size.width, gradient.size.height), gradient.CGImage); 
    CGContextSetBlendMode(context, kCGBlendModeDestinationIn); 
    CGContextDrawImage(context, CGRectMake(0,0,width,height), image.CGImage); 
    struct RGBA *pixels = CGBitmapContextGetData(context); 
    if (pixels != NULL) { 
     for (int y = 0; y < height; y++) { 
      for (int x = 0; x < width; x++) { 
       int offset = x+y*width; 
       if (pixels[offset].alpha >= BLUE_ALPHA_THRESHOLD && 
        ((x == 0 || x == width-1 || y == 0 || y == height-1) || 
        (pixels[x+(y-1)*width].alpha < BLUE_ALPHA_THRESHOLD) || 
        (pixels[x+1+y*width].alpha < BLUE_ALPHA_THRESHOLD) || 
        (pixels[x+(y+1)*width].alpha < BLUE_ALPHA_THRESHOLD) || 
        (pixels[x-1+y*width].alpha < BLUE_ALPHA_THRESHOLD))) { 
        pixels[offset].red = MIN(pixels[offset].red + BLUE_BRIGHTNESS_ADJUST,255); 
        pixels[offset].green = MIN(pixels[offset].green + BLUE_BRIGHTNESS_ADJUST,255); 
        pixels[offset].blue = MIN(pixels[offset].blue + BLUE_BRIGHTNESS_ADJUST,255); 
       } 
      } 
     } 
     CGImageRef image = CGBitmapContextCreateImage(context); 
     if (image != NULL) { 
      result = [UIImage imageWithCGImage:image]; 
      CGImageRelease(image); 
     } 
    } 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 
    return result; 
} 

pour faire fonctionner l'effet de filtre bleu vous aurez besoin d'inclure cette image dans votre projet « selection_gradient.png »: selection_gradient.png http://oi55.tinypic.com/bgwv0j.jpg
Aussi, vous voudrez peut-être jouer avec les définitions pour obtenir exactement l'effet que vous voulez, je n'ai pas pris beaucoup de temps pour les perfectionner, même si elles me semblent assez bonnes.

Bien sûr, je ne connais pas les filtres exacts qu'Apple a appliqués, mais je les ai "mesurés" et ils me paraissent bien. Je ne suis pas sûr si ces fonctions sont compatibles avec l'iPhone 4 parce que je ne les utilise que dans une application iPad, mais il ne serait pas difficile de les modifier à votre goût.

+0

J'ai de la difficulté à faire fonctionner ce filtre sur les appareils de la rétine. Est-ce que quelqu'un a eu du succès à faire ça? J'ai essayé CGContextScaleCTM() mais cela rend l'image deux fois plus grande. –

+0

Vous devriez juste avoir à changer 'result = [UIImage imageWithCGImage: newImage],' à 'result = [UIImage imageWithCGImage: échelle newImage: [UIScreen mainScreen] Orientation .scale: UIImageOrientationUp];' –

+0

En fait, je compris une façon exactement répliquer le filtre UITabBarItem. C'est un peu un hack, mais c'est une copie parfaite. Je posterai ma solution dans un instant. –

1

Essayez celui-ci; il est plus court:

+ (UIImage *)blendImageBlue:(UIImage *)senderImage { 
     UIImage *image = [UIImage imageNamed:@"selection_gradient"]; 

     CGSize newSize = CGSizeMake(senderImage.size.width, senderImage.size.height); 
     UIGraphicsBeginImageContextWithOptions(newSize, NO, [UIScreen mainScreen].scale); 

     [senderImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 
     [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeSourceAtop alpha:0.8]; 

     UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 

     UIGraphicsEndImageContext(); 

     return newImage; 
} 

Edit: Utilisez @ "le selection_gradient.png" de poiuy_qwert

+0

N'avez pas testé votre code, mais d'après ce que je peux dire cela n'éclaircit pas les bords de l'icône? –

0

Si vous êtes intéressé par une réplique exacte du filtre UITabBarItem, essayez cette solution. Vous n'avez pas besoin d'inclure d'images supplémentaires dans votre projet. Je suis pleinement conscient que c'est un hack total et je ne fais aucune promesse quant à la compatibilité à l'avenir, mais cela fonctionne à la fois dans iOS 5 et iOS 6 autant que je sache, et avec une bonne gestion des erreurs, je pense que ça peut être utile. Ici, il va:

UIImage *grayTabBarItemFilter(UIImage *image) { 
    UITabBar* bar = [[UITabBar alloc] init]; 
    UITabBarItem* item = [[UITabBarItem alloc] initWithTitle:@"" image:image tag:0]; 
    [bar setItems:@[item]]; 
    [[[[UIApplication sharedApplication] windows] lastObject] addSubview:bar]; 
    UIImage* returnImage; 
    for(UIView* view in bar.subviews) { 
     for(UIView* small in view.subviews) { 
      if([small respondsToSelector:@selector(image)]) { 
       returnImage = [(UIImageView*)small image]; 
      } 
     } 
    } 

    [bar removeFromSuperview]; 

    return returnImage ? returnImage : image; 
} 

UIImage *blueTabBarItemFilter(UIImage *image) { 
    UITabBar* bar = [[UITabBar alloc] init]; 
    UITabBarItem* item = [[UITabBarItem alloc] initWithTitle:@"" image:image tag:0]; 
    [bar setItems:@[item]]; 
    [bar setSelectedItem:item]; 
    [[[[UIApplication sharedApplication] windows] lastObject] addSubview:bar]; 
    UIImage* returnImage; 
    for(UIView* view in bar.subviews) { 
     NSInteger count = 0; 
     for(UIView* small in view.subviews) { 
      if([small respondsToSelector:@selector(image)]) { 
       count++; 
       if(count > 1) { 
        returnImage = [(UIImageView*)small image]; 
       } 
      } 
     } 
    } 

    [bar removeFromSuperview]; 

    return returnImage ? returnImage : image; 
} 

Encore une fois, je suis conscient que cela est une solution fragile au mieux, mais si vous êtes intéressé par une réplique parfaite, il est ici.

Questions connexes