Skip to content

Commit

Permalink
Added dynamic reflections example
Browse files Browse the repository at this point in the history
  • Loading branch information
nicklockwood committed Dec 31, 2011
1 parent 009654e commit f0df8eb
Show file tree
Hide file tree
Showing 14 changed files with 1,727 additions and 0 deletions.
45 changes: 45 additions & 0 deletions Examples/Reflections Demo/ReflectionView/ReflectionView.h
@@ -0,0 +1,45 @@
//
// ReflectionView.h
//
// Created by Nick Lockwood on 19/07/2011.
// Copyright 2011 Charcoal Design. All rights reserved.
//
// Get the latest version of ReflectionView from either of these locations:
//
// http://charcoaldesign.co.uk/source/cocoa#reflectionview
// https://github.com/nicklockwood/ReflectionView
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//

#import <UIKit/UIKit.h>


@class CAGradientLayer;

@interface ReflectionView : UIView

@property (nonatomic, assign) CGFloat reflectionGap;
@property (nonatomic, assign) CGFloat reflectionScale;
@property (nonatomic, assign) CGFloat reflectionAlpha;
@property (nonatomic, assign) BOOL dynamic;

- (void)update;

@end
225 changes: 225 additions & 0 deletions Examples/Reflections Demo/ReflectionView/ReflectionView.m
@@ -0,0 +1,225 @@
//
// ReflectionView.m
//
// Created by Nick Lockwood on 19/07/2011.
// Copyright 2011 Charcoal Design. All rights reserved.
//
// Get the latest version of ReflectionView from either of these locations:
//
// http://charcoaldesign.co.uk/source/cocoa#reflectionview
// https://github.com/nicklockwood/ReflectionView
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//

#import "ReflectionView.h"
#import <QuartzCore/QuartzCore.h>


@interface ReflectionView ()

@property (nonatomic, retain) CAGradientLayer *gradientLayer;
@property (nonatomic, retain) UIImageView *reflectionView;

@end


@implementation ReflectionView

@synthesize reflectionGap;
@synthesize reflectionScale;
@synthesize reflectionAlpha;
@synthesize gradientLayer;
@synthesize reflectionView;
@synthesize dynamic;

+ (Class)layerClass
{
return [CAReplicatorLayer class];
}

- (void)update
{
if (dynamic)
{
//remove gradient view
[reflectionView removeFromSuperview];
self.reflectionView = nil;

//update instances
CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
layer.shouldRasterize = YES;
layer.rasterizationScale = [UIScreen mainScreen].scale;
layer.instanceCount = 2;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, 0, layer.bounds.size.height + reflectionGap, 0);
transform = CATransform3DScale(transform, 1.0, -1.0, 0.0);
layer.instanceTransform = transform;
layer.instanceAlphaOffset = reflectionAlpha - 1.0;

//create gradient layer
if (!gradientLayer)
{
gradientLayer = [[CAGradientLayer alloc] init];
self.layer.mask = gradientLayer;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor blackColor].CGColor,
(id)[UIColor blackColor].CGColor,
(id)[UIColor clearColor].CGColor,
nil];
}

//update mask
[CATransaction begin];
[CATransaction setDisableActions:YES]; // don't animate
CGFloat total = layer.bounds.size.height * 2.0 + reflectionGap;
CGFloat halfWay = (layer.bounds.size.height + reflectionGap) / total - 0.01;
gradientLayer.frame = CGRectMake(0, 0, self.bounds.size.width, total);
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0],
[NSNumber numberWithFloat:halfWay],
[NSNumber numberWithFloat:halfWay + (1.0 - halfWay) * reflectionScale],
nil];
[CATransaction commit];
}
else
{
//remove gradient layer
self.layer.mask = nil;
self.gradientLayer = nil;

//update instances
CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
layer.shouldRasterize = NO;
layer.instanceCount = 1;

//create reflection view
if (!reflectionView)
{
reflectionView = [[UIImageView alloc] initWithFrame:self.bounds];
reflectionView.contentMode = UIViewContentModeScaleToFill;
reflectionView.userInteractionEnabled = NO;
[self addSubview:reflectionView];
}

//create gradient mask
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
CGContextRef gradientContext = UIGraphicsGetCurrentContext();
CGFloat colors[] = {1.0, 1.0, 0.0, 1.0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
CGPoint gradientStartPoint = CGPointMake(0, 0);
CGPoint gradientEndPoint = CGPointMake(0, self.bounds.size.height * reflectionScale);
CGContextDrawLinearGradient(gradientContext, gradient, gradientStartPoint,
gradientEndPoint, kCGGradientDrawsAfterEndLocation);
CGImageRef gradientMask = CGBitmapContextCreateImage(gradientContext);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
UIGraphicsEndImageContext();

//create drawing context
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -self.bounds.size.height);

//clip to gradient
CGContextClipToMask(context, self.bounds, gradientMask);
CGImageRelease(gradientMask);

//draw reflected layer content
[self.layer renderInContext:context];

//capture resultant image
reflectionView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//update reflection
reflectionView.alpha = reflectionAlpha;
reflectionView.frame = CGRectMake(0, self.bounds.size.height + reflectionGap,
self.bounds.size.width, self.bounds.size.height);
}
}

- (void)setup
{
//set default properties
reflectionGap = 4;
reflectionScale = 0.5;
reflectionAlpha = 0.5;

//update reflection
[self update];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder]))
{
[self setup];
}
return self;
}

- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
[self setup];
}
return self;
}

- (void)setReflectionGap:(CGFloat)_reflectionGap
{
reflectionGap = _reflectionGap;
[self update];
}

- (void)setReflectionScale:(CGFloat)_reflectionScale
{
reflectionScale = _reflectionScale;
[self update];
}

- (void)setReflectionAlpha:(CGFloat)_reflectionAlpha
{
reflectionAlpha = _reflectionAlpha;
[self update];
}

- (void)setDynamic:(BOOL)_dynamic
{
dynamic = _dynamic;
[self update];
}

- (void)layoutSubviews
{
[self update];
}

- (void)dealloc
{
[gradientLayer release];
[reflectionView release];
[super dealloc];
}

@end
2 changes: 2 additions & 0 deletions Examples/Reflections Demo/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

0 comments on commit f0df8eb

Please sign in to comment.