sourcetip

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

fileupload 2023. 10. 30. 21:12
반응형

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

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

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

이것은 아래에서 위로 새로운 화면을 보여주지만 나는 그것을 사용하지 않고 오른쪽에서 왼쪽으로 보여주길 원합니다.UINavigationController.

스토리보드 대신 Xib을 사용하고 있는데 어떻게 해야 하나요?

그것이 중요한 것이 아닙니다.xib아니면storyboard당신이 사용하고 있는.일반적으로 오른쪽에서 왼쪽으로의 전환은 보기 컨트롤러를 프레젠테이션으로 밀어 넣을 때 사용됩니다.UINavigiationController.

갱신하다

타이밍함수추가kCAMediaTimingFunctionEaseInEaseOut

GitHub에 Swift 4 구현이 추가된 샘플 프로젝트


스위프트 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.

현재/해체 코드 작성, 스위프트 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)
    }
}

모든 답을 읽고 올바른 해결책을 찾을 수 없습니다.올바른 방법은 제시된 VC 대리인을 위해 사용자 정의 UIViewController Animated Transitioning을 만드는 것입니다.

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

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보기 컨트롤러를 애니메이션화하는 데 사용됩니다.View Controller를 사용하여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)

사용자 지정 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)
        })
    }
}

이거 먹어봐요.

    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뷰 컨트롤러,dashboardWorkout자네 같은 경우에는

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

간단한 통화 후에:

let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromRight)

왼쪽에서 오른쪽으로:

let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromleft)

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

업데이트된 2022 구문

"빠른 수정" CAT 전환 방법을 사용하려면...

class AA: UIViewController

 func goToBB() {
    
    let bb = .. instantiateViewcontroller, storyboard etc .. as! AlreadyOnboardLogin
    
    let tr = CATransition()
    tr.duration = 0.25
    tr.type = CATransitionType.moveIn
    tr.subtype = CATransitionSubtype.fromRight
    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"를 클릭합니다.진짜 여기까지입니다.

아니면, 당신이 원한다면.

  1. 인에didFinishLaunchingWithOptionsnav 컨트롤러를 코드에 쉽게 추가할 수 있습니다.

  2. 당신은 그 변수를 어디에도 둘 필요가 없습니다..navigationController항상 속성으로 사용할 수 있습니다. - easy.

내비게이션 컨트롤러가 있으면 화면 간에 전환을 하는 것은 사소한 일입니다.

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

할 수 있습니다.pop.

또 문제가 생겼어요!하지만 그건 표준 사과 "듀얼 푸시" 효과를 줄 뿐입니다.

(이전의 것은 새 것이 미끄러지면서 더 낮은 속도로 미끄러집니다.)

일반적으로 그리고 놀랍게도, 여러분은 일반적으로 완전한 사용자 정의 전환을 위해 노력해야 합니다.

가장 단순하고 일반적인 이동/이동 전환만 원하더라도 전체 사용자 지정 전환을 수행해야 합니다.

다행히도, 이 QA에 보일러 플레이트 코드를 잘라 붙이기 위해서... https://stackoverflow.com/a/48081504/294884 . 2018년 새해 복 많이 받으세요!

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)

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]

이거 먹어봐요.

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)
    // Never Easy than this before :)
     // you just need to add a Static function for navigation transition
     // This Code is recommended for the view controller.
  
     public class CustomNavigation:  UIViewController {
            
            
            public override func loadView() {
                super.loadView();
                
            }
            public override func viewDidLoad() {
                super.viewDidLoad()
                // Do any additional setup after loading the view.
            }
            
            public override func viewDidAppear(_ animated: Bool) {
                super.viewDidAppear(true);
            }
        
        public static func segueNavToLeft(view: UIView) {
                let transition = CATransition()
                transition.duration = 0.3
                transition.type = CATransitionType.push
                transition.subtype = CATransitionSubtype.fromLeft
                transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
                view.window!.layer.add(transition, forKey: kCATransition)
            }
            
            public static func segueNavToRight(view: UIView) {
                let transition = CATransition()
                transition.duration = 0.3
                transition.type = CATransitionType.push
                transition.subtype = CATransitionSubtype.fromRight
                transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
                view.window!.layer.add(transition, forKey: kCATransition)
            }
            
        }
    
    
    
    // simply call in your viewcontroller:
     func moveToRight()  {
            
            CustomNavigation.segueNavToRight(view: view)
    
            let controller = self.storyboard?.instantiateViewController(withIdentifier: "id") as! YourViewController
            let navigationController = UINavigationController(rootViewController: YourViewController)
            navigationController.modalPresentationStyle = .fullScreen
            self.present(navigationController, animated: false, completion: nil)
            
          
        }

func moveToLeft() {

       CustomNavigation.segueNavToLeft(view: view)
        self.dismiss(animated: true, completion: nil)
} 
  1. 밀 때 회색 바탕
class RightToLeftPresentationController: UIPresentationController {
    lazy var blackView: UIView = {
        let view = UIView()
        view.frame = self.containerView?.bounds ?? .zero
        view.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.5)
        
        return view
    }()
    
    // MARK:- Presentation
    override func presentationTransitionWillBegin() {
        self.containerView?.addSubview(blackView)
        
        self.presentingViewController.transitionCoordinator?
            .animate(alongsideTransition: { _ in
                self.blackView.alpha = 0.5
            }, completion: nil)
    }
    
    // MARK:- Dismiss
    override func dismissalTransitionWillBegin() {
        UIView.animate(withDuration: 0.25) {
            self.blackView.alpha = 0
        }
    }

    override func dismissalTransitionDidEnd(_ completed: Bool) {
        if completed {
            blackView.removeFromSuperview()
        }
    }
}
  1. 지원 스토리보드
class RightToLeftPresentationSegue: UIStoryboardSegue {
    override func perform() {
        destination.modalPresentationStyle = .custom
        destination.transitioningDelegate = self
        source.present(destination, animated: true)
    }
}
extension RightToLeftPresentationSegue: UIViewControllerTransitioningDelegate {
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        let controller = RightToLeftPresentationController(presentedViewController: presented, presenting: presenting)
        presented.transitioningDelegate = controller
        
        return controller
    }
}
  1. support off(@hotjard 감사합니다)
extension RightToLeftPresentationController: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return RightToLeftTransition()
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return LeftToRightTransition()
    }
}
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)
        })
    }
}

CAT Transition()을 사용하여 볼 수 있는 "검은색" 전환을 보지 않고 Apple의 고전 애니메이션을 유지하고 싶다면 제게 효과가 있는 더 나은 솔루션을 제공합니다.단순히 popToViewController 메서드를 사용합니다.

필요한 뷰컨트롤러를 찾을 수 있습니다.

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

restoreIdentifier를 검색하여 필요한 보기컨트롤러를 찾을 수 있습니다.

주의: 예를 들어, 3개의 뷰 컨트롤러를 통해 탐색할 때 마지막에 도착하면 첫 번째를 팝업합니다.이 경우 popToViewController가 해당 컨트롤러를 덮어썼기 때문에 을(를) 잃게 됩니다.그건 그렇고 해결책이 있습니다. 나중에 필요한 VC인 popToView 컨트롤러 이전에 쉽게 저장할 수 있습니다.저한테는 아주 잘 통했어요.

언급URL : https://stackoverflow.com/questions/37722323/how-to-present-view-controller-from-right-to-left-in-ios-using-swift

반응형