【问题标题】:Using CAShapeLayer to create UIActivityIndicator animation使用 CAShapeLayer 创建 UIActivityIndi​​cator 动画
【发布时间】:2016-01-07 11:07:19
【问题描述】:

我想使用CAShapeLayer stroke 创建看起来像UIActivityIndicator 动画的动画。

我已经创建了图层:

self.ovalShapeLayer = [CAShapeLayer layer];

self.ovalShapeLayer.strokeColor = [UIColor redColor].CGColor;
self.ovalShapeLayer.fillColor = [UIColor clearColor].CGColor;
self.ovalShapeLayer.lineWidth = 15.0;

self.ovalShapeLayer.lineDashPattern = @[@1, @9];
self.ovalShapeLayer.lineDashPhase = 20.0;
self.ovalShapeLayer.lineJoin = kCALineJoinBevel;
self.ovalShapeLayer.strokeStart = 0.0;
self.ovalShapeLayer.strokeEnd = 1.0;

self.ovalShapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:self.controlView.bounds].CGPath;

[self.controlView.layer addSublayer:self.ovalShapeLayer];

而且效果很好。我还可以使用

为笔画末端设置动画
[CABasicAnimation animationWithKeyPath:@"strokeEnd"]

但是UIActivityIndicator 动画更复杂,因为它的破折号正在淡入/淡出,看起来像旋转。您对如何实现该动画有任何想法吗?我正在考虑使用新的CAShapeLayer 创建每个破折号,然后使用keyframe 不透明动画,但这似乎是错误的方式。

【问题讨论】:

    标签: ios objective-c uiactivityindicatorview cashapelayer caanimation


    【解决方案1】:

    您可以在附件中获取 1 张加载器图像,然后在 z 轴上旋转该图像。

    CABasicAnimation* rotationAnimation;
        rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
        rotationAnimation.duration = duration;
        rotationAnimation.cumulative = YES;
        rotationAnimation.repeatCount = repeat;
    
    [imageView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
    

    @interface CustomView (){
        __weak IBOutlet UIImageView *loaderImageView;
    }
    
    @end
    
    @implementation CustomView
    
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
        if (self) {
            // Initialization code
    //        loaderImageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, 35, 35}];
    //        loaderImageView.contentMode = UIViewContentModeScaleAspectFit;
    //        [self addSubview:loaderImageView];
    
        }
        return self;
    }
    
    - (void) setUp{
        CABasicAnimation* rotationAnimation1;
        rotationAnimation1 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        rotationAnimation1.toValue = @M_PI_2;
        rotationAnimation1.duration = 1.0;
        rotationAnimation1.cumulative = YES;
        rotationAnimation1.repeatCount = HUGE_VALF;
        [loaderImageView.layer addAnimation:rotationAnimation1 forKey:@"rotation"];
    }
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect
    {
        // Drawing code
    }
    */
    
    @end
    

    【讨论】:

    • 但是在这个方法中我需要很多 UIImageView 对象,对吗?
    • 不,您只需要 1 张图像,在 z 轴上旋转图像会得到如附件截图所示的输出。
    • 但我说的是 UIImageView,而不是 UIImage。我不应该查看每个破折号吗?
    • [imageView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];它正在使用uiimageview。在 uiimageview 中设置 1 个图像,并像在共享代码中一样旋转它的图层。它会工作
    • 也许我没有正确理解,但我的观点是围绕它自己的轴旋转。能否提供完整代码?
    【解决方案2】:

    我花了很多时间了解 UIRefreshControl 的工作原理,包括 UIActivityIndi​​cator。最后,我写了一个刷新控件来避免系统刷新控件中的一些问题。这是我在刷新控件中的活动指示器的代码:https://github.com/JohnWong/JWKit/blob/master/refresh-control/JWRefreshIndicatorView.m

    如果你使用 lldb 来检查系统活动指示器和我的,你会发现它和 UIActivityIndi​​cator 非常相似。 CAReplicatorLayer 是创建视图的关键。

    【讨论】:

      【解决方案3】:

      经过一些研究,我发现了很棒的课程 - CAReplicatorLayer

      使用该类,我能够创建一个CALayer 对象并使用CATransform3D 复制它。

      这是我的代码:

          self.replicatorLayer = [CAReplicatorLayer layer];
          self.replicatorLayer.frame = self.controlView.bounds;
          [self.controlView.layer addSublayer:self.replicatorLayer];
      
          self.dashLayer = [CALayer layer];
          CGFloat dotSide = 4.0;
      
          self.dashLayer.frame = CGRectMake(CGRectGetMidX(self.replicatorLayer.frame) - dotSide / 2, 0.0, dotSide, dotSide * 4);
          self.dashLayer.backgroundColor = [UIColor redColor].CGColor;
          self.dashLayer.cornerRadius = 1.5;
          self.dashLayer.cornerRadius = 2.5;
          [self.replicatorLayer addSublayer:self.dashLayer];
      
          self.replicatorLayer.instanceCount = 12;
          self.replicatorLayer.instanceTransform = CATransform3DMakeRotation(M_PI / 6, 0.0, 0.0, 1.0);
          self.replicatorLayer.instanceDelay = 1.0 / 12;
      

      动画看起来像这样:

          CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
          animation.fromValue = @(1.0);
          animation.toValue = @(0.0);
          animation.duration = 1.0;
          animation.repeatCount = CGFLOAT_MAX;
          [self.dashLayer addAnimation:animation forKey:nil];
      

      像魅力一样工作;)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-20
        • 1970-01-01
        相关资源
        最近更新 更多