簡體   English   中英

如何重新創建UITabBarItem圖像過濾器?

[英]How to recreate the UITabBarItem image filter?

我正在編寫一個自定義UITabBar替換,我想知道如何重新創建內置實現使用UITabBarItem圖像的過濾器 - 藍色照射在選定的選項卡上,灰色漸變在未選擇的選項卡上。 我想這是使用源圖像alpha值作為遮罩並用預先制作的藍色(或任何顏色)閃亮圖像覆蓋它而另一個遮住灰色的問題,但我想知道什么是最好的方法來自代碼觀點。

最好,

編輯:稍微修正了藍色濾鏡
Edit2:清理了灰色濾鏡

我需要代碼來做這些效果,所以我為它們寫了幾個函數:

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

要使藍色濾鏡效果起作用,您需要將此圖像作為“selection_gradient.png”包含在項目中: selection_gradient.png
此外,你可能想要使用定義來獲得你喜歡的效果,我沒有花太多時間來完善它們,盡管它們對我來說看起來很好。

當然我不知道Apple應用的確切過濾器,但我“估計”了它們,它們看起來對我來說沒問題。 我不確定這些功能是否與iPhone 4兼容,因為我只在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;
}

編輯:使用@ poiuy_qwert的“selection_gradient.png”

如果您對UITabBarItem過濾器的精確副本感興趣,請嘗試此解決方案。 您不需要在項目中包含任何額外的圖像。

我完全清楚這是一個徹頭徹尾的黑客,我對未來的兼容性沒有任何承諾,但據我所知,它可以在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;
}

同樣,我知道這是一個不穩定的解決方案,但如果你對一個完美的復制品感興趣,那么它就是。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM