Ios 使用UIAttachmentBehavior拖动视图

Ios 使用UIAttachmentBehavior拖动视图,ios,objective-c,uikit-dynamics,uidynamicbehavior,Ios,Objective C,Uikit Dynamics,Uidynamicbehavior,我想拖动一个UIView,让它移动附加到它的其他视图的位置,就像它们都是通过字符串附加的一样。开始状态将是一群聚集在一起的UIView。如果拉出一个,则它所附着的项目将在它与要拖动的视图之间达到最小距离后开始移动。我认为实现这一点的最佳方法是使用UIDynamicEmbehavior,因为我需要它重新就位并施加重量。我不太确定如何在不执行荒谬代码的情况下实现这一点。下面是我的代码。不幸的是,我遇到了将方形项拖回square2的问题。如果有人有什么建议,我很乐意澄清是否需要 - (void)vie

我想拖动一个UIView,让它移动附加到它的其他视图的位置,就像它们都是通过字符串附加的一样。开始状态将是一群聚集在一起的UIView。如果拉出一个,则它所附着的项目将在它与要拖动的视图之间达到最小距离后开始移动。我认为实现这一点的最佳方法是使用UIDynamicEmbehavior,因为我需要它重新就位并施加重量。我不太确定如何在不执行荒谬代码的情况下实现这一点。下面是我的代码。不幸的是,我遇到了将方形项拖回square2的问题。如果有人有什么建议,我很乐意澄清是否需要

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

}

您需要使用附件来拖动形状,以便动画师可以使用其physic引擎计算每个项目的位置

以下是您的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
    }
}
拖动时,可能需要临时移除重力。只要看看我的评论,看看你可以在哪里做(不要忘了在拖拉结束时把它放回去)

正如您所看到的,您确实需要更少的编码来处理这样的手势:)


您可以同时使用附件的阻尼、频率和长度,以使形状对拖动手势做出不同的反应。您还可以使用UIDynamicEmbehavior的
density
属性将密度添加到形状中。

我还需要进一步使用它,这不是我想要的行为。我确实需要这些正方形相互重叠。当它们被拉出时,它们应该弹回到彼此重叠的位置。我们如何才能使其仅在一个轴上拖动,即仅垂直平移?@Mrug而不是将锚点设置为
接触点
,只使用其
y
值,并根据您的喜好设置
x
,即
[self.attachment setAnchorPoint:CGPointMake(draggedView.center.x,touchPoint.y)];