UIPanGestureRecognizer不能平滑地移动UIImages并进行渲染吗?

时间:2013-04-23 13:07:38

标签: ios uipangesturerecognizer

我在项目中遇到问题我的项目目的是在开始时添加许多UIImages,这些图像应该是可拖放的,因为我使用UIPanGestureRecognizer但仍然面临问题请帮助我提前谢谢。

此代码位于我的viewdidload方法

 UIView *holderView = [[UIView alloc]init];

for (int i = 0; i<=4; i+=1) {

    NSMutableArray * images = [[NSMutableArray alloc]initWithObjects:@"iphone-status-bar.png",@"uiswitch.png",@"NavigationBar.png",@"barbutton.png",@"ios-back-button.png", nil];


    NSString * image_name= [NSString stringWithFormat:@"%@",[images objectAtIndex:i]];

//  NSLog(@"%@",image_name);

    UIImage *image = [UIImage imageNamed:image_name];

    holderView = [[UIView alloc] initWithFrame:CGRectMake(2, i*30, image.size.width, image.size.height)];

    UIImageView *imageview = [[UIImageView alloc] initWithFrame:[holderView frame]];

    imageview.userInteractionEnabled = YES;

    [imageview setImage:image];

    [holderView addSubview:imageview];

    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];

    [panRecognizer setMinimumNumberOfTouches:1];

    [panRecognizer setMaximumNumberOfTouches:1];

    [panRecognizer setDelegate:self];

     [holderView addGestureRecognizer:panRecognizer];


     [self.view addSubview:holderView];
}

手势处理程序是:

-(void)move:(id)sender {

    [self.view bringSubviewToFront:[(UIPanGestureRecognizer*)sender view]];
    CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {

        firstX = [[sender view] center].x;
        firstY = [[sender view] center].y;
    }

    translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY+translatedPoint.y);

    [[sender view] setCenter:translatedPoint];

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {

        CGFloat finalX = translatedPoint.x + (.01*[(UIPanGestureRecognizer*)sender velocityInView:self.view].x);
        CGFloat finalY = translatedPoint.y + (.01*[(UIPanGestureRecognizer*)sender velocityInView:self.view].y);

        if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {

            if(finalX < 0) {

                finalX = 0;
            }

            else if(finalX > 768) {

                finalX = 768;
            }

            if(finalY < 0) {

                finalY = 0;
            }

            else if(finalY > 1024) {

                finalY = 1024;
            }
        }

        else {

            if(finalX < 0) {

                finalX = 0;
            }

            else if(finalX > 1024) {

                finalX = 768;
            }

            if(finalY < 0) {

                finalY = 0;
            }

            else if(finalY > 768) {

                finalY = 1024;
            }
        }

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:.35];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        [[sender view] setCenter:CGPointMake(finalX, finalY)];
        [UIView commitAnimations];
    }
}

1 个答案:

答案 0 :(得分:0)

我个人怀疑holderView逻辑。您使用holderView的垂直偏移量将i * 30添加到控制器的顶级视图中,但是当您将imageView添加到holderView时,您正在抵消它在holderView之后再次i * 30(因为您使用frame的{​​{1}},其中有holderView个偏移量)!更糟糕的是,因为您的手势识别器位于y而不是holderView,当您尝试通过点击图像抓住imageView时,您通常不会超过你认为自己是imageView,而是其他一个图像中的一个!

假设您喜欢现在布置图像的方式(相距60.0分),那么我建议您将holderView更改为i*30并且:或者

  • i*60.0的{​​{1}}设置更改为frame;或者,甚至更好,

  • 完全摆脱了imageView个观点,因为(至少基于你目前所分享的内容)它没有增加任何价值,只会使代码复杂化。

另外,还有一些其他观察结果:

  • [holderView bounds]数组不需要是可变的,您不应该在holderView循环内重新初始化它。

  • 您可能应该在images循环中引用for而不是硬编码[images count]

通过这些更改,4代码如下所示:

for

您也可以简化viewDidLoad例行程序:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    NSArray *images = [[NSArray alloc]initWithObjects:@"iphone-status-bar.png",@"uiswitch.png",@"NavigationBar.png",@"barbutton.png",@"ios-back-button.png", nil];

    // if you're using a recent version of the compiler, you could simplify that further to just
    //
    // NSArray *images = @[@"iphone-status-bar.png",@"uiswitch.png",@"NavigationBar.png",@"barbutton.png",@"ios-back-button.png"];

    for (int i = 0; i < [images count]; i++) {

        NSString *imageName = [images objectAtIndex:i]; // or you could say `NSString *imageName = images[i];`
        UIImage *image = [UIImage imageNamed:imageName];
        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
        imageView.frame = CGRectMake(2.0, i * 60.0, image.size.width, image.size.height);
        imageView.userInteractionEnabled = YES;
        [self.view addSubview:imageView];

        UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];
        panRecognizer.minimumNumberOfTouches = 1;
        panRecognizer.maximumNumberOfTouches = 1;

        [imageView addGestureRecognizer:panRecognizer];
    }
}

就个人而言,我讨厌看到硬编码的坐标,所以我可能会进一步将move代码简化为:

-(void)move:(UIPanGestureRecognizer *)gesture {

    static CGPoint originalCenter; // or make this a class ivar; but don't make this a global!

    if (gesture.state == UIGestureRecognizerStateBegan) {

        [gesture.view.superview bringSubviewToFront:gesture.view];
        originalCenter = gesture.view.center;
    }

    CGPoint translation = [gesture translationInView:self.view];
    CGPoint translatedPoint = CGPointMake(originalCenter.x+translation.x, originalCenter.y+translation.y);

    gesture.view.center = translatedPoint;

    if(gesture.state == UIGestureRecognizerStateEnded) {
        CGPoint velocity = [gesture velocityInView:gesture.view];
        translatedPoint.x = MAX(translatedPoint.x + .01 * velocity.x, 0.0);
        translatedPoint.y = MAX(translatedPoint.y + .01 * velocity.y, 0.0);

        if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {

            translatedPoint.x = MIN(translatedPoint.x, 768.0);
            translatedPoint.y = MIN(translatedPoint.y, 1024.0);
        }
        else {

            translatedPoint.x = MIN(translatedPoint.x, 1024.0);
            translatedPoint.y = MIN(translatedPoint.y, 768.0);
        }

        [UIView animateWithDuration:0.35
                              delay:0.0
                            options:UIViewAnimationOptionCurveEaseOut
                         animations:^{
                             gesture.view.center = translatedPoint;
                         }
                         completion:nil];
    }
}