swift - 如何为 CALayer 从可变起点到给定终点设置动画

标签 swift animation calayer

CALayer动画

我的应用程序的目的是在 TableView 中显示 ToDos/Tasks。所有任务都有开始值和结束值。

对于第一个任务,我想显示一个进度指示器,以便更好地了解剩余时间。对于背景,我的 ViewController 中有一个带有 autoLayout 约束的 UIView。我用于动画的 CALayer 是 backgroundView 的子层。 x 轴上层的起点是可变的,因此即使重新加载应用程序,计时器也设置正确。终点是一个绝对值(背景 View 的全宽)。这些参数都运行良好,只是动画不起作用。我正在设置动画应该开始的值,以及剩余的持续时间,但 CALayer 不会移动。我曾尝试使用 UIView.animate 和 CABasicAnimation 来操纵图层,但在每种情况下,将图层设置到其起始位置后,动画都不会开始。

( https://ise-technology.com/cdn/stack-overflow/calayertimer/timer )

// func for setting setting the CALayer and the BackgroundView for the given values

func setTimerView(isActive: Bool, color: UIColor, animationDuration: Double){
    
    if isActive == true {
        
        configureBackgroundView(bool: true) // just sets the height for the background view
        
        backgroundTimerView.backgroundColor = color.withAlphaComponent(0.3)
        
        timerView.backgroundColor = color.cgColor
        
        setAnimationForDuration(duration: animationDuration)
        
    } else {
        configureBackgroundView(bool: false)
        timerView.backgroundColor = UIColor.clear.cgColor
    }
}


// func where the animation should be embedded 

func setAnimationForDuration(duration: Double) {

    let startPoint = setStartPoint(duration: duration)

    timerView.frame.origin.x = CGFloat(-startPoint)
    

    // after updating the origin X of the Layer to the current   position, its not possible to start an animation. My attempts to here place in this func


    let animation = CABasicAnimation()
    
    animation.duration = duration
    animation.toValue = timerView.frame.origin.x = 0 

    timerView.add(animation, forKey: nil)
     
}

最佳答案

您应该能够使用 CABasicAnimation 来完成您想要完成的任务。我已经在 Objective-C 中发布了我的答案,但我确信将它改编为 Swift 也相对容易。

我认为您还遗漏了一些额外的东西:

设置图层的 anchor 和位置:

    self.progressLayer.position = CGPointZero;
    self.progressLayer.anchorPoint = CGPointZero;

为 bounds.size.width 键路径设置 CABasicAnimation

CABasicAnimation *progressAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size.width"];

设置填充模式为转发,完成后移除为NO

    progressAnimation.fillMode = kCAFillModeForwards;
    [progressAnimation setRemovedOnCompletion:NO];

这是一个仅使用一个 View Controller 的示例,它为进度条从中间点到终点设置动画:

@interface ViewController ()
@property (strong, nullable) IBOutlet UIView *backgroundView;
@property (strong, nullable) CALayer *progressLayer;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.progressLayer = [[CALayer alloc] init];
    [self.progressLayer setFrame:CGRectMake(self.backgroundView.bounds.origin.x, self.backgroundView.bounds.origin.y, self.backgroundView.bounds.size.width / 2.0f, self.backgroundView.bounds.size.height)];
    self.progressLayer.position = CGPointZero;
    self.progressLayer.anchorPoint = CGPointZero;
    self.progressLayer.backgroundColor = [UIColor greenColor].CGColor;
    [self.backgroundView.layer addSublayer:self.progressLayer];
}

- (IBAction)animateProgress:(id)sender {
    [self.progressLayer removeAnimationForKey:@"progressAnimation"];
    CABasicAnimation *progressAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size.width"];
    progressAnimation.duration = 2.0f;
    progressAnimation.toValue = @(self.backgroundView.bounds.size.width);
    progressAnimation.fillMode = kCAFillModeForwards;
    [progressAnimation setRemovedOnCompletion:NO];
    [self.progressLayer addAnimation:progressAnimation forKey:@"progressAnimation"];
}

@end

您应该能够在自定义 tableview 单元格的 awakeFromNib + 一些方法中执行类似的操作来触发动画。

上面的例子是这样的:

Animate_Progress_Layer

关于swift - 如何为 CALayer 从可变起点到给定终点设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57044479/

相关文章:

ios - 将 UNIX 时间从 json 导入(swift 结构)转换为日期作为字符串并填充表

android - 以编程方式调整布局大小(作为动画)

ios - 无法对 SCNPlane 阵列使用多个图像

ios - 是否有一种方法比 NSKeyedArchiver 使用更少的内存来归档对象?

ios - 重新加载表会导致闪烁

animation - Blender 导出了一个 Three.js 动画 - 骨骼奇怪地旋转

css - 如何淡入和淡出svg的颜色

ios5 - 自定义 CALayer - 无效的上下文 0x0

ios - 使用UIBezierPath绘制同心圆

ios - Swift、Firebase 从未知子项中检索数据