Swift 如何设置CALayer从可变起点到给定终点的动画 卡拉耶动画

Swift 如何设置CALayer从可变起点到给定终点的动画 卡拉耶动画,swift,animation,calayer,Swift,Animation,Calayer,我的应用程序的目的是在表格视图中显示待办事项/任务。所有任务都有开始值和结束值 对于第一个任务,我想显示一个进度指示器,以便更好地了解剩余时间。对于背景,我的ViewController中有一个带有自动布局约束的UIView。我用于动画的CALayer是背景视图中的一个子层。x轴上图层的起点是variabel,因此即使重新加载应用程序,计时器也设置正确。终点是绝对值(背景视图的全宽)。这些参数都工作得很好,只是动画不工作。我正在设置动画应该从哪里开始的值,以及剩余的持续时间,但CALayer不会

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

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

()


您应该能够使用CABasicAnimation来完成您试图完成的任务。我已经在Objective-C中发布了我的答案,但我确信将其应用于Swift也相对容易

我认为您还缺少一些其他东西:

设置层的锚固点和位置: 设置bounds.size.width键路径的CABasicAnimation 将填充模式设置为“向前”,并将“完成时删除”设置为“否” 下面是一个仅使用一个视图控制器的示例,该视图控制器用于设置进度条从中点到全点的动画:

@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+某些方法中执行类似的操作来触发动画

下面是上面的例子:


您应该能够使用Cabasicanization来完成您试图完成的任务。我已经在Objective-C中发布了我的答案,但我确信将其应用于Swift也相对容易

我认为您还缺少一些其他东西:

设置层的锚固点和位置: 设置bounds.size.width键路径的CABasicAnimation 将填充模式设置为“向前”,并将“完成时删除”设置为“否” 下面是一个仅使用一个视图控制器的示例,该视图控制器用于设置进度条从中点到全点的动画:

@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+某些方法中执行类似的操作来触发动画

下面是上面的例子:


非常感谢,我正在尝试用swift重新创建它。你在哪里设置位置,我假设它在你的viewDidLoad()中设置帧的位置。是的,在我的示例中,我在viewDidLoad中设置了progressLayer的位置。如果您在UITableViewCell中使用此功能,我猜您可能希望将其设置为awakeFromNib。非常感谢,我正在尝试用swift重新创建它。你在哪里设置位置,我假设它在你的viewDidLoad()中设置帧的位置。是的,在我的示例中,我在viewDidLoad中设置了progressLayer的位置。如果您在UITableViewCell中使用它,我猜您可能需要在awakeFromNib中设置它。
CABasicAnimation *progressAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size.width"];
    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
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")

        
    }
    

}