很多时候,当你需要设计更高级的UI或者是减少设计师的工作量的时候,我们就需要用代码自行绘制UI,而自行绘制UI就需要用到CoreGraphics这个框架(OpenGL更高阶,目前还没达到这个水准)。

  CGContext类,相当于Android里面的Canvas,使用UIGraphicsGetCurrentContext()获取当前CGContext的引用CGContextRef。我们在每一次的绘制之前都应该保存下原来的状态,待绘制完成后再恢复回原来的状态。所以CGContextSaveGState(ctx);… CGContextRestoreGState(ctx);都应该成对的出现,在他们之间的是绘制UI的代码。

  CGPath类用于描述绘制的区域或者路线。在CGContext中addLine,addRect,其实都是在添加path,在添加完成path以后我们可以选择是fill该path,还是stroke该path。设置相应的颜色以及线宽即可。如果我们只需要在某个区域中绘制,我们可以在描述完path以后使用CGContextClip(ctx)来裁剪当前画布。

  CGAffineTransform是一个仿射变换的结构体,相当于一个矩阵,用于进行二维平面的几何变换(平移,旋转,缩放),而且这些几何变换都已经有封装好的函数可调用,变换的顺序就是矩阵连乘的顺序,切不可把矩阵连乘的顺序放反,否则得到的结果可能不一样

  CGColorSpace类是用于界面颜色显示,通常颜色组成为RGBA(红,绿,蓝,透明度)四种,使用CGColorSpaceCreateDeviceRGB获取CGColorSpace的引用CGColorSpaceRef,需要注意的是,在CoreGraphics中,使用create方法生成的引用,最后都需要调用release方法释放掉,如CGColorSpaceCreateDeviceRGB()对应的就是CGColorSpaceRelease(rgb)。

ios coredata卡顿 ios coregraphic_ios coredata卡顿

ios coredata卡顿 ios coregraphic_ci_02

展开代码

#define UIColorFromHex(hexValue) [UIColor \
colorWithRed:((float)((hexValue & 0xFF0000) >> 16))/255.0 \
green:((float)((hexValue & 0xFF00) >> 8))/255.0 \
blue:((float)(hexValue & 0xFF))/255.0 alpha:1.0]

[UIImage imageWithGradientBeginColor:UIColorFromHex(0x626262) middleColor:UIColorFromHex(0x515151) endColor:UIColorFromHex(0x424242) size:CGSizeMake(320.0f, 44.0f)];

 

ios coredata卡顿 ios coregraphic_ios coredata卡顿

ios coredata卡顿 ios coregraphic_ci_02

展开代码

+ (UIImage *)imageWithGradientBeginColor:(UIColor *)beginColor middleColor:(UIColor *)middleColor endColor:(UIColor *)endColor size:(CGSize)size
{
    UIColor *colors[] = {beginColor, middleColor, endColor};
    UIGraphicsBeginImageContext(size);
    [[UIColor clearColor] setFill];
 
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    size_t numberOfComponents = CGColorGetNumberOfComponents(UIColorFromHex(0x111111).CGColor);
    int numberOfColors = sizeof(colors)/sizeof(colors[0]);
    CGFloat colorComponents[numberOfColors*numberOfComponents];
    for (int i=0; i<numberOfColors; i++) {
        UIColor *color = colors[i];
        const CGFloat *components = CGColorGetComponents(color.CGColor);
        for (int j=0; j<numberOfComponents; j++) {
            colorComponents[i*numberOfComponents+j] = components[j];
        }
    }
    CGFloat locations[] = {0.0f, 0.5f, 1.0f};
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colorComponents, locations, sizeof(locations)/sizeof(locations[0]));
 
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);
    CGContextAddRect(ctx, CGRectMake(0.0f, 0.0f, size.width, size.height));
    CGContextClip(ctx);
    CGContextDrawLinearGradient(ctx, gradient, CGPointMake(size.width/2.0, 0.0f), CGPointMake(size.width/2.0, size.height), kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation);
    CGColorSpaceRelease(rgb);
    CGGradientRelease(gradient);
 
 
 
    CGAffineTransform myTextTransform;
    CGContextSelectFont (ctx,
                         "Helvetica-Bold",
                         20.0,
                         kCGEncodingMacRoman);
    CGContextSetCharacterSpacing (ctx, 2.0);
    CGContextSetTextDrawingMode (ctx, kCGTextFill);
 
    CGContextSetRGBFillColor(ctx, .8, .8, .8, .8);
//    CGContextSetRGBStrokeColor (ctx, 0, 0, 1, 1);
    myTextTransform = CGAffineTransformMakeScale(1.0, -1.0f);
 
    CGContextConcatCTM(ctx, CGAffineTransformMakeTranslation(140.0f, 30.0f));
    CGContextSetTextMatrix (ctx, myTextTransform);//  CGContextConcatCTM(ctx, CGAffineTransformConcat(myTextTransform, CGAffineTransformMakeTranslation(140.0f, 30.0f)));
    CGContextShowTextAtPoint(ctx, 0.0f, 0.0f, "Title", 5);
 
 
    CGContextRestoreGState(ctx);
 
    UIImage *anImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
//    NSLog(@"%@", kCachePath);
//    [UIImagePNGRepresentation(anImage) writeToFile:[kCachePath stringByAppendingPathComponent:@"linearGradient.png"] atomically:YES];
    return anImage;
}

以上代码为生成如上图片所需的代码,在用CoreGraphics绘制时,我们应该注意的是使用CGContextShowTextAtPoint绘制文字时,如果不进行几何变换,得到的是文字的倒影,所以我们需要使用CGContextSetTextMatrix (ctx, myTextTransform); 其中的transform为关于x轴对称的变换矩阵。当然我们也可以不用这么做,我们只需要把原来CGContext的坐标关于x轴对称,然后再平移即可,看这句代码CGContextConcatCTM(ctx, CGAffineTransformConcat(myTextTransform, CGAffineTransformMakeTranslation(140.0f, 30.0f))); 。同样的,使用如下语句CGContextDrawImage(ctx, CGRectMake(0.0, 0.0, image.size.width, image.size.height), image.CGImage);绘制图片时,得到的也将是图片的倒影,所以同样的也需要进行关于x轴的坐标变换。但是使用[image drawInRect:CGRectMake(0.0f, 0.0f, image.size.width, image.size.height)];绘制图片时就不需要关于x轴对称。(经过实践,得知并不是像有些文章所说的CGContext的坐标原点在左下角,只是绘制文字以及图片时会得到倒影,做一下相关的变换即可)。

 

  就记录这么多了,知晓了原理以后,总可以通过几何变换得到我们想要的图形,当然所有的形状都要能用数学的形势描述出来,这个需要很深的造诣。

 

ios coredata卡顿 ios coregraphic_UI_05ios coredata卡顿 ios coregraphic_ci_06

展开代码[UIImage gradientCircleImgWithCenterColor:UIColorFromHex(0xff0000) endColor:UIColorFromHex(0x880000) radius:100.0f];

 

ios coredata卡顿 ios coregraphic_UI_05ios coredata卡顿 ios coregraphic_ci_06

展开代码+ (UIImage *)gradientCircleImgWithCenterColor:(UIColor *)centerColor endColor:(UIColor *)endColor radius:(CGFloat)radius
{
    UIColor *colors[] = {centerColor, endColor};
    UIGraphicsBeginImageContext(CGSizeMake(radius*2.0f, radius*2.0f));
    [[UIColor clearColor] setFill];
    
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    size_t numberOfComponents = CGColorGetNumberOfComponents(centerColor.CGColor);
    int numberOfColors = sizeof(colors)/sizeof(colors[0]);
    CGFloat colorComponents[numberOfColors*numberOfComponents];
    for (int i=0; i<numberOfColors; i++) {
        UIColor *color = colors[i];
        const CGFloat *components = CGColorGetComponents(color.CGColor);
        for (int j=0; j<numberOfComponents; j++) {
            colorComponents[i*numberOfComponents+j] = components[j];
        }
    }
    CGFloat locations[] = {0.0f, 1.0f};
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colorComponents, locations, sizeof(locations)/sizeof(locations[0]));
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);
    CGContextAddRect(ctx, CGRectMake(0.0f, 0.0f, radius*2.0f, radius*2.0f));
    CGContextClip(ctx);

//    CGContextSetShadowWithColor(ctx, CGSizeMake(-10.0f, -5.0f), 10.0, UIColorFromHex(0x222222).CGColor);
//    CGContextDrawRadialGradient(ctx, gradient, CGPointMake(radius, radius), 0.0f, CGPointMake(radius, radius), radius-30.0f, 0);
    CGFloat offset = 10.0f;
    CGFloat radiusOffset = 12.0f;
    CGContextSetShadowWithColor(ctx, CGSizeMake(10.0f, 5.0f), 7.0f, UIColorFromHex(0x222222).CGColor);
    CGContextDrawRadialGradient(ctx, gradient, CGPointMake(radius*1.5f-offset, radius*1.5f-offset), 0.0f, CGPointMake(radius*1.5f-offset, radius*1.5f-offset), radius*0.5f-radiusOffset, 0);
    CGContextSetShadowWithColor(ctx, CGSizeMake(-10.0f, -5.0f), 7.0f, UIColorFromHex(0x222222).CGColor);
    CGContextDrawRadialGradient(ctx, gradient, CGPointMake(radius*0.5f+offset, radius*0.5f+offset), 0.0f, CGPointMake(radius*0.5f+offset, radius*0.5f+offset), radius*0.5f-radiusOffset, 0);
    CGContextSetShadowWithColor(ctx, CGSizeMake(-10.0f, 5.0f), 7.0f, UIColorFromHex(0x222222).CGColor);
    CGContextDrawRadialGradient(ctx, gradient, CGPointMake(radius*0.5f+offset, radius*1.5f-offset), 0.0f, CGPointMake(radius*0.5f+offset, radius*1.5f-offset), radius*0.5f-radiusOffset, 0);
    CGContextSetShadowWithColor(ctx, CGSizeMake(10.0f, -5.0f), 7.0f, UIColorFromHex(0x222222).CGColor);
    CGContextDrawRadialGradient(ctx, gradient, CGPointMake(radius*1.5f-offset, radius*0.5f+offset), 0.0f, CGPointMake(radius*1.5f-offset, radius*0.5f+offset), radius*0.5f-radiusOffset, 0);
    
    CGGradientRelease(gradient);
    CGColorSpaceRelease(rgb);
    
    CGContextSetShadow(ctx, CGSizeMake(0.0f, 0.0f), 1.0f);
    CGContextSetFillColorWithColor(ctx, UIColorFromHex(0x00ff00).CGColor);
    CGContextBeginPath(ctx);
    CGContextAddArc(ctx, radius*0.5f+offset, radius*0.5f+offset, radius*0.5f-radiusOffset, M_PI_2, 0.0, 1);
    CGContextAddArc(ctx, radius*1.5f-offset, radius*0.5f+offset, radius*0.5f-radiusOffset, M_PI, M_PI_2, 1);
    CGContextAddArc(ctx, radius*1.5f-offset, radius*1.5f-offset, radius*0.5f-radiusOffset, -M_PI_2, -M_PI, 1);
    CGContextAddArc(ctx, radius*0.5f+offset, radius*1.5f-offset, radius*0.5f-radiusOffset, 0.0, -M_PI_2, 1);
    CGContextClosePath(ctx);
    CGContextFillPath(ctx);
    
    CGContextSetLineWidth(ctx, 2.0f);
    CGContextSetStrokeColorWithColor(ctx, UIColorFromHex(0xeeeeee).CGColor);
    CGContextStrokeRect(ctx, CGRectMake(radius*0.5f+offset, radius*0.5f+offset, radius-2.0f*offset, radius-2.0f*offset));
    
    CGContextRestoreGState(ctx);
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
//    [UIImagePNGRepresentation(image) writeToFile:[kCachePath stringByAppendingPathComponent:@"circle.png"] atomically:YES];
    return image;
}