Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView drag (image and text)

Is it possible to drag UIView around the iOS screen while it has both image and text? e.g. small cards. Could you point me to the similar (solved) topic? I haven't found any.

like image 447
psimekjr Avatar asked Feb 13 '11 03:02

psimekjr


4 Answers

This is what a neat solution, based on pepouze's answer, would look like (tested, it works!)

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *aTouch = [touches anyObject];
    CGPoint location = [aTouch locationInView:self];
    CGPoint previousLocation = [aTouch previousLocationInView:self];
    self.frame = CGRectOffset(self.frame, (location.x - previousLocation.x), (location.y - previousLocation.y));
}
like image 147
Arie Litovsky Avatar answered Nov 16 '22 21:11

Arie Litovsky


While UIView does not have a built-in support for moving itself along the user dragging, it should be not so difficult to implement it. It is even easier when you are only dealing with dragging on the view, and not other actions such as tapping, double tapping, multi-touches etc.

First thing to do is to make a custom view, say DraggableView, by subclassing UIView. Then override UIView's touchesMoved:withEvent: method, and you can get a current dragging location there, and move the DraggableView. Look at the following example.

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *aTouch = [touches anyObject];
    CGPoint location = [aTouch locationInView:self.superview];
    [UIView beginAnimations:@"Dragging A DraggableView" context:nil];
    self.frame = CGRectMake(location.x, location.y, 
                            self.frame.size.width, self.frame.size.height);
    [UIView commitAnimations];
}

And because all subviews of the DraggableView object will be moved, too. So put all your images and texts as subviews of the DraggableView object.

What I implemented here is very simple. However, if you want more complex behaviors for the dragging, (for example, the user have to tap on the view for a few seconds to move the view), then you will have to override other event handling methods (touchesBegan:withEvent: and touchesEnd:withEvent) as well.

like image 34
MHC Avatar answered Nov 16 '22 19:11

MHC


An addition to MHC's answer.

If you don't want the upper left corner of the view to jump under your finger, you can also override touchesBegan like this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *aTouch = [touches anyObject];

    offset = [aTouch locationInView: self];
}

and change MHC's touchesMoved to:

 -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
 {
      UITouch *aTouch = [touches anyObject];
      CGPoint location = [aTouch locationInView:self.superview];

      [UIView beginAnimations:@"Dragging A DraggableView" context:nil];
      self.frame = CGRectMake(location.x-offset.x, location.y-offset.y, 
                              self.frame.size.width, self.frame.size.height);
      [UIView commitAnimations];
  }

you should also define CGPoint offset in the interface:

@interface DraggableView : UIView
{
    CGPoint offset;
}

EDIT:

Arie Litovsky provides more elegant solution that allows you to ditch the ivar: https://stackoverflow.com/a/10378382/653513

like image 24
Rok Jarc Avatar answered Nov 16 '22 21:11

Rok Jarc


Even though rokjarc solution works, using

CGPoint previousLocation = [aTouch previousLocationInView:self.superview];

avoids the CGPoint offset creation and the call to touchesBegan:withEvent:

like image 5
pepouze Avatar answered Nov 16 '22 21:11

pepouze