斯威夫特:我超级困惑! UILabel 上的 UIGravityBehavior vs NSTimer vs CGPointMake
Swift: I'm super confused! UIGravityBehavior vs NSTimer vs CGPointMake on UILabel
所以我声明了一个 UILabel!名为 "textLabel" 的重力效果会上升。现在,当它达到 -30 时,我希望标签重新出现在 (200, 444) 处。我使用 NSTimer 来检查 if (labelText > -30) 但是当它 reaches/passes 那一点时,它只是在它应该出现的地方(在中间附近)闪烁,但它不是从中间开始的。这是我的大部分代码。
如何让标签出现在它的新位置?所以它可以在达到 y 轴上的 -30 后再次循环?我找了又找。 HELPPPPPPP
@IBOutlet weak var textLabel: UILabel!
var gravity: UIGravityBehavior!
var animator: UIDynamicAnimator!
var itemBehavior: UIDynamicItemBehavior!
var boundaryTimer = NSTimer()
Override func viewDidLoad() {
animator = UIDynamicAnimator(referenceView: view)
gravity = UIGravityBehavior(items: [textLabel])
animator.addBehavior(gravity)
boundaryTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "leftBoundary", userInfo: nil, repeats: true)
itemBehavior = UIDynamicItemBehavior(items: [textLabel])
itemBehavior.elasticity = 1.2
gravity.gravityDirection = CGVectorMake(0.0 , -0.01)
animator.addBehavior(itemBehavior)
}
func leftBoundary() {
if textLabel.center.y < 40 {
self.textLabel.center = CGPointMake(200, 444)
}
}
您应该首先从动画师中删除所有标签行为。
这与 UIKit Dynamics 的工作方式有关。它实际上只操纵视图的层/表示层,因此如果您想自己设置位置(通过视图,这也会影响层),则需要重置所有内容。
另外,我觉得定时器的设置效率不高。相反,您应该尝试 KVO(键值观察)。您可以观察关键路径 "center.y" 并在它超过您的限制时做出反应。
您可以添加然后删除附件行为,而不是设置 center
,例如:
func leftBoundary() {
if textLabel.center.y < 40 {
let attachment = UIAttachmentBehavior(item: textLabel, attachedToAnchor: textLabel.center)
animator.addBehavior(attachment)
attachment.anchorPoint = view.center
attachment.action = {[unowned self, attachment] in
if self.textLabel.center.y > 100 {
self.animator.removeBehavior(attachment)
}
}
}
}
请注意,您可能想要更改 itemBehavior
,以便 allowRotation
为 false
(取决于您想要的 UI)。
另请注意,我在这里使用的这个 action
也可以用于您的 gravity
行为。因此,与其使用计时器(它可能不会总是同时捕获标签),不如使用 action
,它会在动画的每一帧上调用。
所以我声明了一个 UILabel!名为 "textLabel" 的重力效果会上升。现在,当它达到 -30 时,我希望标签重新出现在 (200, 444) 处。我使用 NSTimer 来检查 if (labelText > -30) 但是当它 reaches/passes 那一点时,它只是在它应该出现的地方(在中间附近)闪烁,但它不是从中间开始的。这是我的大部分代码。
如何让标签出现在它的新位置?所以它可以在达到 y 轴上的 -30 后再次循环?我找了又找。 HELPPPPPPP
@IBOutlet weak var textLabel: UILabel!
var gravity: UIGravityBehavior!
var animator: UIDynamicAnimator!
var itemBehavior: UIDynamicItemBehavior!
var boundaryTimer = NSTimer()
Override func viewDidLoad() {
animator = UIDynamicAnimator(referenceView: view)
gravity = UIGravityBehavior(items: [textLabel])
animator.addBehavior(gravity)
boundaryTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "leftBoundary", userInfo: nil, repeats: true)
itemBehavior = UIDynamicItemBehavior(items: [textLabel])
itemBehavior.elasticity = 1.2
gravity.gravityDirection = CGVectorMake(0.0 , -0.01)
animator.addBehavior(itemBehavior)
}
func leftBoundary() {
if textLabel.center.y < 40 {
self.textLabel.center = CGPointMake(200, 444)
}
}
您应该首先从动画师中删除所有标签行为。
这与 UIKit Dynamics 的工作方式有关。它实际上只操纵视图的层/表示层,因此如果您想自己设置位置(通过视图,这也会影响层),则需要重置所有内容。
另外,我觉得定时器的设置效率不高。相反,您应该尝试 KVO(键值观察)。您可以观察关键路径 "center.y" 并在它超过您的限制时做出反应。
您可以添加然后删除附件行为,而不是设置 center
,例如:
func leftBoundary() {
if textLabel.center.y < 40 {
let attachment = UIAttachmentBehavior(item: textLabel, attachedToAnchor: textLabel.center)
animator.addBehavior(attachment)
attachment.anchorPoint = view.center
attachment.action = {[unowned self, attachment] in
if self.textLabel.center.y > 100 {
self.animator.removeBehavior(attachment)
}
}
}
}
请注意,您可能想要更改 itemBehavior
,以便 allowRotation
为 false
(取决于您想要的 UI)。
另请注意,我在这里使用的这个 action
也可以用于您的 gravity
行为。因此,与其使用计时器(它可能不会总是同时捕获标签),不如使用 action
,它会在动画的每一帧上调用。