简体   繁体   English

如何将多个UIDynamicItem彼此附加

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM