How can I replicate UINavigationBar's gradient colors?

后端 未结 4 1833
太阳男子
太阳男子 2021-02-06 13:13

I\'ve been trying to replicate the gradient from UINavigationBar to use as a gradient on custom UIButton subclass objects on the same view.

How

4条回答
  •  遥遥无期
    2021-02-06 14:09

    Thanks for the good question and the generous bounty. I went to work on this and neglected to check in to see that it was already answered acceptably. Nevertheless, it was fun building and testing the following navigation bar category, that reveals it's colors ...

    //
    //  UINavigationBar+colors.h
    
    #import 
    
    @interface UINavigationBar (Colors)
    
    // Answer an array of colors representing the color of the reciever, starting at fromY, up to toY
    - (NSArray *)colorsFromY:(NSUInteger)fromY to:(NSUInteger)toY;
    
    @end
    

    Link with QuartzCore.framework.

    //
    //  UINavigationBar+colors.m
    
    #import "UINavigationBar+colors.h"
    #import 
    
    #define UIIMAGE_BYTES_PER_PIXEL 4u
    
    @implementation UINavigationBar (Colors)
    
    + (NSData *)dataFromImage:(UIImage *)image {
    
        CGImageRef imageRef = [image CGImage];
        NSUInteger width = CGImageGetWidth(imageRef);
        NSUInteger height = CGImageGetHeight(imageRef);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        NSUInteger dataSize = height * width * UIIMAGE_BYTES_PER_PIXEL;
        unsigned char *rawData = malloc(dataSize);
        NSUInteger bytesPerRow = width * UIIMAGE_BYTES_PER_PIXEL;
        NSUInteger bitsPerComponent = 8;
        CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                     bitsPerComponent, bytesPerRow, colorSpace,
                                                     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
        CGColorSpaceRelease(colorSpace);
    
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
        CGContextRelease(context);
    
        NSData *rtn = [NSData dataWithBytes:rawData length:dataSize];
        free(rawData);
        return rtn;
    }
    
    
    + (UIColor *)colorOfImage:(UIImage *)image atX:(NSUInteger)px atY:(NSUInteger)py  {
    
        NSData *imgData = [self dataFromImage:image];
        if (!imgData) return nil;
    
        NSUInteger byteIndex = UIIMAGE_BYTES_PER_PIXEL * (image.size.width * py + px);
    
        unsigned char rgbaData[4];
        NSRange range = { byteIndex, 4u };
        [imgData getBytes:rgbaData range:range];
        CGFloat red   = rgbaData[0] / 255.0;
        CGFloat green = rgbaData[1] / 255.0;
        CGFloat blue  = rgbaData[2] / 255.0;
        CGFloat alpha = rgbaData[3] / 255.0;
    
        return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    }
    
    - (UIImage *)asImage {
    
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0.0);
        [self.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return img;
    }
    
    - (NSArray *)colorsFromY:(NSUInteger)fromY to:(NSUInteger)toY {
    
        NSMutableArray *answer = [NSMutableArray array];
        UIImage *image = [self asImage];
    
        for (NSUInteger y = MAX(0, fromY); y < MIN(self.bounds.size.height, toY); y++) {
            [answer addObject:[self.class colorOfImage:image atX:1 atY:y]];
        }
        return [NSArray arrayWithArray:answer];
    }
    
    @end
    

    Call it like this:

    // from a view controller contained by a navigation controller...
    UINavigationBar *bar = self.navigationController.navigationBar;
    
    NSArray *colors = [bar colorsFromY:0 to:bar.bounds.size.height];
    for (UIColor *color in colors) {
        NSLog(@"%@", color);
    }
    

提交回复
热议问题