【问题标题】:How to achieve continuous drag drop menu effect?如何实现连续拖拽菜单效果?
【发布时间】:2012-01-10 23:42:12
【问题描述】:

我正在尝试实现拖放菜单效果。我不知道该怎么做,也许有人有这种确切效果的经验。

很简单,当用户触摸菜单项时,我希望在他们的触摸位置出现图形。他们的触摸现在将控制图形的平移。释放触摸后,图形将就位并呈现完整的 alpha。

我已经熟悉创建平移手势和实例化图形。到目前为止,我可以创建触摸菜单项的图形。最大的问题是我如何“忽略”触摸手势,使其成为单一且连续的动作。

另外,菜单项应该是 UIButton 还是 UIImageView?

任何帮助表示赞赏。谢谢

【问题讨论】:

    标签: iphone ios xcode ipad


    【解决方案1】:

    我玩这个很开心。以下代码将在触摸时从按钮中抓取图像,将该图像拖动到 alpha=0.5,然后将其拖放到您触摸结束时 alpha=1.0 的任何位置。此后它将继续可拖动。

    导入 QuartzCore 后,创建一个新文件。 .h 应为:

    #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
    

    .m 应该是:

    #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
    

    现在在您的主视图控制器中,添加:

    #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;
    

    在这种情况下,imageButton 将是您的苹果按钮。现在在您的 .m 文件中,添加以下内容:

    @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];
    }
    

    瞧!连接你的按钮,设置它的图像,然后把副本扔到整个屏幕上。 :)

    注意:我没有发表太多评论,但很乐意回答任何问题。

    干杯!

    编辑:修复了-(void)draw:(UIImage *)image{},以便它可以正确调整图像大小。

    【讨论】:

      【解决方案2】:

      如果您想要将触摸功能传递给第二个图形(大图形),我认为您可以这样做

      在 .h 上,您必须声明要拖动的图像和浮动变量以记住可拖动按钮的前一点(我假设您使用 IOS 5 SDK)

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

      那么,在 .m 你可以这样做

      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];
      

      然后做拖拽功能

      - (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];
      }
      

      最后,在您将按钮返回到其原始位置的位置创建 dragRelease 函数并将图像的 alpha 设置为 1

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

      你就完成了:3

      这只是基本的想法,也许这不是你想要的,但我希望这会有所帮助

      edit* : 哦,别忘了综合所有属性,如果你使用低于 5.0 的 SDK,你可以将 "strong" 属性更改为 "retain"

      【讨论】:

      • 您好,感谢您试一试。我对您的代码进行了两项更改:我使用了 UIControlEventTouchDragInside 和 UIControlEventTouchDragOutside,因为我认为它们工作得更好。但是我无法获得效果。拖动只会移动按钮,而不是 50% 不透明度的大图像。释放也会将按钮扔到左上角。我会继续改变它,看看我能得到什么。任何额外的代码表示赞赏。谢谢!
      • 您是否将图像作为子视图添加到视图中?使用 [self.view addSubview:myImage]; ???
      • 是的。你有可以上传或分享的工作代码示例吗?谢谢