4

我有一个图层,我想在用户执行操作时显示,并在他完成后隐藏。如果用户再次执行该操作,则该层将再次显示。

为了让 UI 不会因为动画而发狂,我想要:

  • 淡出动画仅在一秒钟后开始(如果用户在开始之前执行操作,则会取消)
  • 如果用户在图层消失之前正在执行操作,则显示图层的淡入淡出动画从当前的淡出不透明度开始

做这个的最好方式是什么?

我试过了,但这不能正常工作(层闪烁时有很多噪音):

- (void)hideHintLayer:(bool)hide
{
  if(hide)
  {
    CABasicAnimation *animation = [CABasicAnimation animation];
    animation.beginTime = CACurrentMediaTime() + 1.0f;
    animation.duration = 1.0f;
    animation.fillMode = kCAFillModeForwards;
    animation.removedOnCompletion = NO;
    animation.keyPath = @"opacity";
    animation.fromValue = @(1.0f);
    animation.toValue = @(0.0f);
    [layer addAnimation:animation forKey:nil];
  }
  else
  {
    layer.opacity = 1.0f;
  }
}
4

1 回答 1

3

如果你想停止动画,你可以这样做

[layer removeAllAnimations];

如果您想alpha在动画隐藏视图期间知道当前(以便您可以反转动画,从正确的位置开始,您可以执行以下操作:

CALayer *presentationLayer = layer.presentationLayer;
CGFloat startingAlpha = presentationLayer.opacity;

然后,您可以将 alpha 设置为从startingAlpha1.0 到 1.0,以便在不闪烁屏幕的情况下为取消隐藏设置动画。

您可以使用基于块的动画来制作实际的动画,或者我想您可以使用CABasicAnimation,尽管我不确定您为什么会这样做。


因此,例如,您可以执行以下操作(在我的示例中,我有一个“显示”按钮)。我正在使用块动画,但我怀疑它也可以正常工作CABasicAnimation

- (IBAction)onPressShowButton:(id)sender
{
    [self showAndScheduleHide];
}

- (void)showAndScheduleHide
{
    [UIView animateWithDuration:1.0
                     animations:^{
                         self.containerView.alpha = 1.0;
                     }
                     completion:^(BOOL finished) {
                         [self scheduleHide];
                     }];
}

- (void)show
{
    [UIView animateWithDuration:1.0
                     animations:^{
                         self.containerView.alpha = 1.0;
                     }
                     completion:nil];
}

- (void)scheduleHide
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                                  target:self
                                                selector:@selector(startToHide)
                                                userInfo:nil
                                                 repeats:NO];
}

- (void)startToHide
{
    self.timer = nil;

    self.hiding = YES;

    [UIView animateWithDuration:5.0
                          delay:0.0
                        options:UIViewAnimationOptionAllowUserInteraction
                     animations:^{
                         self.containerView.alpha = 0.0;
                     }
                     completion:^(BOOL finished) {
                         self.hiding = NO;
                     }];
}

然后,您可以使用一些实用方法来反转它或重新安排正在进行的隐藏:

- (void)reverseAndPauseHide
{
    // if we have a "hide" scheduled, then cancel that

    if (self.timer)
    {
        [self.timer invalidate];
        self.timer = nil;
    }

    // if we have a hide in progress, then reverse it

    if (self.hiding)
    {
        [self.containerView.layer removeAllAnimations];

        CALayer *layer = self.containerView.layer.presentationLayer;
        CGFloat currentAlpha = layer.opacity;

        self.containerView.alpha = currentAlpha;

        [self show];
    }
}

然后,问题是您何时知道该调用它reverseAndPauseHide以及何时scheduleHide再次调用它。因此,例如,您可以处理触摸:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];

    [self reverseAndPauseHide];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];

    [self scheduleHide];
}
于 2013-01-22T01:05:52.537 回答