2015-01-15 16 views
15

Là một phần của việc triển khai UICollisionBehaviour tôi thiết lập các ranh giới cho cạnh màn hình. Sau đó tôi đã thêm một số khung nhìn và cuối cùng đính kèm một UIPanGestureRecognizer vào một trong số chúng.UICollisionBehavior - lượt xem vượt qua các ranh giới

Bây giờ tôi có thể đẩy xung quanh các chế độ xem nhỏ hơn bằng chế độ xem có thể kéo của tôi.

Hammer-time!

Vấn đề: Nếu tôi dồn một cái nhìn nhỏ hơn và tiếp tục đẩy nó chống lại các cạnh màn hình, nó sẽ cuối cùng trượt qua ranh giới và bị mắc kẹt ở phía bên kia. "Cái nhìn búa" của tôi mà tôi sử dụng để đánh và đẩy các khung cảnh khác xung quanh cũng sẽ bị kẹt trong ranh giới. I E. nó bị kẹt/không thể kéo được ở phía bên của màn hình.

Tôi đã làm một ví dụ rất nhỏ để xem liệu tôi có thể tái tạo nó khi tôi có rất ít lượt xem và không có hành vi xung đột, lượt xem vẫn đi qua ranh giới. Hoặc UIDynamics không thể xử lý rất nhiều, hoặc (nhiều khả năng) tôi bằng cách nào đó cấu hình nó sai.

Các ví dụ nhỏ dưới đây có hành vi kỳ lạ:

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. 
} 

}

Nhờ sự giúp đỡ nhất định.

+2

Thêm một thẻ Swift để giúp câu hỏi của bạn để được nhìn thấy. – iOSAaronDavid

+2

Tôi cũng thấy điều này xảy ra. Có vẻ như khi một lượt xem bị áp lực qua một biên giới, nó gần như tạo thành một lỗ mà qua đó các khung nhìn khác có thể đi qua. Tò mò để nghe bất kỳ câu trả lời nào. – Warpling

Trả lời

4

Tin vui: bạn không làm gì sai. Tin xấu: đây là hành vi mong đợi. Búa của bạn đang đẩy tầm nhìn vào các ranh giới tham chiếu cho đến khi nó cuối cùng phá vỡ bởi vì vật lý của mô hình của bạn nói rằng đó là những gì nó nên làm. Ranh giới tham chiếu không phải là ranh giới không thể vượt qua được, nó chỉ xác định một khu vực nơi quy tắc vật lý của bạn áp dụng nhất quán.

này là không thực sự ghi nhận, nhưng trang cho UICollisionBehavior khẳng định:

Khi cài đặt vị trí ban đầu cho một mục năng động, bạn phải đảm bảo rằng giới hạn của nó không giao nhau bất kỳ ranh giới va chạm. Hành vi hoạt ảnh cho một mục không đúng chỗ như vậy là không xác định.

Điều này chỉ đúng một phần, trong trường hợp của bạn (như với tôi) nếu một mục nằm ngoài ranh giới sau khi khởi tạo, hành vi của nó cũng không xác định.

Tôi đã cố sắp xếp một bộ bóng ở bên phải của chế độ xem. Có một điểm neo dưới quả bóng ngoài cùng bên phải. Chế độ xem màu vàng là chế độ xem tham chiếu và mọi thứ đều bắt đầu tốt ... this works

Nhưng khi tôi thêm nhiều quả bóng hơn vào thời điểm chúng không còn phù hợp nữa, chúng sẽ bắt đầu xuất hiện. Trên thực tế, hình ảnh ở trên cùng bên phải của hình ảnh xuất hiện ở giữa phía dưới và cuộn xung quanh mặt đối chiếu xem theo chiều kim đồng hồ để gần điểm neo. this is broken

UPDATE: Đối với một giải pháp bạn có thể đặt collisionDelegate của collisionBehaviors của bạn và nắm bắt được bắt đầu và kết thúc của những va chạm và sau đó di chuyển tầm nhìn của bạn trở lại vào ranh giới và xa búa của bạn để làm cho nó trông giống như họ đã trốn thoát.

Như bạn đã tìm ra bản dịchReferenceBoundsIntoBoundary tương đương với tập hợp các cuộc gọi addBoundaryWithIdentifier.

Sử dụng:

collisionBehaviour!.translatesReferenceBoundsIntoBoundary = true 

giống như:

//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

Cảm ơn bạn vì những hiểu biết, tôi sẽ xem lại bản demo nhỏ của tôi để xem liệu tôi có thể buộc các quả bóng bên trong ranh giới một lần nữa, mà không có vẻ lạ. – RickiG

Các vấn đề liên quan