iPhone/iOS: How to implement Drag and Drop for sub

2019-01-18 05:35发布

I am having an horizontal scrollview in an UIViewController, where i have many images in small sizes. I am keeping the images in scrollview because the images are more, so user can scroll horizontally and choose images. But, the problem is, i have to select an image and drag and drop to that UIViewController view. But, since the images are in scrollview, drag and drop images into UIViewcontroller's view is not working, not detecting the touch events too. Please NOTE: If i don't have scrollview but just keeping the images also into UIViewcontroller's view itself, drag and drop the images on the same screen, is working very well.

How can I resolve this when I need to have scrollview and drag and drop images, any advice/help please?

5条回答
姐就是有狂的资本
2楼-- · 2019-01-18 05:45

Getsy,

Try the code for drag and drop the objects :

-(void)dragAndDropWithGesture {

UILongPressGestureRecognizer *downwardGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(dragGestureChanged:)];
[scrollViewAlfabeto addGestureRecognizer:downwardGesture];
    for (UIGestureRecognizer *gestureRecognizer in myscrollView.gestureRecognizers)
    {
       [gestureRecognizer requireGestureRecognizerToFail:downwardGesture];
    }
}

- (void) dragGestureChanged:(UIPanGestureRecognizer*)gesture
{
CGPoint point = [gesture locationInView:scrollViewAlfabeto];

if (gesture.state == UIGestureRecognizerStateBegan) 
{

    [imageViewToMove removeFromSuperview];
    [self.view addSubview:imageViewToMove];

    UIView *draggedView = [myscrollView hitTest:point withEvent:nil];
    if ([draggedView isKindOfClass:[UIImageView class]])
    {
        imageViewToMove = (UIImageView*)draggedView;
    }
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
    imageToMove.center = point;
}
else if (gesture.state == UIGestureRecognizerStateEnded     ||
         gesture.state == UIGestureRecognizerStateCancelled ||
         gesture.state == UIGestureRecognizerStateFailed)
{
    // Determine if dragged view is in an OK drop zone
    // If so, then do the drop action, if not, return it to original location

    NSLog(@"point.x final:%f", point.x);
    NSLog(@"point.y final:%f", point.y);

    if (CGRectContainsPoint(goal.frame, point)){
        imageToMove.frame = CGRectMake(167, 159, 100, 100);
    }

    else{

        [imageToMove removeFromSuperview];
        [myscrollView addSubview:imageToMove];
        [imageToMove setFrame:CGRectMake(12, 38, 100, 100)];
        imageToMove = nil;



    }
}

}

May this code will help you out.

查看更多
不美不萌又怎样
3楼-- · 2019-01-18 05:47

For a similar problem, I made UIScrollView subclass like the following: PoliteScrollView passes touch messages to it's subviews when it determines that they are being dragged.

@interface PoliteScrollView : UIScrollView

// number of pixels perpendicular to the scroll views orientation to make a drag start counting as a subview drag
// defaults to 1/10 of the scroll view's width or height, whichever is smaller
@property(nonatomic,assign) CGFloat subviewDraggingThreshold;
// yes when a subview is being dragged
@property(nonatomic,assign) BOOL isDraggingSubview;
// the subview being dragged
@property(nonatomic,strong) UIView *draggingSubview;

@end

@protocol PoliteScrollViewDelegate <NSObject>
@optional
- (void)scrollView:(PoliteScrollView *)scrollView subviewTouchesBegan:(NSSet *)touches;
- (void)scrollView:(PoliteScrollView *)scrollView subviewTouchesMoved:(NSSet *)touches;
- (void)scrollView:(PoliteScrollView *)scrollView subviewTouchesEnded:(NSSet *)touches;
@end

The key design idea is that dragging in a scroll view is ambiguous. Is the user scrolling or dragging a subview? PoliteScroll view handles this by providing two things: (1) a notion of orientation (horizontal if it's longer than it is wide, vertical otherwise), and (2) a threshold distance for what constitutes a drag in the direction perpendicular to it's orientation. (defaults to 1/10 the width or height).

I pasted this and several other files are in a paste bin, containing the following:

  • PoliteScrollView .h and .m
  • DraggableImageView.h and .m - that changes it's position when it gets touch messages.
  • ViewController.m - that demonstrates thetwo in combination.

To combine these in a project, paste the paste bin into files appropriately named, add a storyboard with a PoliteScrollView (be sure to set it's delegate), add in some images (the ViewController tries to add puppy0.jpeg to puppy4.jpeg.

查看更多
成全新的幸福
4楼-- · 2019-01-18 05:52

I created an example which illustrates how to drag and drop between two or more views: http://www.ancientprogramming.com/2012/04/05/drag-and-drop-between-multiple-uiviews-in-ios/

I found it a good idea to register the gesture recognizer to a different view than the actual views being dragged. This will make sure the gestures continue even though the dragged view changes its 'parent' view.

Maybe it can give some inspiration

查看更多
5楼-- · 2019-01-18 06:03

Hi Getsy,

I am not going to provide you code directly but give idea how to manage this.

You can manage this way, When you get touch on your object in scrollView at that time or when you move that object by draging at that time disable scroll by myScroll.scrollEnabled = NO;

Then When on endTouch you can enable Scroll by myScroll.scrollEnabled = YES; So by this you can manage you object moving in scroll hope you got logic.

Here is the demo code : Drag and Drop with ScrollView. which has same logic of Disabling scroll view on touchesMoved: and Enabling scroll view on touchesEnded:.

查看更多
聊天终结者
6楼-- · 2019-01-18 06:11

I did implement that behaviour before without any subclassing.

I used canCancelContentTouches = NO of the UIScrollView to make sure the subviews handle there touches on their own. If a subview (in your case an image) was touched, i moved the view out of the scrollview onto the superview and started tracking it's dragging. (You have to calculate the correct coordinates within the new superview, so it stays in place).

After dragging finishes, i checked if the target area was reached, otherwise I moved it back into the scrollview. If that's not detailed enough I could post some code.

Well here is my example code: Github: JDDroppableView

查看更多
登录 后发表回答