【问题标题】:How to add gravity to UIViews in a UITableViewCell?如何在 UITableViewCell 中向 UIViews 添加重力?
【发布时间】:2021-09-02 17:17:52
【问题描述】:

我正在尝试通过重力作用来为一些 UIView 设置动画。理想情况下,每个视图都将保持在 UITableViewCell 边界内,并且它们会相互反弹,并且墙壁就像边界一样。但是,当我运行此代码时,UIView 只是在原地浮动,仅当另一个视图恰好填充在同一位置时才会移动。

class AnimateTableViewCell: UITableViewCell {
    
    private var animator: UIDynamicAnimator!
    private var gravity: UIGravityBehavior!
    private var collision: UICollisionBehavior!
    
    private var views = [UIView]()
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        animator = UIDynamicAnimator(referenceView: self.contentView)
        let items = [UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill")]
        
        for item in items {
            let size = Int.random(in: 75 ... 180)
            self.setUpView(view: UIView(frame: CGRect(x: 100, y: 100, width: size, height: size)), image: item!, size: size/2)
        }

    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func applyGravity(to item: UIView) {
        gravity = UIGravityBehavior(items: [item])
        animator.addBehavior(gravity)
        
        collision = UICollisionBehavior(items: views)
        collision.translatesReferenceBoundsIntoBoundary = true
        animator.addBehavior(collision)
        
        let bounce = UIDynamicItemBehavior(items: views)
        bounce.elasticity = 0.3
    }
    
    private func setUpView(view: UIView, image: UIImage, size: Int) {
        contentView.addSubview(view)
        view.backgroundColor = image.averageColor
        view.layer.cornerRadius = view.frame.height/2
        
        let imageView = UIImageView(image: image)
        imageView.contentMode = .scaleAspectFit
        
        view.addSubview(imageView)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            imageView.heightAnchor.constraint(equalToConstant: CGFloat(size)),
            imageView.widthAnchor.constraint(equalToConstant: CGFloat(size)),
            imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
        views.append(view)
        applyGravity(to: view)
    }
}

【问题讨论】:

  • @matt 我让tableview单元格尽可能简单,这可以在任何UITableViewController中调用

标签: ios swift xcode uiview gravity


【解决方案1】:

有两个主要问题。

首先,碰撞行为妨碍了您。注释掉这一行:

 animator.addBehavior(collision)

现在至少你会看到重力作用。

第二,你在说

    gravity = UIGravityBehavior(items: [item])
    animator.addBehavior(gravity)

多次,每个项目一次。那是错误的。您必须只有一个包含所有项目的重力行为。

仅通过重新排列您的一些代码并更改一些幻数,我得到了一个中等的结果;至少这应该可以帮助您入门(我使用了一个只有一个单元格的表格视图,高度很高):

class AnimateTableViewCell: UITableViewCell {
    
    private var animator: UIDynamicAnimator!
    private var gravity = UIGravityBehavior()
    private var collision = UICollisionBehavior()
    
    private var views = [UIView]()
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        animator = UIDynamicAnimator(referenceView: self.contentView)
        let items = [UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill"),UIImage(systemName: "star.fill")]
        for item in items {
            let size = Int.random(in: 20...40)
            self.setUpView(view: UIView(frame: CGRect(x: 100, y: 100, width: size, height: size)), image: item!, size: size)
        }
        animator.addBehavior(gravity)
        collision.translatesReferenceBoundsIntoBoundary = true
        animator.addBehavior(collision)
        let bounce = UIDynamicItemBehavior(items: views)
        bounce.elasticity = 0.3
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func applyGravity(to item: UIView) {
        gravity.addItem(item)
        collision.addItem(item)
    }
    
    private func setUpView(view: UIView, image: UIImage, size: Int) {
        contentView.addSubview(view)
        view.backgroundColor = .red
        view.layer.cornerRadius = view.frame.height/2
        
        let imageView = UIImageView(image: image)
        imageView.contentMode = .scaleAspectFit
        
        view.addSubview(imageView)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            imageView.heightAnchor.constraint(equalToConstant: CGFloat(size)),
            imageView.widthAnchor.constraint(equalToConstant: CGFloat(size)),
            imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
        views.append(view)
        applyGravity(to: view)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多