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

Iphone 如何重新创建UItabaritem图像过滤器?,iphone,cocoa-touch,uikit,uitabbar,Iphone,Cocoa Touch,Uikit,Uitabbar,我正在编写一个自定义的UITabBar替换,我想知道如何重新创建内置实现对UITabBarItem图像所做的过滤器——选中的选项卡上显示蓝色,未选中的选项卡上显示灰色渐变。我想这是一个使用源图像alpha值作为遮罩的问题,并用预先制作的蓝色(或任何颜色)发光图像和另一个灰色图像覆盖它,但我想知道从代码的角度来看什么是最好的方法 最佳,编辑:稍微修正了蓝色过滤器 编辑2:清理灰色过滤器 我需要代码来实现这些效果,所以我为它们编写了两个函数: UIImage *grayTabBarItemFilte

我正在编写一个自定义的UITabBar替换,我想知道如何重新创建内置实现对UITabBarItem图像所做的过滤器——选中的选项卡上显示蓝色,未选中的选项卡上显示灰色渐变。我想这是一个使用源图像alpha值作为遮罩的问题,并用预先制作的蓝色(或任何颜色)发光图像和另一个灰色图像覆盖它,但我想知道从代码的角度来看什么是最好的方法


最佳,

编辑:稍微修正了蓝色过滤器
编辑2:清理灰色过滤器

我需要代码来实现这些效果,所以我为它们编写了两个函数:

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;
}
UIImage*graytabaritemfilter(UIImage*image){
int width=image.size.width,height=image.size.height;
UIImage*结果=图像;
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
if(colorSpace==NULL){
返回结果;
}
CGContextRef context=CGBitmapContextCreate(NULL,宽度,高度,8,宽度*4,颜色空间,KCGIMAGEAlphaPremultipledLast);
if(上下文==NULL){
CGCOLORSPACTERELEASE(色彩空间);
返回结果;
}
CGFloat colors[8]={80/255.0,80/255.0,80/255.0,1,175/255.0175/255.0175/255.0,1};
CGGradientRef gradient=CGGradientCreateWithColorComponents(颜色空间,颜色,NULL,2);
CGContextDrawLinearGradient(上下文、渐变、CGPointMake(0,-(32高度)/2.0)、CGPointMake(0,高度+(32高度)/2.0)、0);
CGGradientRelease(梯度);
CGContextSetBlendMode(上下文,kCGBlendModeDestinationIn);
CGContextDrawImage(上下文,CGRectMake(0,0,宽度,高度),image.CGImage);
CGImageRef newImage=CGBitmapContextCreateImage(上下文);
if(newImage!=NULL){
结果=[UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
}
CGContextRelease(上下文);
CGCOLORSPACTERELEASE(色彩空间);
返回结果;
}
结构RGBA{
无符号字符红色;
无符号字符绿色;
无符号字符蓝色;
无符号字符α;
};
#定义蓝色α阈值128
#定义蓝色\u亮度\u调整30
UIImage*blueTabBarItemFilter(UIImage*image){
int width=image.size.width,
高度=image.size.height;
UIImage*结果=图像;
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
if(colorSpace==NULL){
返回结果;
}
CGContextRef context=CGBitmapContextCreate(NULL,宽度,高度,8,宽度*4,颜色空间,KCGIMAGEAlphaPremultipledLast);
if(上下文==NULL){
CGCOLORSPACTERELEASE(色彩空间);
返回结果;
}
UIImage*gradient=[UIImage ImageName:@“selection_gradient.png”];
CGContextDrawImage(上下文,CGRectMake(-(gradient.size.width-width)/2.0,-(gradient.size.height-height)/2.0,gradient.size.width,gradient.size.height),gradient.CGImage);
CGContextSetBlendMode(上下文,kCGBlendModeDestinationIn);
CGContextDrawImage(上下文,CGRectMake(0,0,宽度,高度),image.CGImage);
struct RGBA*pixels=CGBitmapContextGetData(上下文);
如果(像素!=NULL){
对于(int y=0;y=BLUE\u alpha\u阈值&&
((x==0 | | x==width-1 | | y==0 | | y==height-1)||
(像素[x+(y-1)*宽度].alpha<蓝色alpha\u阈值)||
(像素[x+1+y*宽度]。alpha<蓝色\u alpha\u阈值)||
(像素[x+(y+1)*宽度].alpha<蓝色\u alpha\u阈值)||
(像素[x-1+y*宽度].alpha<蓝色\u alpha\u阈值){
像素[offset].red=MIN(像素[offset].red+BLUE\u亮度调整,255);
像素[offset].green=MIN(像素[offset].green+BLUE\u亮度调整,255);
像素[offset].blue=MIN(像素[offset].blue+blue\u亮度调整,255);
}
}
}
CGImageRef image=CGBitmapContextCreateImage(上下文);
如果(图像!=NULL){
结果=[UIImage imageWithCGImage:image];
CGImageRelease(图像);
}
}
CGContextRelease(上下文);
CGCOLORSPACTERELEASE(色彩空间);
返回结果;
}
要使蓝色滤镜效果生效,您需要将此图像作为“selection_gradient.png”包含在项目中:
另外,你可能想玩defines来获得你喜欢的效果,我没有花太多时间来完善它们,尽管它们在我看来已经足够好了


当然,我不知道苹果应用了什么样的过滤器,但我对它们进行了“客串估计”,它们看起来还不错。我不确定这些功能是否与iphone4兼容,因为我只在iPad应用程序中使用它们,但根据您的喜好编辑它们并不难;它比较短:

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

编辑:使用@pouy_qwert的“selection_gradient.png”

如果您对Uitabritem过滤器的精确副本感兴趣,请尝试此解决方案。您不需要在项目中包含任何额外的图像

我完全知道这是一个彻底的黑客行为,我对未来的兼容性没有做出任何承诺,但据我所知,它在iOS 5和iOS 6中都能工作,并且通过正确的错误处理,我认为它是有用的。下面是:

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

同样,我知道这充其量是一个不可靠的解决方案,但如果您对完美的复制品感兴趣,请看这里。

您可以简单地为每个选项卡使用两个不同的图像(带有灰显和高亮显示的内容),然后单击选项卡按钮在它们之间切换。。。(当然,如果您只是为您的应用程序而不是作为可重用组件创建此自定义选项卡栏替换,则此选项有效)嗨,lukya,谢谢您的反馈。为每个项目使用两个图像是显而易见的解决方案,但我想以代码方式实现它,使其可重用,正如您所说的