关于Apple如何实现"幻灯片解锁"(还有"滑动关闭"是另一个相同的例子)动画的任何想法?
我想过某种动画面具 - 但出于性能原因,iPhone OS上没有屏蔽功能.
是否有他们可能使用的私有API效果(如SuckEffect)?一种聚光灯效果?一些核心动画的事情?
编辑:这绝对不是一系列剧照.我已经看过编辑plist值或其他东西的例子,并在越狱的iphone上自定义字符串.
通过使用核心动画可以轻松完成,在显示文本的图层上设置遮罩层动画.
在任何普通的UIViewController中尝试这个(你可以从基于View的应用程序项目模板的新Xcode项目开始),或者在这里获取我的Xcode项目:
请注意,该CALayer.mask
属性仅适用于iPhone OS 3.0及更高版本.
- (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]; }
此代码使用的图像是:
另一种解决方案是使用图层蒙版,而是手工绘制渐变而不需要图像.视图是带动画的视图,透明度是从0到1的浮点数,用于定义透明度(1 =无透明度,无意义),渐变宽度是渐变的所需宽度.
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版本:
let transparency:CGFloat = 0.5 let gradientWidth: CGFloat = 40 let gradientMask = CAGradientLayer() gradientMask.frame = swipeView.bounds let gradientSize = gradientWidth/swipeView.frame.size.width let 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 = startLocations gradientMask.startPoint = CGPointMake(0 - (gradientSize*2), 0.5) gradientMask.endPoint = CGPointMake(1 + gradientSize, 0.5) swipeView.layer.mask = gradientMask animation.fromValue = startLocations animation.toValue = endLocations animation.repeatCount = HUGE animation.duration = 3 gradientMask.addAnimation(animation, forKey: "animateGradient")
斯威夫特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) }
您可以使用kCGTextClip
绘图模式设置剪切路径,然后使用渐变填充.
// Get Context CGContextRef context = UIGraphicsGetCurrentContext(); // Set Font CGContextSelectFont(context, "Helvetica", 24.0, kCGEncodingMacRoman); // Set Text Matrix CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); CGContextSetTextMatrix(context, xform); // Set Drawing Mode to set clipping path CGContextSetTextDrawingMode (context, kCGTextClip); // Draw Text CGContextShowTextAtPoint (context, 0, 20, "Gradient", strlen("Gradient")); // Calculate Text width CGPoint textEnd = CGContextGetTextPosition(context); // Generate Gradient locations & colors size_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 Colorspace CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); // Create Gradient CGGradientRef gradient = CGGradientCreateWithColorComponents (colorspace, components, locations, num_locations); // Draw Gradient (using clipping path CGContextDrawLinearGradient (context, gradient, rect.origin, textEnd, 0); // Cleanup (exercise for reader)
设置NSTimer并更改位置中的值,或使用CoreAnimation执行相同操作.
我将Pascal上面提供的代码添加为UILabel上的类别,因此您可以以这种方式为任何UILabel制作动画.这是代码.某些参数可能需要根据您的背景颜色等进行更改.它使用与Pascal在其答案中嵌入的相同的蒙版图像.
//UILabel+FSHighlightAnimationAdditions.m #import "UILabel+FSHighlightAnimationAdditions.h" #import#import @implementation UILabel (FSHighlightAnimationAdditions) - (void)setTextWithChangeAnimation:(NSString*)text { NSLog(@"value changing"); self.text = text; 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(self.frame.size.width * -1, 0.0f, self.frame.size.width * 2, self.frame.size.height); // Animate the mask layer's horizontal position CABasicAnimation *maskAnim = [CABasicAnimation animationWithKeyPath:@"position.x"]; maskAnim.byValue = [NSNumber numberWithFloat:self.frame.size.width]; maskAnim.repeatCount = 1e100f; maskAnim.duration = 2.0f; [maskLayer addAnimation:maskAnim forKey:@"slideAnim"]; self.layer.mask = maskLayer; } @end //UILabel+FSHighlightAnimationAdditions.h #import @interface UILabel (FSHighlightAnimationAdditions) - (void)setTextWithChangeAnimation:(NSString*)text; @end
不是那么新鲜......但也许它会有用
#define MM_TEXT_TO_DISPLAY @"default" #define MM_FONT [UIFont systemFontOfSize:MM_FONT_SIZE] #define MM_FONT_SIZE 25 #define MM_FONT_COLOR [[UIColor darkGrayColor] colorWithAlphaComponent:0.75f]; #define MM_SHADOW_ENABLED NO #define MM_SHADOW_COLOR [UIColor grayColor] #define MM_SHADOW_OFFSET CGSizeMake(-1,-1) #define MM_CONTENT_EDGE_INSETS_TOP 0 #define MM_CONTENT_EDGE_INSETS_LEFT 10 #define MM_CONTENT_EDGE_INSETS_BOTTON 0 #define MM_CONTENT_EDGE_INSETS_RIGHT 10 #define MM_CONTENT_EDGE_INSETS UIEdgeInsetsMake(MM_CONTENT_EDGE_INSETS_TOP, MM_CONTENT_EDGE_INSETS_LEFT, MM_CONTENT_EDGE_INSETS_BOTTON, MM_CONTENT_EDGE_INSETS_RIGHT) #define MM_TEXT_ALIGNMENT UITextAlignmentCenter #define MM_BACKGROUND_COLOR [UIColor clearColor] #define MM_TIMER_INTERVAL 0.05f #define MM_HORIZONTAL_SPAN 5 @interface MMAnimatedGradientLabel : UILabel { NSString *textToDisplay; int text_length; CGGradientRef gradient; int current_position_x; NSTimer *timer; CGPoint alignment; CGGlyph *_glyphs; } - (id)initWithString:(NSString *)_string; - (void)startAnimation; - (void)toggle; - (BOOL)isAnimating; @end #define RGB_COMPONENTS(r, g, b, a) (r) / 255.0f, (g) / 255.0f, (b) / 255.0f, (a) @interface MMAnimatedGradientLabel (Private) - (CGRect)calculateFrame; @end @implementation MMAnimatedGradientLabel // Missing in standard headers. extern void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], const CGGlyph[], size_t); - (id)init { textToDisplay = MM_TEXT_TO_DISPLAY; return [self initWithFrame:[self calculateFrame]]; } - (id)initWithString:(NSString *)_string { textToDisplay = _string; return [self initWithFrame:[self calculateFrame]]; } -(id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // set default values // self.textAlignment = MM_TEXT_ALIGNMENT; self.backgroundColor = MM_BACKGROUND_COLOR; self.font = MM_FONT; self.text = textToDisplay; self.textColor = MM_FONT_COLOR; if (MM_SHADOW_ENABLED) { self.shadowColor = MM_SHADOW_COLOR; self.shadowOffset = MM_SHADOW_OFFSET; } text_length = -1; CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); CGFloat colors[] = { RGB_COMPONENTS(255.0, 255.0, 255.0, 0.00), // RGB_COMPONENTS(255.0, 255.0, 255.0, 0.15), RGB_COMPONENTS(255.0, 255.0, 255.0, 0.95), // RGB_COMPONENTS(255.0, 255.0, 255.0, 0.15), RGB_COMPONENTS(255.0, 255.0, 255.0, 0.00) }; gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4)); CGColorSpaceRelease(rgb); current_position_x = -(frame.size.width/2);// - MM_CONTENT_EDGE_INSETS.left - MM_CONTENT_EDGE_INSETS.right); } return self; } - (CGRect)calculateFrame { CGSize size = [textToDisplay sizeWithFont:MM_FONT]; NSLog(@"size: %f, %f", size.width, size.height); return CGRectMake(0, 0, size.width + MM_CONTENT_EDGE_INSETS.left + MM_CONTENT_EDGE_INSETS.right, size.height + MM_CONTENT_EDGE_INSETS.top + MM_CONTENT_EDGE_INSETS.bottom); } - (void)tick:(NSTimer*)theTimer { if (current_position_x < self.frame.size.width) current_position_x = current_position_x + MM_HORIZONTAL_SPAN; else current_position_x = -(self.frame.size.width/2); // - MM_CONTENT_EDGE_INSETS.left - MM_CONTENT_EDGE_INSETS.right); [self setNeedsDisplay]; } - (void)startAnimation { timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:MM_TIMER_INTERVAL target:self selector:@selector(tick:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } - (void)toggle { if (!timer) { timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:MM_TIMER_INTERVAL target:self selector:@selector(tick:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } else { [timer invalidate]; [timer release]; timer = nil; current_position_x = -(self.frame.size.width/2); [self setNeedsDisplay]; } } - (BOOL)isAnimating { if (timer) return YES; else return NO; } - (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); // Get drawing font. CGFontRef font = CGFontCreateWithFontName((CFStringRef)[[self font] fontName]); CGContextSetFont(ctx, font); CGContextSetFontSize(ctx, [[self font] pointSize]); // Calculate text drawing point only first time // if (text_length == -1) { // Transform text characters to unicode glyphs. text_length = [[self text] length]; unichar chars[text_length]; [[self text] getCharacters:chars range:NSMakeRange(0, text_length)]; _glyphs = malloc(sizeof(CGGlyph) * text_length); for (int i=0; i