简体   繁体   English

在 Swift 中移动一个对象 (UIView) 并且已经设置了重力/碰撞/弹性

[英]Moving an object (UIView) in Swift with gravity/collision/elasticity already setup

I would like to create a square in swift that starts at the top of the screen and fall down to the bottom of the screen and stay there.我想快速创建一个从屏幕顶部开始并落到屏幕底部并停留在那里的正方形。 I also would like to be able to drag it with my finger toward the top and make it fall toward the bottom of the screen again.我还希望能够用我的手指将它拖向顶部并使其再次落向屏幕底部。 Any tips on how to do that?关于如何做到这一点的任何提示?

I was able to create a square that falls toward the bottom of the screen already.我已经能够创建一个落在屏幕底部的正方形。 I was also able to move it with my finger as well.我也可以用手指移动它。 But the problem is, whenever I move it, the square just stay in the same place.但问题是,每当我移动它时,方块就停留在同一个地方。 Gravity/collision/elasticity don't seem to work after I move it.我移动它后,重力/碰撞/弹性似乎不起作用。 I want it to fall after I lift my finger off the square.我希望我的手指离开方块后它会掉下来。 See below for an excerpt of my code.请参阅下面的我的代码的摘录。 There is probably something simple that I miss.可能有一些简单的东西我想念。 Any tips would be appreciated.任何提示将不胜感激。

import UIKit

class ViewController: UIViewController {

  var greenSquare: UIView?
  var redSquare:UIView?
  var animator: UIDynamicAnimator?

  override func viewDidLoad() {
    super.viewDidLoad()
    createFallingObject()

    func createFallingObject() {

     //remove square from superview
     redSquare?.removeFromSuperview()

     //create the shape
     var dimen = CGRect(x: 130,y: 25,width: 90,height: 90)
     redSquare = UIView(frame: dimen)
     redSquare?.backgroundColor = UIColor.red

     //then add to the screen
     self.view.addSubview(redSquare!)

     //Initialize the animator
     animator = UIDynamicAnimator(referenceView: self.view)

     //Add gravity to the squares
     let gravity = UIGravityBehavior(items: [redSquare!])
     let direction = CGVector(dx: 0.0, dy: 0.05)
     gravity.gravityDirection = direction

     //Collision
     let boundaries = UICollisionBehavior(items: [redSquare!])
     boundaries.translatesReferenceBoundsIntoBoundary = true

     //Elasticity
     let bounce = UIDynamicItemBehavior(items: [redSquare!])
     bounce.elasticity = 0.3



     // 1. create a gesture recognizer (tap gesture)
     let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))


     //add pan gesture Regcognizer to the red square
     let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
     redSquare?.addGestureRecognizer(panGestureRecognizer)


     animator?.addBehavior(boundaries)
     animator?.addBehavior(bounce)
     animator?.addBehavior(gravity)
    }

    //this method handle pan
    func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
     if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {

        let translation = gestureRecognizer.translation(in: self.view)
        // note: 'view' is optional and need to be unwrapped
        gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
        gestureRecognizer.setTranslation(CGPoint.zero, in: self.view)

        //redSquare?.frame.origin.x = translation.x
        //redSquare?.frame.origin.y = translation.y
     }
   }

   // 3. this method is called when a tap is recognized
   func handleTap(sender: UITapGestureRecognizer) {
    createFallingObject()
   }
}

You should remove the item from the UIDynamicAnimator when the pan gesture begin and add it back when it ends.您应该在平移手势开始时从UIDynamicAnimator删除该项目,并在它结束时将其添加回来。

When a view is added to a dynamic animator its position should be determine by the animator and the animator alone.当一个视图被添加到动态动画师时,它的位置应该由动画师和动画师单独确定。 Removing the item from the animator will allow the view to position normally using its frame.从动画师中删除项目将允许视图使用其框架正常定位。 Adding it back to the animator will cause the animator to resume positioning it from its current state.将它添加回动画师将导致动画师从当前状态恢复定位。

Alternatively, if you need to the update the position of an item manually (ie not based on the physics of the animator), you should call animator.updateItem(usingCurrentState: myDynamicItem) , where myDynamicItem is the item you want to update.或者,如果您需要手动更新项目的位置(即不基于动画师的物理特性),您应该调用animator.updateItem(usingCurrentState: myDynamicItem) ,其中myDynamicItem是您要更新的项目。

thanks beyowulf.谢谢贝优武夫。 animator?.removeAllBehavior() did the trick in the pan gesture routine animator?.removeAllBehavior() 在平移手势例程中发挥了作用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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