简体   繁体   English

如何重新创建UITabBarItem图像过滤器?

[英]How to recreate the UITabBarItem image filter?

I'm writing a custom UITabBar replacement, and I would like to know how to recreate the filter that the built-in implementation does with the UITabBarItem image - that blue shining on selected tabs and gray gradient on unselected ones. 我正在编写一个自定义UITabBar替换,我想知道如何重新创建内置实现使用UITabBarItem图像的过滤器 - 蓝色照射在选定的选项卡上,灰色渐变在未选择的选项卡上。 I guess it's a matter of using the source image alpha value as a mask and overlay it with a pre-made blue (or whatever color) shining image and another one grayed out, but I would like to know what is the best approach from a code point of view. 我想这是使用源图像alpha值作为遮罩并用预先制作的蓝色(或任何颜色)闪亮图像覆盖它而另一个遮住灰色的问题,但我想知道什么是最好的方法来自代码观点。

Best, 最好,

Edit: Fixed up the blue filter a little 编辑:稍微修正了蓝色滤镜
Edit2: Cleaned up the grey filter Edit2:清理了灰色滤镜

I required code to do these effects, so I wrote a couple functions for them: 我需要代码来做这些效果,所以我为它们写了几个函数:

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

To make the blue filter effect work you'll need to include this image in your project as "selection_gradient.png": 要使蓝色滤镜效果起作用,您需要将此图像作为“selection_gradient.png”包含在项目中: selection_gradient.png
Also, you may want to play with the defines to get the effect exactly how you like, I didn't take much time to perfect them, though they look good enough to me. 此外,你可能想要使用定义来获得你喜欢的效果,我没有花太多时间来完善它们,尽管它们对我来说看起来很好。

Of course I don't know the exact filters that Apple applied, but I "guestimated" them and they look alright to me. 当然我不知道Apple应用的确切过滤器,但我“估计”了它们,它们看起来对我来说没问题。 I'm not sure if these functions are iPhone 4 compatible because I'm only using them in an iPad app, but it wouldn't be hard to edit them to your liking. 我不确定这些功能是否与iPhone 4兼容,因为我只在iPad应用程序中使用它们,但根据自己的喜好编辑它们并不困难。

Try this one; 试试这个; it's shorter: 它更短:

+ (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: Use @poiuy_qwert's "selection_gradient.png" 编辑:使用@ poiuy_qwert的“selection_gradient.png”

If you're interested in an exact replica of the UITabBarItem filter, then try this solution. 如果您对UITabBarItem过滤器的精确副本感兴趣,请尝试此解决方案。 You don't need to include any extra images into your project. 您不需要在项目中包含任何额外的图像。

I'm fully aware that this is a total hack and I make no promises as to compatibility in the future, but it works in both iOS 5 and iOS 6 as far as I can tell, and with proper error handling I think it can be useful. 我完全清楚这是一个彻头彻尾的黑客,我对未来的兼容性没有任何承诺,但据我所知,它可以在iOS 5和iOS 6中运行,并且通过适当的错误处理,我认为它可以是有用。 Here it goes: 在这里:

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

Again, I'm aware that this is a shaky solution at best, but if you're interested in a perfect replica, here it is. 同样,我知道这是一个不稳定的解决方案,但如果你对一个完美的复制品感兴趣,那么它就是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM