Swift:动画CALayer

3
在下面的代码中,我正在尝试通过用户按住屏幕(longPressGestureRecognizer)来使一个CALayer从屏幕左侧动画到右侧。当用户松开手指时,CALayer将暂停。
var l = CALayer()
var holdGesture = UILongPressGestureRecognizer()
let animation = CABasicAnimation(keyPath: "bounds.size.width")

override func viewDidLoad() {
    super.viewDidLoad()
    setUpView()
}

func setUpView(){
    l.frame = CGRect(x: 0, y: 0, width: 0, height: 10)
    l.backgroundColor = UIColor.redColor().CGColor

    self.view.addGestureRecognizer(holdGesture)
    holdGesture.addTarget(self, action:"handleLongPress:")
}

func handleLongPress(sender : UILongPressGestureRecognizer){

    if(sender.state == .Began) { //User is holding down on screen
        print("Long Press Began")
        animation.fromValue = 0
        animation.toValue = self.view.bounds.maxX * 2
        animation.duration = 30
        self.view.layer.addSublayer(l)
        l.addAnimation(animation, forKey: "bounds.size.width")
    }
    else { //User lifted Finger
        print("Long press ended")
        print("l width: \(l.bounds.size.width)")
        pauseLayer(l)
    }
}

func pauseLayer(layer : CALayer){
    var pausedTime : CFTimeInterval = layer.convertTime(CACurrentMediaTime(), fromLayer: nil)
    layer.speed = 0.0
    layer.timeOffset = pausedTime
}

我有两个问题:
  1. 当用户松开手指后,我打印 CALayer 的宽度时,它总是为0。我正在对宽度进行动画处理,并且它正在扩展,因此我不知道为什么它不会给我 CALayer 的新宽度。
  2. 当用户松开手指后再次按下时,CALayer 会消失。我需要它继续留在屏幕上并创建另一个 CALayer,我没有以任何方式删除它,因此我不明白它为什么还会消失。我检查了对象的内存,它仍然存在。

问题2的更新: 我相信要创建另一个 CALayer,我不能只添加图层。我必须复制或创建一个 UIView,然后将图层添加到其中。但我仍然不理解为什么它会消失。


1
在对图层进行动画处理之前,您应该先将目标边界设置为该图层。 - Shripada
谢谢您的回应!您具体指的是什么意思?您能回答这个问题吗? 有些人说我应该创建CALayer的副本。@Shripada - OriginalAlchemist
我已经尝试回答了,请查看-@originalAlchemist - Shripada
你太棒了!!看看我的评论! @Shripada - OriginalAlchemist
1个回答

7

基本上你正在尝试在用户按住时调整图层的大小。以下是可用于调整给定图层大小的函数:

如果你想将原点固定在左侧,你需要先设置图层的锚点:

layer.anchorPoint = CGPointMake(0.0, 1);

func resizeLayer(layer:CALayer, newSize: CGSize) {

    let oldBounds = layer.bounds;
    var newBounds = oldBounds;
    newBounds.size = size;


    //Ensure at the end of animation, you have proper bounds
    layer.bounds = newBounds

    let boundsAnimation = CABasicAnimation(keyPath: "bounds")
    positionAnimation.fromValue = NSValue(CGRect: oldBounds)
    positionAnimation.toValue = NSValue(CGRect: newBounds)
    positionAnimation.duration = 30
} 

在您的情况下,我不确定您在哪里恢复暂停的图层。此外,请注意每次用户点击时,在handleLongPress方法中都会添加新的动画!这将产生不必要的影响。理想情况下,您只需要在第一次启动动画时启动动画,之后只需恢复先前启动的已暂停动画即可。
//Flag that holds if the animation already started..
var animationStarted = false

func handleLongPress(sender : UILongPressGestureRecognizer){

  //User is holding down on screen
  if(sender.state == .Began){

    if(animationStarted == false){
      let targetBounds =  CalculateTargetBounds() //Implement this to your need
      resizeLayer(layer, targetBounds)
      animationStarted = true
    }else {
      resumeLayer(layer)
    }
  }else {
    pauseLayer(layer)
  }
}

太棒了!谢谢!唯一的问题是我想每次用户按住时创建一个新层。下一层的起点将从上一层离开的地方开始,看起来像一个连续的条形图,但实际上是多个相邻放置的条形图。我这样做的原因是因为我将它们存储到数组中,需要时可以删除它们。我需要跟踪每次按住和条形图的长度,然后在需要时删除它们(不用担心删除)。请帮忙! - OriginalAlchemist
你确定这段代码是正确的吗?你定义了一个名为resizeLayer的函数,它接受一个参数newSize,但你没有在函数内部使用它。相反,你引用了size,我不确定它是从哪里来的。如果因为你在UIView的子类中,那么即使如此,oldBoundsnewBounds始终会相等,因为你正在从旧的设置新的,然后从当前(即旧的)设置新的大小...或者我错过了什么? - Mark A. Donohoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接