Tuesday, September 18, 2012

Draging and Droping objects in iOS App

Hi Guyz, in this section i will  describe you how to drag any particular views/objects and dropping it somewhere else. This is the nice feature  mostly seen in web apps, but here i will be detailing how to use this features in iOS Apps. In this demo, we will be changing the background color of UIView (where we will be dropping objects) depending on the dragged object's color and i will also give you a hint to change the position(repositioning it) of dragged object's as a result of Drag and Drop.
Lets get started !!!!

First design your  ViewController.xib file  as in figure with four dragging objects(here,UIImageView) and one UIView (as dropping target view). Change the background color of all 4 UIImageViews.
Now in .h file,
   // connect target UIView in Interface Builder
@property (nonatomic, strong) IBOutlet UIView *dropTargetView;
     // define temp UIImageView for view being dragged
@property (nonatomic, strong)  UIImageView *dragObjectView; 
    //distance between the actual touch point and the upper left corner of the dragObject
@property (nonatomic, assign) CGPoint touchOffset;
  // drag object's original position  in screen
@property (nonatomic, assign) CGPoint homePosition;

In order to implement drag and drop, we have to track not only when touches occur, but how they move about the screen (drag) and where they end (drop), To achieve this we will be using TouchEvent delegates method.
Now in .m file,
@synthesize dropTargetView,dragObjectView,touchOffset,homePosition;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    if ([touches count] == 1) {
        // one finger touch
        //we look at all subviews of the main view, and for each, we see if the touch occurred inside that view’s frame. We also verify that the object touched is an image view (because we are using UIImageview as a dragging object here).    

       CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
        for (UIImageView *iView in self.view.subviews) { // checking of Dragging Object's Class type
            if ([iView isMemberOfClass:[UIImageView class]]) {
                if (touchPoint.x > iView.frame.origin.x &&
                    touchPoint.x < iView.frame.origin.x + iView.frame.size.width &&
                    touchPoint.y > iView.frame.origin.y &&
                    touchPoint.y < iView.frame.origin.y + iView.frame.size.height)
                {
                    iView.alpha = 0.5; // making selected view dim background to notice it as a object being dragged

                    //we now designate the view as the dragObjectView, get the offset of the touch from the upper left corner of the view  as a CGPoint, and “remember” the view’s home position.
                    self.dragObjectView = iView;
                    self.touchOffset = CGPointMake(touchPoint.x - iView.frame.origin.x,
                                                   touchPoint.y - iView.frame.origin.y);
                    self.homePosition = CGPointMake(iView.frame.origin.x,
                                                    iView.frame.origin.y);
                    [self.view bringSubviewToFront:self.dragObjectView]; //bringing object dragged to be in front where it is going to replaced
                }
            }
        }
    }
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
//we get the position of the touch, then set the dragObject’s frame to the new touch position minus the touchOffset coordinates (the width and height of object don’t change).

    CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
    CGRect newDragObjectFrame = CGRectMake(touchPoint.x - touchOffset.x,
                                           touchPoint.y - touchOffset.y,
                                           self.dragObjectView.frame.size.width,
                                           self.dragObjectView.frame.size.height);
    self.dragObjectView.frame = newDragObjectFrame;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
//For our example, we observe whether the last touch point is inside the frame of the dropTargetView. If it is, we change the background color of the drop target to the background color of the dragObjectView. Regardless of the dragObject’s position, we send it back to its homePosition.   

// Beside above statement, you can drag and drop your object at any position by simply repositioning your object to new frame
 CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
    if (touchPoint.x > self.dropTargetView.frame.origin.x &&
        touchPoint.x < self.dropTargetView.frame.origin.x + self.dropTargetView.frame.size.width &&
        touchPoint.y > self.dropTargetView.frame.origin.y &&
        touchPoint.y < self.dropTargetView.frame.origin.y + self.dropTargetView.frame.size.height )
    {

    // If dragged object is ended inside our dropping UIView, change the background color
        self.dropTargetView.backgroundColor = self.dragObjectView.backgroundColor;
       
    }

  // And also give your dragged object its original location frame
    self.dragObjectView.frame = CGRectMake(self.homePosition.x, self.homePosition.y,
                                      self.dragObjectView.frame.size.width,
                                      self.dragObjectView.frame.size.height);
    self.dragObjectView.alpha = 1.0; // setting alpha to 1 since we changed it to 0.5 in touchBegin case

  Note : If you simply want to relocate your dragged object by dropping it anywhere, then you don't have to write above if codes, just reframe your dragged object as :
      // self.dragObjectView.frame = CGRectMake(touchPoint.x,touchPoint.y, self.dragObjectView.frame.size.width,  self.dragObjectView.frame.size.height);
}

Final Look of the app should be :




2 comments:

  1. Thank you so much. Could u please tell me how I can keep the dragobject remains in the frame when I drag another object?

    ReplyDelete
  2. Can u tell me how to replace UIImageview over another Uiimage view if i'm dragging and dropping. I mean if i'm dragging on image view and placing over another image view the existing image view should hide when placing new one.

    ReplyDelete