Swift를 사용하여 iOS에서 오른쪽에서 왼쪽으로 뷰 컨트롤러를 표시하는 방법


82

새 화면을 표시하기 위해 presentViewController를 사용하고 있습니다.

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

이것은 아래에서 위로 새로운 화면을 보여 주지만 UINavigationController.

스토리 보드 대신 Xib를 사용하고 있는데 어떻게 할 수 있습니까?


간단히 말해서 전체 답변 : stackoverflow.com/a/48081504/294884
Fattie

답변:


158

이 경우 그것은 중요하지 않습니다 xib또는 storyboard당신이 사용하고 있는지. 일반적으로 오른쪽에서 왼쪽으로의 전환은 뷰 컨트롤러를 발표자의 UINavigiationController.

최신 정보

타이밍 기능 추가 kCAMediaTimingFunctionEaseInEaseOut

샘플 프로젝트스위프트 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];


스위프트 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
사용자 지정 UIStoryboardSegue의 perform () 메서드 내에서 Swift3 코드를 사용하려고했습니다. 문제는 동일한 뷰에서 전환이 수행 된 다음 두 번째 뷰가 나타납니다. 그것에 대한 아이디어가 있습니까?
Devarshi

2
이 방법을 사용할 때 갑자기 소스 VC가 페이드 아웃됩니다. 페이드 효과를 제거하고 푸시 애니메이션과 같은 효과를 얻으려면 어떻게해야합니까?
Umair Afzal

1
@UmairAfzal 그게 창의 색상입니다, 당신은 그것을 피하기 위해 창의 색상을 변경해야합니다.
Abdul Rehman

어떻게 스위프트 3 UIModalPresentationStyle.overCurrentContext로 효과적으로 전환을 사용하는
Mamta

3
"animated"를 "true"로 설정하면 약간의 상향 애니메이션도 나타납니다. "false"로 설정하는 것이 좋습니다
Rebeloper

66

현재 / 해제를위한 완전한 코드, 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)
    }
}

1
좀 더 구체적으로 말씀해주세요. 더 설명하세요!
EMM

2
해산 기능도 있기 때문에 답변을 찬성합니다
Rebeloper

거기에 최고 중 하나!! 👌
Shyam

42

모든 답변을 읽고 올바른 해결책을 찾을 수 없습니다. 이를 수행하는 올바른 방법은 제시된 VC 델리게이트에 대해 사용자 정의 UIViewControllerAnimatedTransitioning을 만드는 것입니다.

따라서 더 많은 단계를 수행한다고 가정하지만 결과는 더 사용자 정의가 가능하며 제시된 뷰와 함께 뷰에서 이동하는 것과 같은 부작용이 없습니다.

따라서 일부 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)


잘 했어! 나는 한동안 모든 대답을 시도하고 있었는데 뭔가 옳지 않은 것이 있었다 ... 나는 심지어는 안되는 하나를 upvoted ...
Reimond Hill

제시된 VC를 닫을 때 dismiss (animated : true, completion : nil)을 호출합니까?
Reimond Hill

@ReimondHill 예, 저는 일반 dismissViewController를 사용하고 있습니다
HotJard

이것은 단연 최고의 솔루션입니다. 예, 조금 더 복잡하지만 견고하고 다양한 조건에서 깨지지 않습니다. 허용되는 대답은 해킹입니다.
mmh02

iPhone 7+, 8+, X, XMax를 제외한 모든 장치에서 완벽하게 작동합니다. 왜 그런지 아세요? vc가 전체 프레임을 차지하지 않습니다.
Umair Afzal

14

사용자 지정 segue를 사용할 수도 있습니다.

스위프트 5

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: UIView.AnimationOptions.curveEaseInOut,
               animations: {
                    dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
            },
                   completion: { finished in
                    src.present(dst, animated: false, completion: nil)
        })
    }
}

더 나은 응답은 현재 컨텍스트에 걸쳐 프레젠테이션에서 다른 사용 된 경우
하기 Varun Naharia

이 사용자 지정 segue를 해제해도 원래 segue 유형이 기본값으로 설정됩니다. 그 주위에 방법이 있습니까?
Alex Bailey

1
사용자 지정 segue는 훌륭하지만 스토리 보드 솔루션
일뿐입니다

7

이 시도,

    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귀하의 경우.


3
고마워요.하지만 다음 VC가 오른쪽에서 왼쪽으로 치우치는 대신 갑자기 나타납니다. I 변경된 애니메이션 기간하지만 여전히 같은
UMAIR 아프

4

"빠른 수정"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 항목으로 이동하여 "내비게이션 컨트롤러에 포함->"을 클릭합니다. 그게 다야. 또는,

  2. didFinishLaunchingWithOptions 당신이 선호하는 경우 탐색 컨트롤러를 구축하기 쉽습니다

  3. .navigationController항상 속성으로 사용할 수 있기 때문에 변수를 어디에도 유지할 필요가 없습니다 .

실제로 navigationController가 있으면 화면 사이를 전환하는 것이 간단합니다.

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

그리고 당신은 할 수 있습니다 pop .

그러나 그것은 당신에게 표준 애플 "듀얼 푸시"효과만을 제공합니다.

(오래된 것은 새로운 것이 미끄러짐에 따라 낮은 속도로 미끄러집니다.)

일반적으로 그리고 놀랍게도 일반적으로 완전한 사용자 지정 전환을 수행하기 위해 노력해야합니다.

가장 단순하고 가장 일반적인 이동 / 이동 전환 전환을 원하는 경우에도 전체 사용자 정의 전환을 수행해야합니다.

다행히도이 QA에 잘라내어 붙여 넣는 상용구 코드가 있습니다 ... https://stackoverflow.com/a/48081504/294884 . 새해 복 많이 받으세요 2018!


3

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)

원하는 기간으로 기간을 변경할 수 있습니다.


1

이 시도.

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
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)

애니메이션을위한 버튼 클릭 이벤트에 이것을 추가했습니다. 그것은 10.2 신속한 4. 엑스 코드에 나를 위해 작동
고추

0

Swift를 사용하여 iOS에서 오른쪽에서 왼쪽으로 뷰 컨트롤러 제공

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]


-1

CATransition ()을 사용하여 볼 수있는 "검은 색"전환을 보지 않고 Apple의 고전적인 애니메이션을 유지하려는 경우 저에게 효과가 있었던 더 나은 솔루션이 있습니다. popToViewController 메서드를 사용하기 만하면됩니다.

필요한 viewController를 찾을 수 있습니다.

self.navigationController.viewControllers // Array of VC that contains all VC of current stack

restoreIdentifier를 검색하여 필요한 viewController를 찾을 수 있습니다.

주의 : 예를 들어 3 개의 뷰 컨트롤러를 통해 탐색하고 마지막에 도착하면 첫 번째 뷰 컨트롤러를 표시합니다. 이 경우 popToViewController가 덮어 쓰기 때문에 유효한 SECOND 뷰 컨트롤러에 대한 참조를 잃게됩니다. BTW, 해결책이 있습니다 : popToViewcontroller 이전에 쉽게 저장할 수 있으며 나중에 필요한 VC를 저장할 수 있습니다. 그것은 나를 위해 아주 잘 작동했습니다.


-4

이것은 나를 위해 일했습니다.

self.navigationController?.pushViewController(controller, animated: true)

탐색 스택에 밀어 넣고 싶지 않았습니다.
Umair Afzal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.