Как я могу начать реплицировать переход контроллера пользовательского вида, который Apple использует по умолчанию в iOS 7?
Используя переходы контроллера пользовательского представления iOS 7, я хочу добиться визуального эффекта, подобного переходу контроллера представления Apple по умолчанию в iOS 7.
(тот, где вы можете скользить, чтобы вытащить контроллер вида из стека, сдвинув его слева направо, где контроллер верхнего уровня сместится с верхней части другой с теневой и сдвигом навигационной панели.)
![enter image description here]()
У меня много трудностей с этим. Большинство обучающих программ для пользовательских контроллеров представлений имеют очень разные эффекты, чем значение по умолчанию, чтобы показать, что API способен отключить, но я хочу реплицировать этот.
В моем подклассе для реализации <UIViewControllerAnimatedTransitioning>
у меня есть следующий код для интерактивной анимации:
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
fromViewController.view.layer.shadowOffset = CGSizeMake(0.0, 0.0);
fromViewController.view.layer.shadowColor = [UIColor blackColor].CGColor;
fromViewController.view.layer.shadowRadius = 5.0;
fromViewController.view.layer.shadowOpacity = 0.5;
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
CGRect newFrame = fromViewController.view.frame;
newFrame.origin.x = CGRectGetWidth(fromViewController.view.bounds);
fromViewController.view.frame = newFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:!transitionContext.transitionWasCancelled];
}];
}
Тем не менее теневой код сильно задерживает его (даже если я использую новые методы snapshot
), и я не могу понять, как вообще манипулировать навигационной панелью.
Кто-нибудь пытался сделать что-то похожее на это и может предоставить пример кода?
Пример проекта для тестирования, если вы хотите: http://cl.ly/0B3q1b390x0D
Кредит objc.io для базового кода.
Ответы
Ответ 1
Установка shadowPath
значительно увеличивает производительность этой тени.
Просто добавьте это в свой метод animateTransition:
после того, как вы установили свойства тени. Это позволяет избежать дорогостоящего рендеринга, который обычно вызывает тень.
[fromViewController.view.layer setShadowPath:[[UIBezierPath bezierPathWithRect:fromViewController.view.bounds] CGPath]];
Я загрузил ваш образец проекта и сделал это, заикание теперь полностью исчезло.
Некоторая информация о том, что это делает здесь.
EDIT:
Ответ на манипулирование анимацией навигационной панели заключается в том, что она не выглядит так, как вы можете. Для этого вам нужно будет переопределить свой класс типа NavigationController с нуля. Адаптация перехода для панели навигации выполняется внутри контроллера контейнера (UINavigationController
) и не отображается в любом месте кода.
Ответ 2
Посмотрите ECSlidingViewController Я использовал его несколько раз, если вы понимаете, как это работает, вы можете легко реализовать что-то подобное.
Если вы хотите изобрести колесо, мой ответ бесполезен, извините.
Ответ 3
Я создаю эффект, используя Dynamics. Я создаю свой собственный подкласс ViewController со следующими методами.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil forMultipleDirections:(BOOL)isTwoDirections;
- (void)addVelocityForGesture:(UIPanGestureRecognizer *)recognizer;
- (UIDynamicItemBehavior*) itemBehaviourForView;
Затем я добавил физику и распознаватель жестов, чтобы обрабатывать жест панорамирования. чтобы он выглядел сверху, просто добавьте смещение тени.
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.parentViewController.view];
_gravity = [[UIGravityBehavior alloc] init];
_gravity.gravityDirection = CGVectorMake(-1.5, 0);
[_animator addBehavior:_gravity];
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.view]];
[collision addBoundaryWithIdentifier:@1 fromPoint:CGPointMake(0, 0) toPoint:CGPointMake(0, self.parentViewController.view.frame.size.height)];
[_animator addBehavior:collision];
[_gravity addItem:self.view];
UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.view]];
[itemBehavior setElasticity:0.2];
[_animator addBehavior:itemBehavior];
Вам потребуется больше методов для добавления скорости в соответствии с направлением панорамирования, тогда вам нужно будет найти точку, в которой вы хотите убрать или скрыть childViewController в зависимости от вашего варианта использования и т.д. Я сделал это и он работает очень хорошо для меня, поскольку он использует Dynamics, он просто поддерживает iOS7 +