Dragging views using UIAttachmentBehavior

为君一笑 提交于 2019-12-03 17:10:27

You need to use an attachment to drag your shape, so the animator can calculate every items positions using its physic engine.

Here is you viewDidLoad updated:

- (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];

}

I added gravity, pan & collisions to both shapes.

Here what should look your handlePan method:

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

You may want to remove gravity temporarily while dragging. Just take a look at my comments to see where you could do it (and don't forget to put it back when the dragging's end).

As you can see, you really need less coding to handle gesture that way :).

You can play with both attachment's damping, frequency and length to make shapes react differently to the drag gesture. You can also add a density to your shapes using the UIDynamicItemBehavior's density property.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!