2015-01-15 7 views
15

UICollisionBehaviour 구현의 일환으로 화면 가장자리의 경계를 설정합니다. 그런 다음 일부보기를 추가하고 마지막으로 UIPanGestureRecognizer를 그 중 하나에 연결했습니다.UICollisionBehavior - 경계를 통과하는 뷰

이제 드래그 할 수있는보기로 더 작은 뷰를 밀 수 있습니다.

Hammer-time!

문제 : 작은 볼을 코너와 화면 가장자리에 밀어 유지하는 경우이 , 그것은 경계를지나 미끄러 결국하고 반대편에 갇혀 얻을. 내가 쳐다보고 다른 뷰를 밀어 붙이는 데 사용하는 내 "해머 뷰"도 경계에 걸릴 것입니다. 나는. 그것은 화면의 측면에 붙어/un-draggable.

아주 작은 예제를 사용하여보기가 거의없고 충돌하는 동작이 없을 때 재생할 수 있는지,보기가 여전히 경계를 통과하는지 확인할 수있었습니다. 어느 쪽이든 UIDynamics는 대단히 다루지 못하거나, (어쩌면) 내가 어떻게 든 잘못 구성하고있다. 주어진 어떤 도움

class ViewController: UIViewController { 

var animator: UIDynamicAnimator? 
var collisionBehaviour: UICollisionBehavior? 
var panBehaviour: UIAttachmentBehavior? 

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

override func viewWillAppear(animated: Bool) { 
    super.viewWillAppear(animated) 
    setup() 
} 

func setup() { 
    //setup collisionBehaviour and animator 
    collisionBehaviour = UICollisionBehavior() 
    collisionBehaviour!.collisionMode = UICollisionBehaviorMode.allZeros 
    animator = UIDynamicAnimator(referenceView: view) 

    //add boundaries 
    collisionBehaviour!.addBoundaryWithIdentifier("verticalMin", fromPoint: CGPointMake(0, 0), toPoint: CGPointMake(0, CGRectGetHeight(view.frame))) 
    collisionBehaviour!.addBoundaryWithIdentifier("verticalMax", fromPoint: CGPointMake(CGRectGetMaxX(view.frame), 0), toPoint: CGPointMake(CGRectGetMaxX(view.frame), CGRectGetHeight(view.frame))) 
    collisionBehaviour!.addBoundaryWithIdentifier("horizontalMin", fromPoint: CGPointMake(0, CGRectGetMaxY(view.frame)), toPoint: CGPointMake(CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))) 
    collisionBehaviour!.addBoundaryWithIdentifier("horizontalMax", fromPoint: CGPointMake(0, 0), toPoint: CGPointMake(CGRectGetMaxX(view.frame), 0)) 

    //  collisionBehaviour!.translatesReferenceBoundsIntoBoundary = true // same effect as the above boundaries 
    //setup up some round views to push around 
    for i in 0..<5 { 
     let ball = UIView(frame: CGRectMake(0, 30, 50, 50)) 
     ball.center = view.center 
     ball.backgroundColor = UIColor.greenColor() 
     ball.layer.cornerRadius = CGRectGetWidth(ball.frame) * 0.5 
     view.addSubview(ball) 
     collisionBehaviour!.addItem(ball) 
    } 

    //setup a hammer view which can be dragged and used to squeze the ball views of the screen 
    let hammer = UIView(frame: CGRectMake(0, 0, 100, 100)) 
    hammer.backgroundColor = UIColor.redColor() 
    view.addSubview(hammer) 
    collisionBehaviour!.addItem(hammer) 

    let noRotationBehaviour = UIDynamicItemBehavior(items: [hammer]) 
    noRotationBehaviour.allowsRotation = false 
    animator!.addBehavior(noRotationBehaviour) 

    let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: Selector("handlePan:")) 
    hammer.addGestureRecognizer(panGestureRecognizer) 

    //"start" the collision detection 
    animator!.addBehavior(collisionBehaviour!) 
} 

//Move the hammer around 
func handlePan(recognizer: UIPanGestureRecognizer) { 
    if let view = recognizer.view { 
     let location = recognizer.locationInView(self.view) 
     switch recognizer.state { 
     case .Began: 
      panBehaviour = UIAttachmentBehavior(item: view, attachedToAnchor: location) 
      animator!.addBehavior(panBehaviour!) 
      println("begin") 
     case .Changed: 
      panBehaviour!.anchorPoint = location 
      println("change \(location)") 
     case .Ended: 
      println("ended") 
      animator!.removeBehavior(panBehaviour!) 
     default: 
      println("done") 
     } 
    } 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 

}

감사 :

작은 예는 아래의 이상한 행동을 가지고있다.

+2

질문을하는 데 도움이되는 스위프트 태그 추가를 볼 수 있습니다. – iOSAaronDavid

+2

나는 또한 이것을 보았다. 보기가 경계를 통해 가압 될 때 다른보기가 통과 할 수있는 구멍을 거의 형성하는 것처럼 보입니다. 호기심이 어떤 대답을 듣고. – Warpling

답변

4

좋은 소식 : 당신은 아무 잘못도하지 않습니다. 나쁜 소식 : 이것은 예상되는 행동입니다. 모델의 물리학이 그것이해야하는 일이기 때문에 망치가 마침내 깨질 때까지 망치가 기준 경계선에 대해보기를 밀고 있습니다. 참조 경계는 교차 할 수없는 경계가 아니며 물리 규칙이 일관되게 적용되는 영역 만 정의합니다.

이 정말 문서화되지 않지만 UICollisionBehavior의 페이지 상태 :

동적 항목에 대한 초기 위치를 설정, 당신은 그 경계가 어떤 충돌 경계를 교차하지 않는 를 확인해야합니다. 이러한 잘못 배치 된 항목에 대한 애니메이션 동작은 정의되지 않습니다.

항목을 초기화 한 후 경계 외부에가는 경우는 행동도 정의되지이다, (광산에서와 같이) 귀하의 경우, 부분적으로 만 사실이다.

나는보기의 오른쪽에 공 세트를 정렬하려고 시도했다. 맨 오른쪽 공 밑에 앵커 포인트가 있습니다. 노란색보기가 참조보기이며 모든 것이 잘 시작됩니다. 그러나 나는 더 이상 볼을 넣지 않아 더 이상 맞지 않아 튀어 나오기 시작할 것입니다. 실제로, 이미지의 오른쪽 상단에있는 것이 하단 중앙에서 튀어 나오고 기준 뷰를 중심으로 시계 반대 방향으로 굴러 앵커 포인트 근처에 있습니다. this is broken

UPDATE : 솔루션 당신이 당신의 collisionBehaviors의 collisionDelegate을 설정하고 시작과 충돌의 끝을 캡처 한 다음 모양을 만들기 위해 다시 경계에 멀리 망치에서보기를 이동할 수 있습니다에 대한 그들은 도망 쳤다.

translatesReferenceBoundsIntoBoundary는 addBoundaryWithIdentifier 호출 집합과 같습니다.

사용 :

collisionBehaviour!.translatesReferenceBoundsIntoBoundary = true 

동일하게 :

//add boundaries 
    collisionBehaviour!.addBoundaryWithIdentifier("verticalMin", fromPoint: CGPointMake(0, 0), toPoint: CGPointMake(0, CGRectGetHeight(view.frame))) 
    collisionBehaviour!.addBoundaryWithIdentifier("verticalMax", fromPoint: CGPointMake(CGRectGetMaxX(view.frame), 0), toPoint: CGPointMake(CGRectGetMaxX(view.frame), CGRectGetHeight(view.frame))) 
    collisionBehaviour!.addBoundaryWithIdentifier("horizontalMin", fromPoint: CGPointMake(0, CGRectGetMaxY(view.frame)), toPoint: CGPointMake(CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))) 
    collisionBehaviour!.addBoundaryWithIdentifier("horizontalMax", fromPoint: CGPointMake(0, 0), toPoint: CGPointMake(CGRectGetMaxX(view.frame), 0)) 
+0

통찰력을 가져 주셔서 감사합니다. 나는 작은 데모를 다시 방문하여 경계 안쪽으로 공을 강제로 넣을 수 있는지 알아볼 것입니다. – RickiG