ОтклонитьModalViewController с переходом: слева направо
Я использовал хороший метод для отклонения моего модального контроллера:
[self dismissModalViewControllerWithTransition:2];
который делает переход слайда слева направо, как и контроллер навигации, чтобы открыть представление.
Поскольку этот метод является непубличным методом, apple не примет его. Как я могу запрограммировать этот вид анимации в моем коде (слайд слева направо, чтобы отклонить модальное представление и сдвинуть справа налево, чтобы представить модальное представление)?
Заранее спасибо
Ответы
Ответ 1
Я принял ответ от Safecase, но я хотел бы опубликовать свое окончательное решение здесь:
1) Чтобы представить контроллер модального представления с переходом справа налево, я написал следующий метод:
-(void) presentModalView:(UIViewController *)controller {
CATransition *transition = [CATransition animation];
transition.duration = 0.35;
transition.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromRight;
// NSLog(@"%s: self.view.window=%@", _func_, self.view.window);
UIView *containerView = self.view.window;
[containerView.layer addAnimation:transition forKey:nil];
[self presentModalViewController:controller animated:NO];
}
2) Чтобы отклонить модальный вид с переходом слайда слева направо:
-(void) dismissMe {
CATransition *transition = [CATransition animation];
transition.duration = 0.35;
transition.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromLeft;
// NSLog(@"%s: controller.view.window=%@", _func_, controller.view.window);
UIView *containerView = self.view.window;
[containerView.layer addAnimation:transition forKey:nil];
[self dismissModalViewControllerAnimated:NO];
}
Спасибо, ребята!
Ответ 2
Попробуйте следующее:
Я предполагаю, что вы отклоняете контроллер вида 2 из контроллера представления 1. В контроллере 2 вы используете этот
[self dismissModalViewControlleAnimated: NO]];
Теперь В первом представлении контроллера, в viewWillAppear: метод добавьте код
CATransition *animation = [CATransition animation];
[animation setDelegate:self];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setDuration:0.50];
[animation setTimingFunction:
[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.layer addAnimation:animation forKey:kCATransition];
Ответ 3
Этот класс Swift 4 ModalService
ниже представляет собой предварительно упакованное гибкое решение, которое можно отбросить в проект и вызвать из любого места, где это требуется. Этот класс выводит модальный вид сверху текущего представления из указанного направления, а затем перемещает его, чтобы показать исходное представление позади него, когда оно выходит. Если в настоящее время отображается presentingViewController
и modalViewController
, который вы создали и хотите отобразить, вы просто вызываете:
ModalService.present(modalViewController, presenter: presentingViewController)
Затем, чтобы убрать, вызовите:
ModalService.dismiss(modalViewController)
Это можно, конечно, вызывать из самого modalViewController как ModalService.dismiss(self)
. Обратите внимание, что отклонение не нужно вызывать из presentingViewController и не требует знания или ссылки на оригинальный presentingViewController.
Класс обеспечивает разумные значения по умолчанию, включая переход модального представления справа и слева. Это направление перехода можно настроить, передав направление, которое можно настроить как для входа, так и для выхода:
ModalService.present(modalViewController, presenter: presentingViewController, enterFrom: .left)
и
ModalService.dismiss(self, exitTo: .left)
Это может быть установлено как .left
, .right
, .top
и .bottom
. Вы также можете пройти индивидуальную продолжительность в секундах, если хотите:
ModalService.present(modalViewController, presenter: presentingViewController, enterFrom: .left, duration: 0.5)
и
ModalService.dismiss(self, exitTo: .left, duration: 2.0)
Голова кивает на @jcdmb для ответа Objective C на этот вопрос, который сформировал ядро решения в этом классе.
Здесь полный класс. Значения, возвращаемые частным transitionSubtype
, выглядят странно, но настроены таким образом преднамеренно. Вы должны протестировать наблюдаемое поведение, прежде чем приступать к необходимости "исправления".:)
import UIKit
class ModalService {
enum presentationDirection {
case left
case right
case top
case bottom
}
class func present(_ modalViewController: UIViewController,
presenter fromViewController: UIViewController,
enterFrom direction: presentationDirection = .right,
duration: CFTimeInterval = 0.3) {
let transition = CATransition()
transition.duration = duration
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionMoveIn
transition.subtype = ModalService.transitionSubtype(for: direction)
let containerView: UIView? = fromViewController.view.window
containerView?.layer.add(transition, forKey: nil)
fromViewController.present(modalViewController, animated: false)
}
class func dismiss(_ modalViewController: UIViewController,
exitTo direction: presentationDirection = .right,
duration: CFTimeInterval = 0.3) {
let transition = CATransition()
transition.duration = duration
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionReveal
transition.subtype = ModalService.transitionSubtype(for: direction, forExit: true)
if let layer = modalViewController.view?.window?.layer {
layer.add(transition, forKey: nil)
}
modalViewController.dismiss(animated: false)
}
private class func transitionSubtype(for direction: presentationDirection, forExit: Bool = false) -> String {
if (forExit == false) {
switch direction {
case .left:
return kCATransitionFromLeft
case .right:
return kCATransitionFromRight
case .top:
return kCATransitionFromBottom
case .bottom:
return kCATransitionFromTop
}
} else {
switch direction {
case .left:
return kCATransitionFromRight
case .right:
return kCATransitionFromLeft
case .top:
return kCATransitionFromTop
case .bottom:
return kCATransitionFromBottom
}
}
}
}