4

ユーザーがアクションを実行したときに表示し、実行後に非表示にしたいレイヤーがあります。ユーザーがアクションを再度実行すると、レイヤーが再度表示されます。

UIがアニメーションで乱暴にならないようにするために、私は次のことを行います。

  • フェードアウトアニメーションは1秒後にのみ開始されます(開始する前にユーザーがアクションを実行するとキャンセルされます)
  • レイヤーが消える前にユーザーがアクションを実行している場合、レイヤーを表示するフェードインアニメーションは現在のフェードアウトの不透明度から始まります

これを行うための最良の方法は何ですか?

私はこれを試しましたが、これは正しく機能しません(レイヤーが点滅している多くのノイズ):

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

次に、アルファをstartingAlpha1.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 に答える