UIView drag (image and text)
Asked Answered
J

6

27

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.

Johppa answered 13/2, 2011 at 3:35 Comment(0)
S
34

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.

Subduct answered 13/2, 2011 at 8:2 Comment(0)
K
36

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));
}
Kirstiekirstin answered 30/4, 2012 at 4:10 Comment(1)
This code makes the UIVIew not jump under your finger, well done.Vulcanite
S
34

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.

Subduct answered 13/2, 2011 at 8:2 Comment(0)
D
24

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://mcmap.net/q/495352/-uiview-drag-image-and-text

Delivery answered 30/11, 2011 at 20:33 Comment(0)
D
5

Even though rokjarc solution works, using

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

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

Dorris answered 29/4, 2012 at 23:45 Comment(1)
Nice one. But you have to use it as diablosnuevos suggests - with CGRectOffset.Delivery
H
2

Here is a solution to drag a custom UIView (it can be scaled or rotated through its transform), which can hold images and/or text (just edit the Tile.xib as required):

app screenshot

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self];
    CGPoint previous = [touch previousLocationInView:self];

    if (!CGAffineTransformIsIdentity(self.transform)) {
        location = CGPointApplyAffineTransform(location, self.transform);
        previous = CGPointApplyAffineTransform(previous, self.transform);
    }

    self.frame = CGRectOffset(self.frame,
                              (location.x - previous.x),
                              (location.y - previous.y));
}
Hoarse answered 23/3, 2014 at 19:18 Comment(0)
E
0

This work for me. My UIView rotated and scaled

- (void) touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
CGPoint previous = [touch previousLocationInView:self];

if (!CGAffineTransformIsIdentity(self.transform)) {
    location = CGPointApplyAffineTransform(location, self.transform);
    previous = CGPointApplyAffineTransform(previous, self.transform);
}
CGRect newFrame = CGRectOffset(self.frame,
                               (location.x - previous.x),
                               (location.y - previous.y));
float x = CGRectGetMidX(newFrame);
float y = CGRectGetMidY(newFrame);
self.center = CGPointMake(x, y);

}

Entomophagous answered 6/12, 2015 at 15:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.