0

我将如何实现像Weather Channel iOS App中的加载动画?

具体来说,我有一个圆形UIButton,当用户点击它时我想要一个旋转的圆圈,并且正在加载一些东西。

最好是使用内置的 iOS 框架和尽可能少的 3rd 方库来实现这一点。

这是天气频道应用程序的外观(无法获得 gif,因此要查看实际效果,请从 App Store 下载应用程序):

天气频道 iOS App 截图

它不一定必须看起来完全像这样,纯色将是一个好的开始。但是概念应该是一样的。我不相信它应该很难做,但遗憾的是我不知道从哪里开始。

感谢大家的帮助!

编辑1: 我应该指出纯色就足够了,它不需要渐变或发光。

我一直在研究一些可能朝着正确方向的简单代码。请随意使用它作为起点:

- (void)drawRect:(CGRect)rect {
  // Make the button round
  self.layer.cornerRadius = self.frame.size.width / 2.0;
  self.clipsToBounds = YES;

  // Create the arc
  CAShapeLayer *circle = [CAShapeLayer layer];
  circle.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2) radius:(self.frame.size.width / 2) startAngle:M_PI_2 endAngle:M_PI clockwise:NO].CGPath;
  circle.fillColor = [UIColor clearColor].CGColor;
  circle.strokeColor = [UIColor redColor].CGColor;
  circle.lineWidth = 10;

  // Create the animation

  // Add arc to button
  [self.layer addSublayer:circle];
}
4

2 回答 2

2

正如在别处指出的那样,您可以添加一个视图,然后旋转它。如果您想使用基于块的动画进行旋转,它可能如下所示:

- (void)rotateView:(UIView *)view {
    [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
        [UIView animateKeyframesWithDuration:1.0 delay:0.0 options:UIViewKeyframeAnimationOptionRepeat animations:^{
            for (NSInteger i = 0; i < 4; i++) {
                [UIView addKeyframeWithRelativeStartTime:(CGFloat) i / 4.0 relativeDuration:0.25 animations:^{
                    view.transform = CGAffineTransformMakeRotation((CGFloat) (i + 1) * M_PI / 2.0);
                }];
            }
        } completion:nil];
    } completion:nil];
}

坦率地说,虽然我通常更喜欢基于块的动画,但用动画包装动画的愚蠢(这是没有缓入/缓出所必需的)使得基于块的方法不那么引人注目。但它说明了这个想法。


或者,在 iOS 7 及更高版本中,您可以使用 UIKit Dynamics 来旋转它:

  1. 为动画师定义一个属性:

    @property (nonatomic, strong) UIDynamicAnimator *animator;
    
  2. 实例化动画师:

    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
  3. 为项目添加旋转:

    UIDynamicItemBehavior *rotationBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.imageView]];
    [rotationBehavior addAngularVelocity:2.0 forItem:self.imageView];
    [self.animator addBehavior:rotationBehavior];
    
于 2015-01-07T15:18:18.873 回答
1

也许我错过了一些东西,但我认为您只需要旋转自定义旋转资产。

您可以使用以下方法轻松实现此目的:

- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration repeat:(float)repeat;
{
    CABasicAnimation* rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 * duration ];
    rotationAnimation.duration = duration;
    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = repeat;

    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

你需要无限期地重复它。所以把HUGE_VALF它作为重复参数。

如果您想根据您的按钮大小创建自定义旋转图像,您可以使用贝塞尔路径。例如,您可以执行以下操作:

-(UIImageView*)drawBezierPathInView:(UIView*)view{

    UIGraphicsBeginImageContext(CGSizeMake(view.frame.size.width, view.frame.size.height));

    //this gets the graphic context
    CGContextRef context = UIGraphicsGetCurrentContext();

    //you can stroke and/or fill
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1.f].CGColor);

    CGFloat lineWidth = 8.f;
    UIBezierPath *spin = [UIBezierPath bezierPath];
    [spin addArcWithCenter:CGPointMake(view.frame.size.width * 0.5f, view.frame.size.height * 0.5f) radius:view.frame.size.width * 0.5f - lineWidth * 0.5f startAngle:-M_PI_2 endAngle:2 * M_PI_2 clockwise:YES];
    [spin setLineWidth:lineWidth];
    [spin stroke];

    //now get the image from the context
    UIImage *bezierImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIImageView *bezierImageView = [[UIImageView alloc]initWithImage:bezierImage];
    return bezierImageView;
}

你创建你的按钮,如:

// myButton is your custom button. spinView is an UIImageView, you keep reference on it to apply or to stop animation
self.spinView = [self drawBezierPathInView:mybutton];
[mybutton addSubview:self.spinView];
[self runSpinAnimationOnView:self.spinView duration:3 repeat:HUGE_VALF];
于 2015-01-07T15:09:20.193 回答