iPhone "slide to unlock" animation iPhone "slide to unlock" animation ios ios

iPhone "slide to unlock" animation


It can be easilly done by using Core Animation, animating a mask layer on the layer displaying the text.

Try this in any plain UIViewController (you can start with a new Xcode project based on the View-based application project template), or grab my Xcode project here:

Note that the CALayer.mask property is only available in iPhone OS 3.0 and later.

- (void)viewDidLoad {  self.view.layer.backgroundColor = [[UIColor blackColor] CGColor];  UIImage *textImage = [UIImage imageNamed:@"SlideToUnlock.png"];  CGFloat textWidth = textImage.size.width;  CGFloat textHeight = textImage.size.height;  CALayer *textLayer = [CALayer layer];  textLayer.contents = (id)[textImage CGImage];  textLayer.frame = CGRectMake(10.0f, 215.0f, textWidth, textHeight);  CALayer *maskLayer = [CALayer layer];  // Mask image ends with 0.15 opacity on both sides. Set the background color of the layer  // to the same value so the layer can extend the mask image.  maskLayer.backgroundColor = [[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.15f] CGColor];  maskLayer.contents = (id)[[UIImage imageNamed:@"Mask.png"] CGImage];  // Center the mask image on twice the width of the text layer, so it starts to the left  // of the text layer and moves to its right when we translate it by width.  maskLayer.contentsGravity = kCAGravityCenter;  maskLayer.frame = CGRectMake(-textWidth, 0.0f, textWidth * 2, textHeight);  // Animate the mask layer's horizontal position  CABasicAnimation *maskAnim = [CABasicAnimation animationWithKeyPath:@"position.x"];  maskAnim.byValue = [NSNumber numberWithFloat:textWidth];  maskAnim.repeatCount = HUGE_VALF;  maskAnim.duration = 1.0f;  [maskLayer addAnimation:maskAnim forKey:@"slideAnim"];  textLayer.mask = maskLayer;  [self.view.layer addSublayer:textLayer];  [super viewDidLoad];}

The images used by this code are:

Mask LayerText Layer


Yet another solution using a layer mask, but instead draws the gradient by hand and does not require images. View is the view with the animation, transparency is a float from 0 - 1 defining the amount of transparency (1 = no transparency which is pointless), and gradientWidth is the desired width of the gradient.

CAGradientLayer *gradientMask = [CAGradientLayer layer]; gradientMask.frame = view.bounds;CGFloat gradientSize = gradientWidth / view.frame.size.width;UIColor *gradient = [UIColor colorWithWhite:1.0f alpha:transparency];NSArray *startLocations = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:(gradientSize / 2)], [NSNumber numberWithFloat:gradientSize]];NSArray *endLocations = @[[NSNumber numberWithFloat:(1.0f - gradientSize)], [NSNumber numberWithFloat:(1.0f -(gradientSize / 2))], [NSNumber numberWithFloat:1.0f]];CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"];gradientMask.colors = @[(id)gradient.CGColor, (id)[UIColor whiteColor].CGColor, (id)gradient.CGColor];gradientMask.locations = startLocations;gradientMask.startPoint = CGPointMake(0 - (gradientSize * 2), .5);gradientMask.endPoint = CGPointMake(1 + gradientSize, .5);view.layer.mask = gradientMask;animation.fromValue = startLocations;animation.toValue = endLocations;animation.repeatCount = HUGE_VALF;animation.duration  = 3.0f;[gradientMask addAnimation:animation forKey:@"animateGradient"];

SWIFT VERSION:

let transparency:CGFloat = 0.5let gradientWidth: CGFloat = 40let gradientMask = CAGradientLayer()gradientMask.frame = swipeView.boundslet gradientSize = gradientWidth/swipeView.frame.size.widthlet gradient = UIColor(white: 1, alpha: transparency)let startLocations = [0, gradientSize/2, gradientSize]let endLocations = [(1 - gradientSize), (1 - gradientSize/2), 1]let animation = CABasicAnimation(keyPath: "locations")gradientMask.colors = [gradient.CGColor, UIColor.whiteColor().CGColor, gradient.CGColor]gradientMask.locations = startLocationsgradientMask.startPoint = CGPointMake(0 - (gradientSize*2), 0.5)gradientMask.endPoint = CGPointMake(1 + gradientSize, 0.5)swipeView.layer.mask = gradientMaskanimation.fromValue = startLocationsanimation.toValue = endLocationsanimation.repeatCount = HUGEanimation.duration = 3gradientMask.addAnimation(animation, forKey: "animateGradient")

Swift 3

fileprivate func addGradientMaskToView(view:UIView, transparency:CGFloat = 0.5, gradientWidth:CGFloat = 40.0) {            let gradientMask = CAGradientLayer()    gradientMask.frame = view.bounds    let gradientSize = gradientWidth/view.frame.size.width    let gradientColor = UIColor(white: 1, alpha: transparency)    let startLocations = [0, gradientSize/2, gradientSize]    let endLocations = [(1 - gradientSize), (1 - gradientSize/2), 1]    let animation = CABasicAnimation(keyPath: "locations")    gradientMask.colors = [gradientColor.cgColor, UIColor.white.cgColor, gradientColor.cgColor]    gradientMask.locations = startLocations as [NSNumber]?    gradientMask.startPoint = CGPoint(x:0 - (gradientSize * 2), y: 0.5)    gradientMask.endPoint = CGPoint(x:1 + gradientSize, y: 0.5)    view.layer.mask = gradientMask    animation.fromValue = startLocations    animation.toValue = endLocations    animation.repeatCount = HUGE    animation.duration = 3    gradientMask.add(animation, forKey: nil)}


You can use the kCGTextClip drawing mode to set the clipping path and then fill with a gradient.

// Get ContextCGContextRef context = UIGraphicsGetCurrentContext();// Set FontCGContextSelectFont(context, "Helvetica", 24.0, kCGEncodingMacRoman);// Set Text MatrixCGAffineTransform xform = CGAffineTransformMake(1.0,  0.0,                                                0.0, -1.0,                                                0.0,  0.0);CGContextSetTextMatrix(context, xform);// Set Drawing Mode to set clipping pathCGContextSetTextDrawingMode (context, kCGTextClip);// Draw TextCGContextShowTextAtPoint (context, 0, 20, "Gradient", strlen("Gradient")); // Calculate Text widthCGPoint textEnd = CGContextGetTextPosition(context);// Generate Gradient locations & colorssize_t num_locations = 3;CGFloat locations[3] = { 0.3, 0.5, 0.6 };CGFloat components[12] = {     1.0, 1.0, 1.0, 0.5,    1.0, 1.0, 1.0, 1.0,    1.0, 1.0, 1.0, 0.5,};// Load ColorspaceCGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();// Create GradientCGGradientRef gradient = CGGradientCreateWithColorComponents (colorspace, components,                                                              locations, num_locations);// Draw Gradient (using clipping pathCGContextDrawLinearGradient (context, gradient, rect.origin, textEnd, 0);// Cleanup (exercise for reader)

Setup an NSTimer and vary the values in locations, or use CoreAnimation to do the same.