IOS - animation not responding

2019-08-17 07:41发布

问题:

I want to create an animated menu.

  • first it's hidden outside screen
  • when user taps the screen, it will slide in
  • user can tap it and it do something
  • then after 3s it will slide outside screen

But problem is it not response when I tap it. Why?

example code: All code is in my UIView class.

showing = NO;
box = [[UIView alloc] initWithFrame:CGRectMake(500,-200,200,200)];
box.backgroundColor = [UIColor redColor];

UITapGestureRecognizer *tapBox = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMenuHandler:)] autorelease];
[box addGestureRecognizer:tapBox];

[self addSubView:box];

and:

-(void) tapMenuHandler: (UIView *)obj {
    //Do something
    NSLog(@"tap box");
} 

and:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (!showing) {

    box.frame = CGRectMake(500, -200, 200, 200);

    [UIView animateWithDuration:0.5f delay:0.3f options:(UIViewAnimationOptionAllowUserInteraction) animations:^{

        box.frame = CGRectMake(500, 200, 200, 200);

    } completion:^(BOOL finished) {
        showing = YES;

                    [UIView animateWithDuration:0.5f delay:3.0f options:(UIViewAnimationOptionAllowUserInteraction) animations:^{
                        box.frame = CGRectMake(500, -200, 200,200);
                    } completion:^(BOOL finished) {
                       showing = NO;
                    }];

    }];    
}

}

Thank for your help and sorry for my English :)

Edit: more detail I tried set start my box's origin in screen (ex. 500,600), It still always response when tap at start point (500,600) even though my box move to another position.

Update: I changed my way to move box outside screen by use NSTimer then it's work!

[UIView animateWithDuration:0.5f delay:0.3f options:UIViewAnimationOptionAllowUserInteraction animations:^{

        box.frame = CGRectMake(500,200,200,200);

    } completion:^(BOOL finished) {
        isShowMenubar = YES;
        //use NSTimer instead of delay
        [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(hideBox) userInfo:nil repeats:NO];

    }]; 

and

-(void)hideBox {
[UIView animateWithDuration:0.5f delay:0.0f options:UIViewAnimationOptionAllowUserInteraction animations:^{
    box.frame = CGRectMake(500,-200,200,200);} completion:^(BOOL finished) {
        isShowMenubar = NO;
    }];
}

回答1:

The reason why the box is not receiving touches has to do with how animation works. Your box is actually offscreen, but visually, it's going through the animation.

Even though you set the delay as 3.0, it still moves the box beforehand (due to the animation method still being called). So in your current code, if you tapped on the box at (500, -200) then it will receive the touch.

To fix this, either use an NSTimer or Grand Central Dispatch to delay.

NSTimer:

[NSTimer scheduledTimerWithTimeInterval:3.0 target:self action:@selector(dismissBox) userInfo:nil repeats:NO];

The problem with NSTimer is that you'll have to put that animation code in a separate method.

Grand Central Dispatch:

double delayInSeconds = 3.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [UIView animateWithDuration:0.5f animations:^{
        box.frame = CGRectMake(box.frame.origin.x, -200, 200,200);

    }completion:^(BOOL finished) {
        showing = NO;
    }];
});


回答2:

I ran the code and didn't see the red view either. Then playing around for a bit, I got that your view is animating but is still out of bounds so you never see it. try changing the animation block to something like (the origin of the frame is at the left bottom corner)

box.frame = CGRectMake(100, 100, 200, 200);

and hopefully it will come animating.

Also, assuming that you run these in your view controller, the correct method should be

[self.view addSubview:box];

hope this helps