How to achieve continuous drag drop menu effect?

2020-04-08 12:59发布

I'm trying to achieve a Drag and Drop menu affect. I'm not sure how to go about this, perhaps someone has experience with this exact effect.

Quite simply, when a user touches down on a menu item, I want a graphic to appear at their touch location. Their touch will now control the panning of the graphic. Upon releasing the touch, the graphic will sit in its place and assume full alpha.

I'm already familiar with creating pan gestures and instantiating a graphic. So far, I can create the graphic where the menu item is touched. The biggest issue is how I "pass over" the touch gesture so it is a single and continuous motion.

Also, should the menu item be UIButton or UIImageView?

Any help appreciated. Thanks enter image description here

2条回答
看我几分像从前
2楼-- · 2020-04-08 13:34

if what you want is to pass the touch function to the second graphic (the big one) i think you can do something like this

on .h you have to declare the images that you're going to drag and float variable to remember previous point of the dragable button (i'm assuming you use IOS 5 SDK)

@property(nonatomic, strong) UIImageView* myImage;
@property float pointX;
@property float pointY;

then, at .m you can do this

myImage = [[UIImageView alloc]initWithImage:@"appleImage.jpg"];
myImage.alpha = 0;

//default UIImageView interaction is disabled, so lets enabled it first
myImage.userInteractionEnabled = YES;

[button addTarget:self action:@selector(wasDragged:withEvent:) forControlEvents:UIControlEventTouchDragInside];

and then make the drag function

- (void)wasDragged:(UIButton *)button withEvent:(UIEvent *)event
{

        self.myImage.alpha = 0.5;

    UITouch *touch = [[event touchesForView:button] anyObject];


    CGPoint previousLocation = [touch previousLocationInView:button];
    CGPoint location = [touch locationInView:button];
    CGFloat delta_x = location.x - previousLocation.x;
    CGFloat delta_y = location.y - previousLocation.y;

    // move button, to keep the dragging effect 
    button.center = CGPointMake(button.center.x + delta_x,
                                button.center.y + delta_y);

        // moving the image
        button.center = CGPointMake(button.center.x + delta_x,
                                button.center.y + delta_y);

    self.pointX = previousLocation.x;
    self.pointY = previousLocation.y;

    [button addTarget:self action:@selector(dragRelease:withEvent:) forControlEvents:UIControlEventTouchUpInside];
}

finally, make the dragRelease function where you return the button to its original place and set the alpha of the images to 1

-(void)dragRelease:(UIButton *)button withEvent:(UIEvent *)event
{
     self.myImage.alpha = 1;
     button.center = CGPointMake(pointX, pointY);
}

and you're done :3

this is just the basic idea though, maybe this isn't what you want, but i hope this helps

edit* : oh and don't forget to synthesize all the properties, also if you're using SDK below 5.0, you can change the "strong" property to "retain"

查看更多
劫难
3楼-- · 2020-04-08 13:37

I had some fun with this one. The following code will grab the image from the button when touched, drag that image at alpha=0.5, and drop it wherever your touches end at alpha=1.0. It will continue to be draggable thereafter.

After importing QuartzCore, create a new file. The .h should read:

#import <Foundation/Foundation.h>
#import <QuartzCore/CAGradientLayer.h>
#import <QuartzCore/CALayer.h>

@interface DraggableImage : CAGradientLayer

- (void)draw:(UIImage *)image;

- (void)moveToFront;

- (void)appearDraggable;

- (void)appearNormal;

@end

and the .m should read:

#import "DraggableImage.h"

@implementation DraggableImage

- (void)draw:(UIImage *)image{
    CGRect buttonFrame = self.bounds;
    int buttonWidth = buttonFrame.size.width;
    int buttonHeight = buttonFrame.size.height;
    UIGraphicsBeginImageContext( CGSizeMake(buttonWidth, buttonHeight) );
    [image drawInRect:self.bounds];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [newImage drawInRect:self.bounds];
}

- (void)moveToFront {
    CALayer *superlayer = self.superlayer;
    [self removeFromSuperlayer];
    [superlayer addSublayer:self];
}

- (void)appearDraggable {
    self.opacity = 0.5;
}


- (void)appearNormal {
    self.opacity = 1.0;
}

@end

Now in your main view controller, add:

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "DraggableImage.h"

@interface YourViewController : UIViewController{
    DraggableImage *heldImage;
    DraggableImage *imageForFrame[5]; // or however many
    UIButton *buttonPressed;
    int imageCount;
}
@property (weak, nonatomic) IBOutlet UIButton *imageButton;
-(IBAction)buildImageLayerForButton:(UIButton *)sender;
- (void)moveHeldImageToPoint:(CGPoint)location;
- (CALayer *)layerForTouch:(UITouch *)touch;

The imageButton in this case would be your apple Button. Now in your .m file, add this:

@synthesize imageButton;

#pragma - mark Touches

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    CALayer *hitLayer = [self layerForTouch:[touches anyObject]];
    if ([hitLayer isKindOfClass:[DraggableImage class]]) {
        DraggableImage *image = (DraggableImage *)hitLayer;

        heldImage = image;
        [heldImage moveToFront];
    }
    hitLayer = nil;
    [super touchesBegan:touches withEvent:event];
}

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

        if (heldImage) 
        {
            UITouch *touch = [touches anyObject];
            UIView *view = self.view;
            CGPoint location = [touch locationInView:view];
            [self moveHeldImageToPoint:location];
        }

}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    if (heldImage) {
        [heldImage appearNormal];
        heldImage = nil;
    }
}

- (void)dragBegan:(UIControl *)c withEvent:ev {
}
- (void)dragMoving:(UIControl *)c withEvent:ev {
    UITouch *touch = [[ev allTouches] anyObject];
    CGPoint touchPoint = [touch locationInView:self.view];
    [self moveHeldImageToPoint:touchPoint];
}

- (void)dragEnded:(UIControl *)c withEvent:ev {
    UITouch *touch = [[ev allTouches] anyObject];
    CGPoint touchPoint = [touch locationInView:self.view];
    [self moveHeldImageToPoint:touchPoint];
    [heldImage appearNormal];
    heldImage = nil;
}



-(IBAction)buildImageLayerForButton:(UIButton *)sender{


        DraggableImage *image = [[DraggableImage alloc] init];
        buttonPressed = sender;
        CGRect buttonFrame = sender.bounds;
        int buttonWidth = buttonFrame.size.width;
        int buttonHeight = buttonFrame.size.height;

        image.frame = CGRectMake(120, 24, buttonWidth*3, buttonHeight*3);
        image.backgroundColor = [UIColor lightGrayColor].CGColor;
        image.delegate = self;
        imageForFrame[imageCount] = image;
        [self.view.layer addSublayer:image];
        [image setNeedsDisplay];
        [image moveToFront];
        [image appearDraggable];
        heldImage = image;
        [self moveHeldImageToPoint:sender.center];

        imageCount++;

}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    UIGraphicsPushContext(ctx);

    DraggableImage *image = (DraggableImage *)layer;
    [image draw:[buttonPressed imageForState:UIControlStateNormal]];

    UIGraphicsPopContext();
}

- (void)moveHeldImageToPoint:(CGPoint)location 
{
    float dx = location.x;
    float dy = location.y;
    CGPoint newPosition = CGPointMake(dx, dy);

    [CATransaction begin];
    [CATransaction setDisableActions:TRUE];
    heldImage.position = newPosition;
    [CATransaction commit];
}

- (CALayer *)layerForTouch:(UITouch *)touch 
{
    UIView *view = self.view;

    CGPoint location = [touch locationInView:view];
    location = [view convertPoint:location toView:nil];

    CALayer *hitPresentationLayer = [view.layer.presentationLayer hitTest:location];
    if (hitPresentationLayer) 
    {
        return hitPresentationLayer.modelLayer;
    }

    return nil;
}

-(void)viewDidLoad{
    [imageButton addTarget:self action:@selector(dragBegan:withEvent:) forControlEvents: UIControlEventTouchDown];
    [imageButton addTarget:self action:@selector(dragMoving:withEvent:) forControlEvents: UIControlEventTouchDragInside | UIControlEventTouchDragOutside];
    [imageButton addTarget:self action:@selector(dragEnded:withEvent:) forControlEvents: UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
    [super viewDidLoad];
}

- (void)viewDidUnload {
    [self setImageButton:nil];
    [super viewDidUnload];
}

Et voila! Connect your button, set its image, and throw copies all over the screen. :)

Note: I didn't comment much, but would be happy to answer any questions.

Cheers!

EDIT: fixed the -(void)draw:(UIImage *)image{} so that it would resize the image properly.

查看更多
登录 后发表回答