Подтвердить что ты не робот

Как представить контроллер представления справа налево в iOS с помощью Swift

Я использую presentViewController для представления нового экрана

let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)

Это представляет новый экран снизу вверх, но я хочу, чтобы он отображался справа налево без использования UINavigationController.

Я использую Xib вместо раскадровки, так как я могу это сделать?

4b9b3361

Ответ 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. Часто бывает удобнее просто представлять в режиме реального времени, особенно для необычных и сложных приложений. Тем не менее, это не сложно "добавить" навигационный контроллер.

  1. просто на раскадровке, перейдите к записи VC и нажмите "embed → in nav controller". Действительно, что это. Или же,

  2. в didFinishLaunchingWithOptions легко построить свой контроллер навигации, если вы предпочитаете

  3. вам даже не нужно хранить переменную где-либо, так как .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)