-
实现一
使用一个继承自UIView的类来包含要实现倒影效果的图片,重写这个UIView子类的绘图方法,以实现图片于倒影,然后把这个View 添加到相应的地方显示。代码:CKReflectionImage.h[cpp]#import <UIKit/UIKit.h>@interface CKReflectionImage : UIView {@privateUIImage *image_;/*** Value of gradient start. This value is divided to height of image.*/CGFloat visibleReflectionHeight_;/*** Padding to top image.*/CGFloat paddingToTopImage_;}@property (nonatomic, readwrite, retain) UIImage *image;@property (nonatomic, readwrite, assign) CGFloat visibleReflectionHeight;@property (nonatomic, readwrite, assign) CGFloat paddingToTopImage;@endCKReflectionImage.h[cpp#import "CKReflectionImage.h"@implementation CKReflectionImage#pragma mark -#pragma mark Properties@synthesize image = image_;@synthesize visibleReflectionHeight = visibleReflectionHeight_;@synthesize paddingToTopImage = paddingToTopImage_;#pragma mark -#pragma mark Memory management- (void)dealloc {[image_ release];image_ = nil;visibleReflectionHeight_ = 0.0f;paddingToTopImage_ = 0.0f;[super dealloc];}#pragma mark -#pragma mark Draw methods/*** Draws the receiver’s image within the passed-in rectangle.** @param rect: The portion of the view’s bounds that needs to be updated.*/- (void)drawRect:(CGRect)rect {[super drawRect:rect];if (image_ != nil) {// Get current context to draw.CGContextRef context = UIGraphicsGetCurrentContext();// Reflection image referencesCGImageRef reflectionImage = NULL;CGImageRef gradientImage = NULL;// Frame of imageCGRect frame = [self frame];frame.origin.x = 0.0f;frame.origin.y = 0.0f;frame.size.width = CGRectGetWidth(frame);frame.size.height = image_.size.height * CGRectGetWidth(frame) / image_.size.width;// Draw initial image in contextCGContextSaveGState(context);{// Draw image in context, commented but the image show in reverse.// CGContextDrawImage(context, frame, [image_ CGImage]);// Push context to draw image.UIGraphicsPushContext(context);// Draw original image in top[image_ drawInRect:frame];// Pop to contextUIGraphicsPopContext();}CGContextRestoreGState(context);// Create gradient bitmapCGContextSaveGState(context);{// Gradient is always black-white and the mask must be in the gray colorspace.CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();// Create a bitmap contextCGContextRef gradientContext = CGBitmapContextCreate(NULL, CGRectGetWidth(frame), CGRectGetHeight(frame), 8, 0, colorSpace, kCGImageAlphaNone);// Define the start and the end grayscale values (with the alpha, even though our// bitmap context doesn't support alpha gradient requieres it).CGFloat colors[] = {0.0f, 1.0f, 1.0f, 1.0f};// Creates the CGGradientCGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);// Release colorSpace referenceCGColorSpaceRelease(colorSpace);// Create the start and end points for the gradient vector (straight down).CGPoint gradientStartPoint = CGPointMake(0, (CGRectGetHeight(frame) - visibleReflectionHeight_));CGPoint gradientEndPoint = CGPointMake(0, ((CGRectGetHeight(frame) * 2) - visibleReflectionHeight_));// Draw gradient into gradient context.CGContextDrawLinearGradient(gradientContext, grayScaleGradient, gradientStartPoint, gradientEndPoint, kCGGradientDrawsAfterEndLocation);// Release Gradient reference.CGGradientRelease(grayScaleGradient);// Convert the gradient context to image.gradientImage = CGBitmapContextCreateImage(gradientContext);// Release gradient contextCGContextRelease(gradientContext);}CGContextRestoreGState(context);// Apply gradient bitmap to new context that contains image.CGContextSaveGState(context);{// Create a RGB color spaceCGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();// Create bitmap context to join image and gradient context.CGContextRef reflectionContext = CGBitmapContextCreate(NULL, CGRectGetWidth(frame), CGRectGetHeight(frame), 8, 0, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast));// Release color spaceCGColorSpaceRelease(colorSpace);// First clip mask to contextCGContextSaveGState(context);{// Clip gradient mask to reflection context.CGContextClipToMask(reflectionContext, frame, gradientImage);}CGContextRestoreGState(context);// Second draw image to contextCGContextSaveGState(reflectionContext);{// Push context to draw image.UIGraphicsPushContext(reflectionContext);// Draw original image in top[image_ drawInRect:frame];// Pop to contextUIGraphicsPopContext();}CGContextRestoreGState(reflectionContext);// Delete gradient image maskCGImageRelease(gradientImage);// Convert reflection context to image.reflectionImage = CGBitmapContextCreateImage(reflectionContext);// Release reflection contextCGContextRelease(reflectionContext);}CGContextRestoreGState(context);// Transform matrix and draw reflection bitmap.CGContextSaveGState(context);{// Translate context matrix to height * 2 but next scale and sum 1.0f of image and padding.CGContextTranslateCTM(context, CGRectGetMinX(frame), (CGRectGetHeight(frame) * 2) + paddingToTopImage_);// Flip vertical image in context.CGContextScaleCTM(context, 1.0f, -1.0f);// Draw reflection image in context.CGContextDrawImage(context, frame, reflectionImage);// Release reflectio image.CGImageRelease(reflectionImage);}CGContextRestoreGState(context);}}/*** Set current image to another image.** @param image: Another image to set.*/- (void)setImage:(UIImage *)image {if (image_ != image) {[image_ release];image_ = [image retain];}[self setNeedsDisplay];}/*** Set current visibleReflectioHeight_ value to another.** @param gradientStart: Another value to visible reflectio height variable.*/- (void)setVisibleReflectionHeight:(CGFloat)visibleReflectioHeight {if (visibleReflectionHeight_ != visibleReflectioHeight) {visibleReflectionHeight_ = visibleReflectioHeight;}[self setNeedsDisplay];}/*** Set current paddingToTopImage variable to another value.** @param paddingToTopImage: Another value to padding to top image.*/- (void)setPaddingToTopImage:(CGFloat)paddingToTopImage {if (paddingToTopImage_ != paddingToTopImage) {paddingToTopImage_ = paddingToTopImage;}[self setNeedsDisplay];}@end使用:[cpp] www.2cto.comCKReflectionImage *reflectionImage = [[CKReflectionImage alloc] initWithFrame:CGRectMake(96, 20, 128, 460)];[reflectionImage setBackgroundColor:[UIColor clearColor]];//set the padding of top image and its reflected image[reflectionImage setPaddingToTopImage:5.0f];// Hide 1/4 parts of image. show 3/4[reflectionImage setVisibleReflectionHeight:(CGRectGetWidth([reflectionImage frame]) / 4 * 3)];[reflectionImage setImage:[UIImage imageNamed:@"1.png"]];[[self view] addSubview:reflectionImage];实现效果实现二为UIImage添加一个关于倒影的category,以实现返回这个图片,[cpp]#import <UIKit/UIKit.h>@interface UIImage (Reflection)- (UIImage *)reflectionWithHeight:(int)height;- (UIImage *)reflectionWithAlpha:(float)pcnt;- (UIImage *)reflectionRotatedWithAlpha:(float)pcnt;@endUIImage+Reflection.h[cpp]#import "UIImage+Reflection.h"#ifndef UIImageReflectionMethods#define UIImageReflectionMethodsCGImageRef CreateGradientImage (int pixelsWide, int pixelsHigh, CGFloat endPoint) {CGImageRef theCGImage = NULL;// gradient is always black-white and the mask must be in the gray colorspaceCGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();// create the bitmap contextCGContextRef gradientBitmapContext = CGBitmapContextCreate(NULL, pixelsWide, pixelsHigh, 8, 0, colorSpace, kCGImageAlphaNone);// define the start and end grayscale values (with the alpha, even though// our bitmap context doesn't support alpha the gradient requires it)CGFloat colors[] = {0.0, 1.0, 1, 1.0};// create the CGGradient and then release the gray color spaceCGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);CGColorSpaceRelease(colorSpace);// create the start and end points for the gradient vector (straight down)CGPoint gradientStartPoint = CGPointZero;CGPoint gradientEndPoint = CGPointMake(0, endPoint);if (endPoint < 0) {gradientEndPoint = CGPointMake(0, -endPoint);}// draw the gradient into the gray bitmap contextCGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint, gradientEndPoint, kCGGradientDrawsAfterEndLocation);CGGradientRelease(grayScaleGradient);// convert the context into a CGImageRef and release the contexttheCGImage = CGBitmapContextCreateImage(gradientBitmapContext);if (endPoint < 0) {// rotateCGContextClearRect(gradientBitmapContext, CGRectMake(0, 0, pixelsWide, pixelsHigh));CGContextTranslateCTM(gradientBitmapContext, 0.0, pixelsHigh);CGContextScaleCTM(gradientBitmapContext, 1.0, -1.0);CGContextDrawImage(gradientBitmapContext, CGRectMake(0, 0, pixelsWide, pixelsHigh), theCGImage);CGImageRelease(theCGImage);theCGImage = CGBitmapContextCreateImage(gradientBitmapContext);}CGContextRelease(gradientBitmapContext);// return the imageref containing the gradientreturn theCGImage;}static CGContextRef MyCreateBitmapContext (int pixelsWide, int pixelsHigh) {CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();// create the bitmap contextCGContextRef bitmapContext = CGBitmapContextCreate (NULL, pixelsWide, pixelsHigh, 8, 0, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));CGColorSpaceRelease(colorSpace);return bitmapContext;}#endif@implementation UIImage (Reflection)- (UIImage *)reflectionRotatedWithAlpha:(float)pcnt {int height = self.size.height;UIImage * fromImage = self;pcnt = 1.0 / pcnt;// create a bitmap graphics context the size of the imageCGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, height);// create a 2 bit CGImage containing a gradient that will be used for masking the// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradientCGImageRef gradientMaskImage = CreateGradientImage(1, height, -(height * pcnt));// create an image by masking the bitmap of the mainView content with the gradient view// then release the pre-masked content bitmap and the gradient bitmapCGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.size.width, height), gradientMaskImage);CGImageRelease(gradientMaskImage);// In order to grab the part of the image that we want to render, we move the context origin to the// height of the image that we want to capture, then we flip the context so that the image draws upside down.// CGContextTranslateCTM(mainViewContentContext, 0.0, height);// CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);// draw the image into the bitmap contextCGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), [fromImage CGImage]);// create CGImageRef of the main view bitmap content, and then release that bitmap contextCGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);CGContextRelease(mainViewContentContext);// convert the finished reflection image to a UIImageUIImage * theImage = [UIImage imageWithCGImage:reflectionImage];// image is retained by the property setting above, so we can release the originalCGImageRelease(reflectionImage);return theImage;}- (UIImage *)reflectionWithHeight:(int)height {if (height == -1) {height = [self size].height;}if (height == 0)return nil;UIImage * fromImage = self;// create a bitmap graphics context the size of the imageCGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, fromImage.size.height);// create a 2 bit CGImage containing a gradient that will be used for masking the// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradientCGImageRef gradientMaskImage = CreateGradientImage(1, height, height);// create an image by masking the bitmap of the mainView content with the gradient view// then release the pre-masked content bitmap and the gradient bitmapCGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.size.width, height), gradientMaskImage);CGImageRelease(gradientMaskImage);// In order to grab the part of the image that we want to render, we move the context origin to the// height of the image that we want to capture, then we flip the context so that the image draws upside down.CGContextTranslateCTM(mainViewContentContext, 0.0, fromImage.size.height);CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);// draw the image into the bitmap contextCGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), [fromImage CGImage]);// create CGImageRef of the main view bitmap content, and then release that bitmap contextCGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);CGContextRelease(mainViewContentContext);// convert the finished reflection image to a UIImageUIImage * theImage = [UIImage imageWithCGImage:reflectionImage];// image is retained by the property setting above, so we can release the originalCGImageRelease(reflectionImage);return theImage;}- (UIImage *)reflectionWithAlpha:(float)pcnt {int height = self.size.height;UIImage * fromImage = self;pcnt = 1.0 / pcnt;// create a bitmap graphics context the size of the imageCGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, height);// create a 2 bit CGImage containing a gradient that will be used for masking the// main view content to create the 'fade' of the reflection. The CGImageCreateWithMask// function will stretch the bitmap image as required, so we can create a 1 pixel wide gradientCGImageRef gradientMaskImage = CreateGradientImage(1, height, height * pcnt);// create an image by masking the bitmap of the mainView content with the gradient view// then release the pre-masked content bitmap and the gradient bitmapCGContextClipToMask(mainViewContentContext, CGRectMake(0.0, 0.0, fromImage.size.width, height), gradientMaskImage);CGImageRelease(gradientMaskImage);// In order to grab the part of the image that we want to render, we move the context origin to the// height of the image that we want to capture, then we flip the context so that the image draws upside down.CGContextTranslateCTM(mainViewContentContext, 0.0, height);CGContextScaleCTM(mainViewContentContext, 1.0, -1.0);// draw the image into the bitmap contextCGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), [fromImage CGImage]);// create CGImageRef of the main view bitmap content, and then release that bitmap contextCGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);CGContextRelease(mainViewContentContext);// convert the finished reflection image to a UIImageUIImage * theImage = [UIImage imageWithCGImage:reflectionImage];// image is retained by the property setting above, so we can release the originalCGImageRelease(reflectionImage);return theImage;}@end使用非常简单:[cpp][refView setImage:[image reflectionWithAlpha:0.5]];[imageView setImage:[image reflectionWithHeight:50]];[topRefView setImage:[image reflectionRotatedWithAlpha:0.5]];效果