【问题标题】:Swift : Animate CALayer斯威夫特:动画CALayer
【发布时间】:2016-01-11 01:50:56
【问题描述】:

在下面的代码中,我试图在用户按住屏幕时将CALayer 从屏幕左侧动画化到屏幕右侧(longPressGestureRecognizer)。当用户抬起手指时,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。我仍然不明白为什么它会消失。

【问题讨论】:

  • 您应该在设置动画之前将目标绑定到图层。
  • 感谢您的回复!你到底什么意思?你能回答这个问题吗?有人说我应该创建 CALayer 的副本。 @Shripada
  • 我已经试着回答了,看看-@originalAlchemist
  • 你太棒了!!看看我的评论! @Shripada

标签: ios swift animation calayer uilongpressgesturerecogni


【解决方案1】:

基本上,当用户按住时,您会尝试调整图层的大小。这是一个可用于调整给定层大小的函数:

如果你想把原点钉在左边,你需要先设置图层的锚点:

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)
  }
}

【讨论】:

  • 这太棒了!谢谢!唯一的事情是我想在每次用户按住时创建一个新层。下一层的原点将从上一层停止的地方开始,它看起来像一个连续的条,但它实际上是多个并排放置的。我这样做的原因是因为我将它们存储到一个数组中,并且可以在需要时删除它们。我需要跟踪每次按住以及该栏的时间长度,然后在需要时将其删除(尽管不要担心删除)。请帮助!!
  • 你确定这段代码是对的吗?你定义了一个函数resizeLayer,它接受一个参数newSize,但你没有在里面使用它。相反,您引用的是size,我不确定它来自哪里。如果是因为您在 UIView 的子类中,那么即使如此,oldBoundsnewBounds 将始终相等,因为您从旧设置新大小,然后从当前设置新大小(即旧大小)。 ) ...还是我错过了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 2017-07-22
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
  • 2017-11-13
相关资源
最近更新 更多