Как представить контроллер представления справа налево в iOS с помощью Swift
Я использую presentViewController для представления нового экрана
let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)
Это представляет новый экран снизу вверх, но я хочу, чтобы он отображался справа налево без использования UINavigationController
.
Я использую Xib вместо раскадровки, так как я могу это сделать?
Ответы
Ответ 1
Не имеет значения, используете ли вы xib
или storyboard
. Обычно переход справа налево используется, когда вы помещаете контроллер представления в существующий UINavigiationController
.
ОБНОВИТЬ
Добавлена функция синхронизации kCAMediaTimingFunctionEaseInEaseOut
Пример проекта с реализацией Swift 4 добавлен в GitHub
Свифт 3 и 4.2
let transition = CATransition()
transition.duration = 0.5
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
present(dashboardWorkout, animated: false, completion: nil)
ObjC
CATransition *transition = [[CATransition alloc] init];
transition.duration = 0.5;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.window.layer addAnimation:transition forKey:kCATransition];
[self presentViewController:dashboardWorkout animated:false completion:nil];
Swift 2.x
let transition = CATransition()
transition.duration = 0.5
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
view.window!.layer.addAnimation(transition, forKey: kCATransition)
presentViewController(dashboardWorkout, animated: false, completion: nil)
Похоже, animated
параметр в методе presentViewController
самом деле не имеет значения в этом случае пользовательского перехода. Он может иметь любое значение, true
или false
.
Ответ 2
Полный код для настоящего/увольнения, Swift 3
extension UIViewController {
func presentDetail(_ viewControllerToPresent: UIViewController) {
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
self.view.window!.layer.add(transition, forKey: kCATransition)
present(viewControllerToPresent, animated: false)
}
func dismissDetail() {
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
self.view.window!.layer.add(transition, forKey: kCATransition)
dismiss(animated: false)
}
}
Ответ 3
Вы также можете использовать пользовательский сегмент.
Swift 3
class SegueFromRight: UIStoryboardSegue
{
override func perform()
{
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIViewAnimationOptions.curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
}
)
}
}
Ответ 4
Прочитайте все ответы и не можете найти правильное решение. Правильный способ сделать это - создать пользовательский UIViewControllerAnimatedTransitioning для представленного делегата VC.
Таким образом, предполагается сделать больше шагов, но результат будет более настраиваемым и не будет иметь побочных эффектов, таких как переход от вида вместе с представленным видом.
Итак, предположим, у вас есть какой-то ViewController, и есть метод для представления
var presentTransition: UIViewControllerAnimatedTransitioning?
var dismissTransition: UIViewControllerAnimatedTransitioning?
func showSettings(animated: Bool) {
let vc = ... create new vc to present
presentTransition = RightToLeftTransition()
dismissTransition = LeftToRightTransition()
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
present(vc, animated: true, completion: { [weak self] in
self?.presentTransition = nil
})
}
presentTransition
и dismissTransition
используется для анимации ваших контроллеров представления. Итак, вы принимаете свой ViewController в UIViewControllerTransitioningDelegate
:
extension ViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return presentTransition
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return dismissTransition
}
}
Итак, последний шаг - создать свой собственный переход:
class RightToLeftTransition: NSObject, UIViewControllerAnimatedTransitioning {
let duration: TimeInterval = 0.25
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
let toView = transitionContext.view(forKey: .to)!
container.addSubview(toView)
toView.frame.origin = CGPoint(x: toView.frame.width, y: 0)
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
toView.frame.origin = CGPoint(x: 0, y: 0)
}, completion: { _ in
transitionContext.completeTransition(true)
})
}
}
class LeftToRightTransition: NSObject, UIViewControllerAnimatedTransitioning {
let duration: TimeInterval = 0.25
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let container = transitionContext.containerView
let fromView = transitionContext.view(forKey: .from)!
container.addSubview(fromView)
fromView.frame.origin = .zero
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseIn, animations: {
fromView.frame.origin = CGPoint(x: fromView.frame.width, y: 0)
}, completion: { _ in
fromView.removeFromSuperview()
transitionContext.completeTransition(true)
})
}
}
В этом контроллере представления кода представлен поверх текущего контекста, вы можете сделать ваши настройки с этой точки. Также вы можете увидеть, что пользовательский UIPresentationController
полезен (перейдите к использованию UIViewControllerTransitioningDelegate
)
Ответ 5
Попробуйте это,
let animation = CATransition()
animation.duration = 0.5
animation.type = kCATransitionPush
animation.subtype = kCATransitionFromRight
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
vc.view.layer.addAnimation(animation, forKey: "SwitchToView")
self.presentViewController(vc, animated: false, completion: nil)
Здесь vc
- viewcontroller, dashboardWorkout
в вашем случае.
Ответ 6
Если вы хотите использовать метод быстрого исправления CATransition....
class AA: UIViewController
func goToBB {
let bb = .. instantiateViewcontroller, storyboard etc .. as! AlreadyOnboardLogin
let tr = CATransition()
tr.duration = 0.25
tr.type = kCATransitionMoveIn // use "MoveIn" here
tr.subtype = kCATransitionFromRight
view.window!.layer.add(tr, forKey: kCATransition)
present(bb, animated: false)
bb.delegate, etc = set any other needed values
}
а потом...
func dismissingBB() {
let tr = CATransition()
tr.duration = 0.25
tr.type = kCATransitionReveal // use "Reveal" here
tr.subtype = kCATransitionFromLeft
view.window!.layer.add(tr, forKey: kCATransition)
dismiss(self) .. or dismiss(bb), or whatever
}
Все это, к сожалению, не совсем правильно :(
CATransition
не предназначен для этой работы.
Обратите внимание, что вы получите раздражающее перекрестное затухание черного цвета, которое, к сожалению, разрушает эффект.
Многие разработчики (как и я) действительно не любят использовать NavigationController
. Часто бывает удобнее просто представлять в режиме реального времени, особенно для необычных и сложных приложений. Тем не менее, это не сложно "добавить" навигационный контроллер.
-
просто на раскадровке, перейдите к записи VC и нажмите "embed → in nav controller". Действительно, что это. Или же,
-
в didFinishLaunchingWithOptions
легко построить свой контроллер навигации, если вы предпочитаете
-
вам даже не нужно хранить переменную где-либо, так как .navigationController
всегда доступен как свойство - легко.
На самом деле, когда у вас есть навигационный контроллер, тривиально выполнять переходы между экранами,
let nextScreen = instantiateViewController etc as! NextScreen
navigationController?
.pushViewController(nextScreen, animated: true)
и вы можете pop
Это, однако, только дает вам стандартный яблочный эффект "двойного толчка"...
(Старый скользит с меньшей скоростью, а новый скользит.)
Как правило, как ни удивительно, вам обычно приходится прилагать все усилия, чтобы сделать полный пользовательский переход.
Даже если вы просто хотите получить самый простой, самый распространенный переход при переходе/отключении, вы должны выполнить полный пользовательский переход.
К счастью, для этого есть некоторый шаблон для вырезания и вставки стандартного кода этого QA... fooobar.com/questions/33271/.... С новым годом 2018!
Ответ 7
Попробуй это.
let transition: CATransition = CATransition()
transition.duration = 0.3
transition.type = kCATransitionReveal
transition.subtype = kCATransitionFromLeft
self.view.window!.layer.addAnimation(transition, forKey: nil)
self.dismissViewControllerAnimated(false, completion: nil)
Ответ 8
текущий контроллер представления справа налево в iOS с помощью Swift
func FrkTransition()
{
let transition = CATransition()
transition.duration = 2
transition.type = kCATransitionPush
transitioningLayer.add(transition,forKey: "transition")
// Transition to "blue" state
transitioningLayer.backgroundColor = UIColor.blue.cgColor
transitioningLayer.string = "Blue"
}
Отказ от:
[https://developer.apple.com/documentation/quartzcore/catransition][1]
Ответ 9
UIView.animate(withDuration: 0.3, animations: {
self.view.frame = CGRect(x: 0, y: -(self.view.frame.height), width: self.view.frame.size.width, height: self.view.frame.size.height)
})
self.dismiss(animated: false, completion: nil)
Ответ 10
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
tabBarController?.view.layer.add(transition, forKey: kCATransition)
self.navigationController?.popToRootViewController(animated: true)
Ответ 11
импортируйте UIKit и создайте одно расширение для UIViewController:
extension UIViewController {
func transitionVc(vc: UIViewController, duration: CFTimeInterval, type: CATransitionSubtype) {
let customVcTransition = vc
let transition = CATransition()
transition.duration = duration
transition.type = CATransitionType.push
transition.subtype = type
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
present(customVcTransition, animated: false, completion: nil)
}}
после вызова simlpy:
let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromRight)
слева направо:
let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromleft)
Вы можете изменить продолжительность с вашей предпочтительной продолжительностью...
Ответ 12
У меня есть лучшее решение, которое сработало для меня, если вы хотите классифицировать классическую анимацию Apple, не увидев этот "черный" переход, который вы видите с помощью CATransition(). Просто используйте метод popToViewController.
Вы можете искать viewController, который вам нужен в
self.navigationController.viewControllers // Array of VC that contains all VC of current stack
Вы можете искать viewController, который вам нужен, ища его restoreIdentifier.
БУДЬТЕ ОСТОРОЖНЫ: например, если вы переходите через 3 контроллера вида, и когда вы дойдете до последнего, вы хотите поместить первый. В этом случае вы потеряете ссылку на эффективный контроллер просмотра SECOND, потому что popToViewController перезаписал его. Кстати, есть решение: вы можете легко сохранить перед popToViewcontroller, VC вам понадобится позже. Это сработало для меня очень хорошо.
Ответ 13
Это сработало для меня:
self.navigationController?.pushViewController(controller, animated: true)