使用UIAttachmentBehavior拖动视图

我想拖动一个UIView,并让它移动附加到其他视图的位置,就好像它们都是通过string连接的。 开始状态将是一堆UIViews聚集在一起。 如果将其中一个拉出来,一旦它与被拖动的视图之间达到最小距离,它所连接的物品就会开始移动。 我在想,最好的方法是使用UIDynamicItemBehavior,因为我需要将它重新设置到位,并将重量应用于它。 我不太清楚如何做到这一点,而不做荒谬的代码,否则。 我所拥有的代码可以在下面看到。 不幸的是,我遇到的问题是将正方形项目拖回到square2。 任何人有任何build议,我会很乐意澄清,如果这是必要的。

- (void)viewDidLoad { [super viewDidLoad]; _containmentView = [[UIView alloc] initWithFrame:CGRectMake(0.0, self.view.frame.size.height/2, self.view.frame.size.width, 200)]; [self.view addSubview:_containmentView]; [_containmentView setBackgroundColor:[UIColor greenColor]]; _square = [[UIView alloc]initWithFrame:CGRectMake(200, 0, 100, 100)]; _square.backgroundColor = [UIColor yellowColor]; [_containmentView addSubview:_square]; _square2 = [[UIView alloc]initWithFrame:CGRectMake(100, 0, 100, 100)]; _square2.backgroundColor = [UIColor redColor]; [_containmentView addSubview:_square2]; _animator = [[UIDynamicAnimator alloc]initWithReferenceView:_containmentView]; _gravity = [[UIGravityBehavior alloc]initWithItems:@[_square, _square2]]; _gravity.gravityDirection = CGVectorMake(-1.0, 0.0); [_animator addBehavior:_gravity]; _collision = [[UICollisionBehavior alloc]initWithItems:@[_square]]; _collision.collisionDelegate = self; _collision.translatesReferenceBoundsIntoBoundary = YES; //causes the boundary to use the bounds of the reference view supplied to the UIDynamicAnimator [_animator addBehavior:_collision]; UIDynamicItemBehavior *itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:@[_square]]; itemBehaviour.elasticity = 0.6; [_animator addBehavior:itemBehaviour]; UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [_square addGestureRecognizer:gesture]; UIAttachmentBehavior *attach = [[UIAttachmentBehavior alloc] initWithItem:_square2 attachedToItem:_square]; [_animator addBehavior:attach]; } -(void)handlePan:(UIPanGestureRecognizer *)gesture { CGPoint touchPoint = [gesture locationInView:self.view]; UIView* draggedView = gesture.view; if (gesture.state == UIGestureRecognizerStateBegan) { // 1. was the pan initiated from the upper part of the recipe? UIView* draggedView = gesture.view; CGPoint dragStartLocation = [gesture locationInView:draggedView]; _draggingView = YES; _previousTouchPoint = touchPoint; // [_animator updateItemUsingCurrentState:draggedView]; } else if (gesture.state == UIGestureRecognizerStateChanged && _draggingView) { // 2. handle dragging float xOffset = _previousTouchPoint.x - touchPoint.x; gesture.view.center = CGPointMake(draggedView.center.x - xOffset, draggedView.center.y); _previousTouchPoint = touchPoint; // [_animator updateItemUsingCurrentState:draggedView]; } else if (gesture.state == UIGestureRecognizerStateEnded && _draggingView) { // 3. the gesture has ended // [self tryDockView:draggedView]; // [self addVelocityToView:draggedView fromGesture:gesture]; [_animator updateItemUsingCurrentState:draggedView]; _draggingView = NO; } } 

你需要使用附件来拖动你的形状,所以animation师可以使用物理引擎计算每个物品的位置。

这里是你viewDidLoad更新:

 - (void)viewDidLoad { [super viewDidLoad]; _containmentView = [[UIView alloc] initWithFrame:CGRectMake(0.0, self.view.frame.size.height/2, self.view.frame.size.width, 200)]; [self.view addSubview:_containmentView]; [_containmentView setBackgroundColor:[UIColor greenColor]]; _square = [[UIView alloc]initWithFrame:CGRectMake(200, 0, 100, 100)]; _square.backgroundColor = [UIColor yellowColor]; [_containmentView addSubview:_square]; _square2 = [[UIView alloc]initWithFrame:CGRectMake(100, 0, 100, 100)]; _square2.backgroundColor = [UIColor redColor]; [_containmentView addSubview:_square2]; _animator = [[UIDynamicAnimator alloc]initWithReferenceView:_containmentView]; _gravity = [[UIGravityBehavior alloc]initWithItems:@[_square, _square2]]; _gravity.gravityDirection = CGVectorMake(-1.0, 0.0); [_animator addBehavior:_gravity]; _collision = [[UICollisionBehavior alloc]initWithItems:@[_square, _square2]]; _collision.translatesReferenceBoundsIntoBoundary = YES; [_animator addBehavior:_collision]; UIDynamicItemBehavior *itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:@[_square, _square2]]; itemBehaviour.elasticity = 0.6; [_animator addBehavior:itemBehaviour]; UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [_square addGestureRecognizer:gesture]; UIPanGestureRecognizer *gesture2 = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [_square2 addGestureRecognizer:gesture2]; UIAttachmentBehavior *attach = [[UIAttachmentBehavior alloc] initWithItem:_square2 attachedToItem:_square]; attach.damping = 1.6; attach.frequency = 10; [_animator addBehavior:attach]; } 

我在两个形状上添加了重力,平移和碰撞。

这里应该看看你的handlePan方法:

 -(void)handlePan:(UIPanGestureRecognizer *)gesture { CGPoint touchPoint = [gesture locationInView:_containmentView]; UIView* draggedView = gesture.view; if (gesture.state == UIGestureRecognizerStateBegan) { // 1. was the pan initiated from the upper part of the recipe? _draggingView = YES; _previousTouchPoint = touchPoint; // Add a new attachment on the selected view; self.attachment = [[UIAttachmentBehavior alloc] initWithItem:draggedView attachedToAnchor:touchPoint]; [self.animator addBehavior:self.attachment]; // Could temporarily remove gravity here } else if (gesture.state == UIGestureRecognizerStateChanged && _draggingView) { // 2. handle dragging [self.attachment setAnchorPoint:touchPoint]; } else if (gesture.state == UIGestureRecognizerStateEnded && _draggingView) { // 3. the gesture has ended _draggingView = NO; [self.animator removeBehavior:self.attachment]; // If gravity was removed, add it back here } } 

拖动时,您可能需要暂时移除重力。 只要看看我的意见,看看你可以做到这一点(不要忘记把它拖回拖动结束时)。

正如你所看到的,你真的需要更less的代码来处理手势:)。

你可以玩附件的阻尼,频率和长度,使形状反应不同的拖动手势。 您还可以使用UIDynamicItemBehavior的density属性将密度添加到您的形状。