Анимация изменения текста заголовка навигационной панели
В моем приложении у меня есть контроллер просмотра страниц, который позволяет пользователю прокручивать между различными "разделами" приложения, а вверху - в панели навигации. Я меняю текст заголовка на новый раздел, который пользователь нажал через pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:
. В настоящий момент он мгновенно меняет текст заголовка, когда анимация завершена. Я хотел бы улучшить это с помощью некоторой анимации, тонкого эффекта затухания и выхода.
Сначала я попытался реализовать [UIView animationWithDuration:...]
для анимации изменения текста заголовка, но он не анимация и просто все еще мгновенно обновляется.
Затем я подумал, можно ли обновить альфа заголовка навигационной панели, когда пользователь прокручивает по горизонтали в зависимости от того, как далеко они прокручиваются, достигая 0 альфа, когда следующий раздел вот-вот появится на экране, затем Я могу мгновенно изменить текст, пока он равен 0, а затем быстро затухает до 1 альфа. Но я не вижу метод UIPageViewControllerDelegate
, который вызывается при обновлении положения прокрутки.
Если возможно, вместо того, чтобы просто затухать и исчезать, я мог бы исчезать, а также перемещать текстовую позицию заголовка в навигационной панели, как и анимация по умолчанию, которая возникает при навигации по нажатию клавиши с помощью жестового салфетки. Я бы сместил старый заголовок раздела, когда пользователь прокручивает и предоставляет следующий заголовок раздела с другой стороны, так что, когда переход завершается, заголовок предыдущего раздела выключен, а новый полностью центрирован, поэтому замена завершается. Но опять же это требует знания точно, сколько пользователь прокрутил контроллер просмотра страницы.
Возможно ли реализовать любую из желаемых анимаций?
Ответы
Ответ 1
Если вы хотите анимировать между различными строками заголовка, используйте следующее:
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
Ответ 2
Swift 5
let fadeTextAnimation = CATransition()
fadeTextAnimation.duration = 0.5
fadeTextAnimation.type = .fade
navigationController?.navigationBar.layer.add(fadeTextAnimation, forKey: "fadeText")
navigationItem.title = "test 123"
Для удобства решение Эшли Миллс в Swift:
16.11.2016 Обновлено для Swift 3 (спасибо n13)
let fadeTextAnimation = CATransition()
fadeTextAnimation.duration = 0.5
fadeTextAnimation.type = kCATransitionFade
navigationController?.navigationBar.layer.add(fadeTextAnimation, 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"
Я снимаю шляпу перед Эшли!
Ответ 3
Решение состоит в том, чтобы создать пользовательский заголовок и анимировать его позицию, используя скрытый метод делегирования прокрутки ViewView. Как сказал Чжан, пользовательское название просто self.navigationItem.titleView = customNavTitleLabel;
Ответ 4
Если вам нужно анимировать только заголовок (не всю панель навигации)
Разработать пользовательский контроль заголовка Ссылка, например
приписывать
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
}
Ответ 5
Найден наилучший способ в этой категории:
@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];
});
}