iOS视图动画允许用户交互

时间:2014-05-19 02:39:02

标签: ios animation uiview uikit

我制作的游戏类似于钢琴拼花https://itunes.apple.com/us/app/piano-tiles-dont-tap-white/id848160327?mt=8

即使早期动画未完成,您也可以点按一个图块。

这是我的实施

- (void)moveDown {


    [UIView animateWithDuration:DURATION_MOVE_DOWN delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{

        for (Tile *t in self.tiles) {
            if (t.y == NUM_TILES_Y - 1) {
                t.y = 0;
            }
            else {
                t.y++;
            }

            if (t.y == 0) {
                //move down
                //then place it to the top (in the completion handler)
                t.frame = [Tile frameWithX:t.x y:NUM_TILES_Y];
            }
            else {
                //move down
                t.frame = [Tile frameWithX:t.x y:t.y];
            }

        }

    } completion:^(BOOL finished) {

        for (Tile *t in self.tiles) {
            //if user tap while animating, just place the tile at its final position first, (then continue the new animation)
            t.frame = [Tile frameWithX:t.x y:t.y];
        }

        [self assignTouchDontTouchWithRowY:0];

    }];

}

assignTouchDontTouchWithRowY方法是随机选择一行的平铺为TileTypeTouch(黑色平铺),其余行为TileTypeDontTouch(白色平铺)

- (void)assignTouchDontTouchWithRowY:(int)y {
    int touchX = [Helper randomIntInclusiveBetweenLow:0 High:NUM_TILES_X -1];
    for (int x = 0; x < NUM_TILES_X; x++) {
        Tile *t = [self tileWithX:x y:y];
        if (x == touchX) {
            t.type = TileTypeTouch;
        }
        else {
            t.type = TileTypeDontTouch;
        }
    }

}

问题在于,当我在早期动画完成之前按下一个图块时,一些代码没有被执行(例如,着色一个新行,向下移动一行,有时底部行被翻译到顶部到顶部而不是先下滑,然后放在顶部)

当我使用选项UIViewAnimationOptionBeginFromCurrentState时,用户交互会在前一个动画制作时被取消。所以它也没有用。

编辑:

enter image description here

在屏幕截图中,(0,1)平铺是第二个最后一个平铺,它被翻译到顶部(没有向下滑动并更新其颜色)

还要注意,在(y = 1)行之上,屏幕外还有另一行(y = 0)。 即有5行,其中4行在屏幕上,第一行(y = 0)在屏幕外的顶部。向下滑动时,最后一行(y = 4)首先向下滑动,然后将其置于完成处理程序中的顶部(y = 0)

编辑3: 以防我的逻辑不明确:

  1. 点击黑色瓷砖时,所有瓷砖向下移动
  2. 为最后一行(y = 4),我先将其向下移动,然后将其放在完成处理程序的顶部(外部屏幕)
  3. 如果用户在动画期间点击一个图块,我首先立即将图块放在正确的位置(即旧动画的最终状态),然后我开始新的动画。
  4. 编辑4: 错误在此处的视频中说明

    https://drive.google.com/file/d/0B-iP0P7UfFj0Q01neEhaZmtBY2c/edit?usp=sharing

2 个答案:

答案 0 :(得分:1)

在新动画之后执行完成块(当你调用-moveDown

时会立即执行)

何时执行完成块?我们不知道!它在队列/未来!

所以将上一个动画的清理代码移到moveDown的开头(在animiation之外,不要忘记检查是否(完成)以保存一些不必要的工作

- (void)moveDown {

    Tile *t = self.tiles[0];
    if (t.layer.animationKeys.count) {
        for (Tile *t in self.tiles) {
            t.frame = [Tile frameWithX:t.x y:t.y];
        }
        [self assignTouchDontTouchWithRowY:0];

    }


    [UIView animateWithDuration:DURATION_MOVE_DOWN delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{

        NSLog(@"anim");
        for (Tile *t in self.tiles) {
            if (t.y == NUM_TILES_Y - 1) {
                t.y = 0;
            }
            else {
                t.y++;
            }

            if (t.y == 0) {
                //move down
                //then place it to the top (in the completion handler)
                t.frame = [Tile frameWithX:t.x y:NUM_TILES_Y];
            }
            else {
                //move down
                t.frame = [Tile frameWithX:t.x y:t.y];
            }

        }

    } completion:^(BOOL finished) {

        if (finished) {

            for (Tile *t in self.tiles) {
                if (t.y == 0) {
                    t.frame = [Tile frameWithX:t.x y:t.y];
                }
            }
            [self assignTouchDontTouchWithRowY:0];


        }


    }];

}

答案 1 :(得分:0)

试试这个:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint touchPoint = [touch locationInView:self.view];
    if ([[movingView.layer presentationLayer] hitTest:touchPoint])
    {
        //Do stuff here
    }
}

我是从here

得到的