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

时间:2019-07-15 17:20:16

标签: swift animation calayer

CALayer动画

我的应用程序的目的是在TableView中显示待办事项/任务。所有任务都有一个开始值和一个结束值。

对于第一个任务,我想显示进度指示器以大致了解剩余时间。对于背景,我的ViewController中有一个具有autoLayout约束的UIView。我用于动画的CALayer是backgroundView的子层。 x轴上图层的起点是variabel,因此即使重新加载应用程序,计时器也已正确设置。终点是绝对值(背景视图的整个宽度)。这些参数都能完美运行,只是动画不起作用。我正在设置从动画应该开始的位置开始的值以及剩下的持续时间,但是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)

}

2 个答案:

答案 0 :(得分:0)

您应该能够将CABasicAnimation用于您要完成的工作。我已经在Objective-C中发布了我的答案,但是我敢肯定,将其适应Swift也相对容易。

我认为您还缺少其他几件事:

设置图层的锚点和位置:

    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];

在此示例中,仅使用一个视图控制器为从中途点到整个点的进度条设置动画:

@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

您应该能够在自定义表格视图单元的awakeFromNib中执行类似的操作,并使用某种方法来触发动画。

这是上面的示例:

Animate_Progress_Layer

答案 1 :(得分:0)

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var backgroundView: UIView!
    
    var progressLayer : CALayer!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.setUpLayer()
        
    }
    
    
    func setUpLayer(){
        
    
        let x = self.backgroundView.bounds.origin.x
        let y = self.backgroundView.bounds.origin.y
        let height = self.backgroundView.bounds.size.height
        let width  = self.backgroundView.bounds.size.width
        
        self.progressLayer = CALayer.init()
        self.progressLayer.frame = CGRect(x: x, y: y, width: 0, height: height)
        self.progressLayer.position = CGPoint.zero
        self.progressLayer.anchorPoint = CGPoint.zero;
        self.progressLayer.backgroundColor = UIColor.red.cgColor;
        self.backgroundView.layer.addSublayer(self.progressLayer)
     
    
    }
    
    @IBAction func buttonAction(_ sender: Any) {
        
     //   self.progressLayer.removeAnimation(forKey: "progressAnimation")
        
        var progressAnimation = CABasicAnimation(keyPath: "bounds.size.width")
         progressAnimation.duration = 2.0
        progressAnimation.toValue =  self.backgroundView.bounds.width
        progressAnimation.fillMode = .forwards
        
        progressAnimation.isRemovedOnCompletion = false
        
        self.progressLayer.add(progressAnimation, forKey: "progressAnimation")

        
    }
    

}