[英]How to attach multiple UIDynamicItems to each other
I am trying to implement circles attached to each other like in Apple's Music App via UIDynamicAnimator
. 我正在尝试通过
UIDynamicAnimator
实现彼此相连的圈子,例如在Apple的Music App中。 I need to attach circles to each other and to view center. 我需要将圆圈彼此连接并查看中心。 I was trying to implement this via
UIAttachmentBehavior
, but seems to it's not supporting multiple attachments. 我试图通过
UIAttachmentBehavior
实现此UIAttachmentBehavior
,但似乎不支持多个附件。 In result, circles overlaps on each other :) 结果,圆圈彼此重叠:)
let attachment = UIAttachmentBehavior(item: circle, attachedToAnchor: CGPoint(x: view.center.x, y: view.center.y))
attachment.length = 10
animator?.addBehavior(attachment)
let push = UIPushBehavior(items: [circle], mode: .continuous)
collision.addItem(circle)
animator?.addBehavior(push)
What I am doing wrong? 我做错了什么?
I don't think the apple music genre picker thing uses UIAttachmentBehavior
which is closer to attaching two views with a pole or a rope. 我不认为苹果音乐类型选择器使用
UIAttachmentBehavior
,它更接近于用一根杆子或一根绳子附加两个视图。 But, it seems like the problem you're experiencing might be that all of the views are added at the same location which has the effect of placing them on top of each other and with the collision behavior causes them to be essentially be stuck together. 但是,似乎您遇到的问题可能是所有视图都添加到了同一位置,从而将它们放置在彼此的顶部,并且碰撞行为导致它们本质上被粘在一起。 One thing to do is to turn on
UIDynamicAnimator
debugging by calling animator.setValue(true, forKey: "debugEnabled")
. 一件事是通过调用
animator.setValue(true, forKey: "debugEnabled")
来打开UIDynamicAnimator
调试。
For recreating the above circle picker design, I would look into using UIFieldBehavior.springField()
. 为了重新创建上面的圆形选择器设计,我将研究使用
UIFieldBehavior.springField()
。
For example: 例如:
class ViewController: UIViewController {
lazy var animator: UIDynamicAnimator = {
let animator = UIDynamicAnimator(referenceView: view)
return animator
}()
lazy var collision: UICollisionBehavior = {
let collision = UICollisionBehavior()
collision.collisionMode = .items
return collision
}()
lazy var behavior: UIDynamicItemBehavior = {
let behavior = UIDynamicItemBehavior()
behavior.allowsRotation = false
behavior.elasticity = 0.5
behavior.resistance = 5.0
behavior.density = 0.01
return behavior
}()
lazy var gravity: UIFieldBehavior = {
let gravity = UIFieldBehavior.springField()
gravity.strength = 0.008
return gravity
}()
lazy var panGesture: UIPanGestureRecognizer = {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.didPan(_:)))
return panGesture
}()
var snaps = [UISnapBehavior]()
var circles = [CircleView]()
override func viewDidLoad() {
super.viewDidLoad()
view.addGestureRecognizer(panGesture)
animator.setValue(true, forKey: "debugEnabled")
addCircles()
addBehaviors()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
gravity.position = view.center
snaps.forEach {
$0.snapPoint = view.center
}
}
func addCircles() {
(1...30).forEach { index in
let xIndex = index % 2
let yIndex: Int = index / 3
let circle = CircleView(frame: CGRect(origin: CGPoint(x: xIndex == 0 ? CGFloat.random(in: (-300.0 ... -100)) : CGFloat.random(in: (500 ... 800)), y: CGFloat(yIndex) * 200.0), size: CGSize(width: 100, height: 100)))
circle.backgroundColor = .red
circle.text = "\(index)"
circle.textAlignment = .center
view.addSubview(circle)
gravity.addItem(circle)
collision.addItem(circle)
behavior.addItem(circle)
circles.append(circle)
}
}
func addBehaviors() {
animator.addBehavior(collision)
animator.addBehavior(behavior)
animator.addBehavior(gravity)
}
@objc
private func didPan(_ sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: sender.view)
switch sender.state {
case .began:
animator.removeAllBehaviors()
fallthrough
case .changed:
circles.forEach { $0.center = CGPoint(x: $0.center.x + translation.x, y: $0.center.y + translation.y)}
case .possible, .cancelled, .failed:
break
case .ended:
circles.forEach { $0.center = CGPoint(x: $0.center.x + translation.x, y: $0.center.y + translation.y)}
addBehaviors()
@unknown default:
break
}
sender.setTranslation(.zero, in: sender.view)
}
}
final class CircleView: UILabel {
override var collisionBoundsType: UIDynamicItemCollisionBoundsType {
return .ellipse
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.height * 0.5
layer.masksToBounds = true
}
}
For more information I would watch What's New in UIKit Dynamics and Visual Effects from WWDC 2015 有关更多信息,我将观看WWDC 2015的UIKit Dynamics和Visual Effects中的新增功能
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.