it-swarm.com.ru

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

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

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

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

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

55
Umair Afzal

Неважно, используете ли вы xib или storyboard. Обычно переход справа налево используется, когда вы помещаете контроллер представления в UINavigiationController настоящего.

ОБНОВЛЕНИЕ

Добавлена ​​функция синхронизации kCAMediaTimingFunctionEaseInEaseOut

Пример проекта с добавлена ​​реализация Swift 4 в GitHub


Swift 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.

119
mrvincenzo

Полный код для подарка/отклонения, 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)
    }
}
36

Вы также можете использовать пользовательский переход.

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)
    }
    )
}
}
12
Photon Point

Прочитайте все ответы и не можете найти правильное решение. Правильный способ сделать это - создать пользовательский 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)

11
HotJard

Попробуй это,

    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
Lion

Если вы хотите использовать метод "быстрого исправления" 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 на самом деле не предназначен для этой работы.

Обратите внимание, что вы получите раздражающее cross fade to black, которое, к сожалению, разрушает эффект.


Многие разработчики (как и я) действительно не любят использовать NavigationController. Зачастую бывает удобнее просто представлять в режиме реального времени, особенно для необычных и сложных приложений. Тем не менее, нетрудно «добавить» навигационный контроллер.

  1. просто на раскадровке перейдите к записи VC и нажмите «embed -> in nav controller». На самом деле это все. Или же,

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

  3. вам даже не нужно хранить переменную где-либо, так как .navigationController всегда доступен как свойство - легко.

Действительно, когда у вас есть навигационный контроллер, тривиально выполнять переходы между экранами,

    let nextScreen = instantiateViewController etc as! NextScreen
    navigationController?
        .pushViewController(nextScreen, animated: true)

и вы можете pop.

Это, однако, только дает вам стандартный эффект Apple "двойной толчок" ...

(Старый скользит с меньшей скоростью, а новый скользит.)

Как правило, как ни удивительно, вам обычно приходится прилагать все усилия, чтобы сделать полный пользовательский переход.

Даже если вы просто хотите получить самый простой, самый распространенный переход при переходе/отключении, вы должны выполнить полный пользовательский переход.

К счастью, для этого есть некоторый шаблон кода в этом QA ... https://stackoverflow.com/a/48081504/294884 . С новым 2018 годом!

4
Fattie

Попробуй это.

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)
1
Ashwin Felix

представить контроллер вида справа налево в 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"
}

Refrence By: [ https://developer.Apple.com/documentation/quartzcore/catransition][1]

0
FURKAN VIJAPURA

импортируйте 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)

вы можете изменить продолжительность с вашей предпочтительной продолжительностью ...

0
Fabio
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)
0
Chilli