iPhone“滑动解锁”动画


75

关于Apple如何实现“滑动解锁”(也称为“滑动关机”是另一个相同的示例)动画的任何想法?

我考虑过某种动画遮罩-但出于性能原因,iPhone OS上不提供遮罩。

他们可能使用过一些私有API效果(例如SuckEffect)吗?聚光灯类型的效果?一些Core Animation的东西吗?

编辑:绝对不是一系列的剧照。我看过一些示例,这些示例正在编辑plist值或其他内容并在越狱的iphone上自定义字符串。


1
我是否正确理解iPhone不支持透明度?(我不拥有一个,所以我不知道)无论如何,根据此视频,实际文本可以更改,因此它不是某些预渲染的动画:uk.youtube.com/watch?v=PVhRnL55cJQ
Tamas Czinege

这是一部越狱的电话。我想知道如何使用官方SDK提取此动画。也就是说,无需使用隐藏的API或访问从CoreFilters等beta版本中删除的内容。

Answers:


70

通过使用Core Animation,在显示文本的图层上设置遮罩层动画,可以轻松完成此操作。

在任何普通的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];
}

此代码使用的图像是:

遮罩层 文字层


2
很好的解决方案。对于那些有兴趣不为标签添加资源的人,我UIImage从一个UILabel(或其他任何一个UIView)创建了一个: UIGraphicsBeginImageContext(_label); [[_label layer] renderInContext:UIGraphicsGetCurrentContext()]; UIImage *textImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
Maurizio

50

另一种使用层掩模的解决方案,而是手工绘制渐变,并且不需要图像。View是带有动画的视图,透明是从0到1的浮点数,定义了透明的数量(1 =无透明是毫无意义的),而gradientWidth是所需的渐变宽度。

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)
}

3
奇迹般有效!您应该按照文档建议用HUGE_VALF替换repeatCount常量。
MBulli

最好!适用于各种CALayer的超级简单!为此做了一个方法:-(void)addSlidingTextEffectToLabel:(UILabel *)标签方向:(UISwipeGestureRecognizerDirection)dir梯度宽度:(CGFloat)gradientWidth速度:(CGFloat)dur强度:(CGFloat)intensity;
伦纳德·保利2014年

1
@Samsinite一个问题,为什么[view removeFromSuperview]在设置蒙版之前和[superview addSubview:view]之后需要?没有它似乎可以正常工作,可能是我缺少了什么吗?
dariaa 2015年

@dariaa,自从我从事任何iOS开发以来已经有一年多了,所以我的记忆犹新。但是,看起来只有在将渐变蒙版添加到其父视图时才会绘制渐变蒙版。一旦将其添加到父视图(绘制)中,将不会绘制任何添加的图层蒙版。但是现在这可能已经改变了,这段代码是在iOS 6天之内编写的。
Samsinite

好一个!感谢分享。
托马斯·卡蒙

13

您可以使用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进行相同的操作。


5
一定要爱的GoreAnimation结束
理查德·罗斯三世

3
想知道何时有人会接手。花了将近一年的时间。
rpetrich

@Soonts:您可能需要kCGEncodingFontSpecific改用
rpetrich 2011年

@rpetrich:完全坏了。AFAIK,对于kCGEncodingFontSpecific,我必须提供自己的字符到字形的翻译,并且iOS中没有用于此的API。
即将

12

我将Pascal上面提供的代码添加为UILabel上的类别,因此您可以以这种方式为任何UILabel设置动画。这是代码。某些参数可能需要更改为背景色,等等。它使用与Pascal回答中嵌入的蒙版图像相同的蒙版图像。

//UILabel+FSHighlightAnimationAdditions.m
#import "UILabel+FSHighlightAnimationAdditions.h"
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@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 <Foundation/Foundation.h>
@interface UILabel (FSHighlightAnimationAdditions)

- (void)setTextWithChangeAnimation:(NSString*)text;

@end

1
开箱即用,这对我来说不起作用...也许我缺少UILabel的配置中的某些特定内容。一个完整的有效示例,无需创建我的文字图像就可以了。
bandejapaisa 2012年

@bandejapaisa您可能还没有添加Mask.png到你的资源
Mazyod

最好使用FLT_MAX代替1e100f
Cfr

5

不太新鲜...但是可能会有用

#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<text_length;i ++)
            _glyphs[i] = chars[i] - 29;

        // Measure text dimensions.
        CGContextSetTextDrawingMode(ctx, kCGTextInvisible); 
        CGContextSetTextPosition(ctx, 0, 0);
        CGContextShowGlyphs(ctx, _glyphs, text_length);
        CGPoint textEnd = CGContextGetTextPosition(ctx);

        // Calculate text drawing point.        
        CGPoint anchor = CGPointMake(textEnd.x * (-0.5), [[self font] pointSize] * (-0.25));  
        CGPoint p = CGPointApplyAffineTransform(anchor, CGAffineTransformMake(1, 0, 0, -1, 0, 1));

        if ([self textAlignment] == UITextAlignmentCenter) 
            alignment.x = [self bounds].size.width * 0.5 + p.x;
        else if ([self textAlignment] == UITextAlignmentLeft) 
            alignment.x = 0;
        else 
            alignment.x = [self bounds].size.width - textEnd.x;

        alignment.y = [self bounds].size.height * 0.5 + p.y;
    }

    // Flip back mirrored text.
    CGContextSetTextMatrix(ctx, CGAffineTransformMakeScale(1, -1));

    // Draw shadow.
    CGContextSaveGState(ctx);
    CGContextSetTextDrawingMode(ctx, kCGTextFill);
    CGContextSetFillColorWithColor(ctx, [[self textColor] CGColor]);
    CGContextSetShadowWithColor(ctx, [self shadowOffset], 0, [[self shadowColor] CGColor]);
    CGContextShowGlyphsAtPoint(ctx, alignment.x, alignment.y, _glyphs, text_length);
    CGContextRestoreGState(ctx);

    // Draw text clipping path.
    CGContextSetTextDrawingMode(ctx, kCGTextClip);
    CGContextShowGlyphsAtPoint(ctx, alignment.x, alignment.y, _glyphs, text_length);

    // Restore text mirroring.
    CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);

    if ([self isAnimating]) {
        // Fill text clipping path with gradient.
        CGPoint start = CGPointMake(rect.origin.x + current_position_x, rect.origin.y);
        CGPoint end = CGPointMake(rect.size.width/3*2 + current_position_x, rect.origin.y);

        CGContextDrawLinearGradient(ctx, gradient, start, end, 0);
    }
}


- (void) dealloc {
    free(_glyphs);
    [timer invalidate];
    [timer release];

    CGGradientRelease(gradient);
    [super dealloc];
}

CGFontGetGlyphsForUnichars-使用该报告的某些人未通过使用私有API的审查?
即将

4

感谢rpetrich提供的剪切梯度配方。我是iPhone和Cocoa的新手开发人员,因此很高兴能找到它。

我已经使用rpetrich的方法实现了一个看起来不错的Slide to Cancel UIViewController。您可以从此处下载实现的Xcode项目。

我的实现使用重复的NSTimer。我无法弄清楚如何使用Core(或Gore)动画使iPhone的图形引擎连续移动突出显示。我认为可以在具有CALayer遮罩层的OS X上完成此操作,但是iPhone OS不支持遮罩层。

当我在iPhone的主屏幕上使用Apple的“滑动解锁”滑块时,偶尔会看到动画冻结。因此,我认为Apple可能也会使用计时器。

如果有人能弄清楚如何使用CA或OpenGL执行基于非计时器的实现,我很乐意看到它。

谢谢您的帮助!



2

我从上述解决方案中汲取了最大的优势,并创建了一个简洁的方法来为您完成所有工作:

- (void)createSlideToUnlockViewWithText:(NSString *)text
{
    UILabel *label = [[UILabel alloc] init];
    label.text = text;
    [label sizeToFit];
    label.textColor = [UIColor whiteColor];

    //Create an image from the label
    UIGraphicsBeginImageContextWithOptions(label.bounds.size, NO, 0.0);
    [[label layer] renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *textImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGFloat textWidth = textImage.size.width;
    CGFloat textHeight = textImage.size.height;

    CALayer *textLayer = [CALayer layer];
    textLayer.contents = (id)[textImage CGImage];
    textLayer.frame = CGRectMake(self.view.frame.size.width / 2 - textWidth / 2, self.view.frame.size.height / 2 - textHeight / 2, textWidth, textHeight);

    UIImage *maskImage = [UIImage imageNamed:@"Mask.png"];
    CALayer *maskLayer = [CALayer layer];
    maskLayer.backgroundColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.15] CGColor];
    maskLayer.contents = (id)maskImage.CGImage;
    maskLayer.contentsGravity = kCAGravityCenter;
    maskLayer.frame = CGRectMake(-textWidth - maskImage.size.width, 0.0, (textWidth * 2) + maskImage.size.width, textHeight);

    CABasicAnimation *maskAnimation = [CABasicAnimation animationWithKeyPath:@"position.x"];
    maskAnimation.byValue = [NSNumber numberWithFloat:textWidth + maskImage.size.width];
    maskAnimation.repeatCount = HUGE_VALF;
    maskAnimation.duration = 2.0;
    maskAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [maskLayer addAnimation:maskAnimation forKey:@"slideAnimation"];

    textLayer.mask = maskLayer;
    self.slideToUnlockLayer = textLayer;
    [self.view.layer addSublayer:self.slideToUnlockLayer];
}

1

首先,非常感谢marcio的解决方案。这几乎可以完美地工作,节省了我很多时间,并且在我的应用程序中引起了极大的轰动。我的老板喜欢它。我欠你啤酒。或几个。

仅针对iPhone 4的一项小修正。我指的是硬件本身,而不仅仅是iOS4。他们将iPhone 4上的系统字体从Helvetica(iPhone 3G及更低版本)更改为Helvetic Neue。这导致您正在执行的从字符到字形的转换恰好偏离了4个点。例如,字符串“ fg”将显示为“ bc”。我通过将字体显式设置为“ Helvetica”而不是使用“ systemFontofSize”来解决此问题。现在,它就像一种魅力。

再次谢谢你!



1

这是一个SwiftUI版本:

struct Shimmer: AnimatableModifier {

    private let gradient: Gradient

    init(sideColor: Color = Color(white: 0.25), middleColor: Color = .white) {
        gradient = Gradient(colors: [sideColor, middleColor, sideColor])
    }

    @State private var position: CGFloat = 0
    var animatableData: CGFloat {
        get { position }
        set { position = newValue }
    }

    func body(content: Content) -> some View {
        content
            .overlay(LinearGradient(
                        gradient: gradient,
                        startPoint: .init(x: position - 0.2 * (1 - position), y: 0.5),
                        endPoint: .init(x: position + 0.2 * position, y: 0.5)))
            .mask(content)
            .onAppear {
                withAnimation(Animation
                                .linear(duration: 2)
                                .delay(1)
                                .repeatForever(autoreverses: false)) {
                    position = 1
                }
            }
    }
}

像这样使用它:

Text("slide to unlock")
    .modifier(Shimmer())

0

也许这只是一个渲染的动画-您知道,一系列剧照接连播放。不一定是动态效果。

更新:没关系,DrJokepu发布的视频证明它是动态生成的。


0
  • 上图:UILabel背景不透明且文本清晰
    • 在drawRect:函式中通过清晰的蒙版过程呈现明文
  • 中间:执行重复动画的工人视图,将图像移动到顶部标签后面
  • 底部:依次添加中间和顶部子视图的UIView。可以是您想要文本为任何颜色

可以在这里查看示例https://github.com/jhurray/AnimatedLabelExample

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.