web-dev-qa-db-ja.com

ナビゲーションバーのタイトルテキストの変更をアニメーション化する

私のアプリには、ユーザーがアプリのさまざまな「セクション」間をスワイプできるページビューコントローラーがあり、ナビゲーションバーの上部で、タイトルテキストをユーザーがpageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:を介してスワイプした新しいセクションに変更します。現在、アニメーションが完了すると、タイトルテキストが即座に変更されます。これをいくつかのアニメーション、微妙なフェードインおよびフェードアウト効果で改善したいと思います。

最初に[UIView animationWithDuration:...]を実装して、タイトルテキストの変更をアニメーション化しようとしましたが、アニメーション化されず、即座に更新されます。

次に、ユーザーがスクロールした距離に基づいて水平方向にスクロールし、次のセクションが画面に表示されるときに0アルファに達するときに、ナビゲーションバーのタイトルのアルファを更新できるかどうか疑問に思いました。そうすれば、すぐにできます。 0のときにテキストを変更してから、すぐに1アルファにフェードインします。しかし、スクロール位置が更新されたときに呼び出されるUIPageViewControllerDelegateのメソッドが表示されません。

可能であれば、フェードインとフェードアウトの代わりに、スワイプジェスチャを介してプッシュセグエから戻るときに発生するデフォルトのアニメーションのように、ナビゲーションバーのタイトルテキストの位置をフェードインおよび移動することができます。ユーザーがスクロールするときに古いセクションタイトルをスライドさせ、反対側に次のセクションタイトルを指定します。これにより、遷移が完了すると、前のセクションタイトルが画面外に表示され、新しいセクションタイトルが完全に中央に配置され、置換が完了します。ただし、これも、ユーザーがページビューコントローラーをどれだけスクロールしたかを正確に知る必要があります。

必要なアニメーションのいずれかを実装することは可能ですか?

15
Jordan H

異なるタイトル文字列間でアニメーション化する場合は、次を使用します。

CATransition *fadeTextAnimation = [CATransition animation];
fadeTextAnimation.duration = 0.5;
fadeTextAnimation.type = kCATransitionFade;

[self.navigationController.navigationBar.layer addAnimation: fadeTextAnimation forKey: @"fadeText"];
self.navigationItem.title = "My new title";

もちろん、期間を調整したり、タイミング機能を設定したりすることもできます。

さまざまな状況で機能する可能性のある他の種類のアニメーションもあります(@inorganikに感謝):

kCATransitionFade
kCATransitionMoveIn
kCATransitionPush
kCATransitionReveal
46
Ashley Mills

便宜上、SwiftのAshley Millsソリューション:

2016年11月16日更新Swift 3(n13に感謝)

let fadeTextAnimation = CATransition()
fadeTextAnimation.duration = 0.5
fadeTextAnimation.type = kCATransitionFade

navigationController?.navigationBar.layer.add(fadeTextAnimat‌​ion, forKey: "fadeText")
navigationItem.title = "test 123"

Swift 2.x

let fadeTextAnimation = CATransition()
fadeTextAnimation.duration = 0.5
fadeTextAnimation.type = kCATransitionFade

navigationController?.navigationBar.layer.addAnimation(fadeTextAnimation, forKey: "fadeText")
navigationItem.title = "test 123"

アシュリーに帽子をチップします!

解決策は、カスタムタイトルを作成し、ページビューコントローラーの非表示のscrollViewのデリゲートメソッドを使用してその位置をアニメーション化することです。張が述べたように、カスタムタイトルは単にself.navigationItem.titleView = customNavTitleLabel;

2
Jordan H

タイトルのみをアニメーション化する必要がある場合(ナビゲーションバー全体ではない)

カスタムタイトルコントロールを開発するリンク

Assign

  let titleView = UIAnimatedTitleView(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
 titleView.text = "Hello"

アニメーション

var flag = true

@objc private func animateNavigationTitle() {
            guard let titleView = navigationItem.titleView as? UIAnimatedTitleView else { return }

        let fadeTextAnimation = CATransition()
        fadeTextAnimation.duration = 0.5
        fadeTextAnimation.type = kCATransitionPush
        fadeTextAnimation.subtype = kCATransitionFromTop

        titleView.layer.add(fadeTextAnimation, forKey: "pushText")
        titleView.text = flag ? "Hello" : "Good buy" 
        flag = !flag
    }
1
Svitlana

最良の方法はこのカテゴリです。

@implementation UIViewController (ControllerNavigationEffects)

-(void) setNavigationTitleWithAnimation:(NSString *) title {
    if ([self.navigationItem.title isEqualToString:title]) {
        return;
    }
    @weakify(self);
    float duration = 0.2;
    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        @strongify(self);
        self.navigationItem.titleView.alpha = 0;
    } completion:^(BOOL finished) {}];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        @strongify(self);
        self.navigationItem.titleView = nil;
        self.navigationItem.title = title;

        [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.navigationItem.titleView.alpha = 1;
        } completion:nil];
    });
}

-(void) setNavigationTitleViewWithAnimation:(UIView *) titleView {
    if ([self.navigationItem.titleView isKindOfClass:[titleView class]]) {
        return;
    }
    @weakify(self);
    float duration = 0.2;

    CATransition *fadeTextAnimation = [CATransition animation];
    fadeTextAnimation.duration = duration;
    fadeTextAnimation.type = kCATransitionFade;

    [self.navigationController.navigationBar.layer addAnimation: fadeTextAnimation forKey: @"fadeText"];
    self.navigationItem.title = @"";


    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        @strongify(self);
        self.navigationItem.title = @"";
        self.navigationItem.titleView = titleView;

        [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.navigationItem.titleView.alpha = 1;
        } completion:nil];

    });
}
0
MCMatan