[ios] 탐색 기반 앱에서 푸시 및 팝 애니메이션을 변경하는 방법

탐색 기반 응용 프로그램이 있고 푸시 및 팝 애니메이션의 애니메이션을 변경하고 싶습니다. 어떻게해야합니까?

2018 수정

이 질문에 대한 많은 답변이 있었으며 지금은 꽤 오래 걸렸습니다. 지금 가장 관련성이 있다고 생각되는 것에 대한 답변을 다시 선택했습니다. 다르게 생각하는 사람이 있으면 의견을 남겨주세요.



답변

탐색 기반 앱에서 푸시 및 팝 애니메이션을 변경하는 방법 …

2019 년에는 “최종 답변!”

전문:

iOS 개발에 익숙하지 않다고 가정 해보십시오. 혼란스럽게도 Apple은 쉽게 사용할 수있는 두 가지 전환을 제공합니다. “crossfade”와 “flip”이 있습니다.

그러나 “crossfade”와 “flip”은 쓸모가 없습니다. 그들은 결코 사용되지 않습니다. 애플이 왜이 두 가지 쓸모없는 전환을 제공했는지는 아무도 모른다!

그래서:

“슬라이드”와 같이 일반적인 일반적인 전환 을 수행하려고한다고 가정합니다 . 이 경우 엄청난 양의 작업을 수행해야합니다! .

이 작업은이 게시물에 설명되어 있습니다.

반복하기 만하면됩니다.

놀랍게도 : iOS를 사용하면 가장 단순하고 일반적인 일상 전환 (예 : 일반 슬라이드)을 원한다면 전체 사용자 정의 전환 을 구현하는 모든 작업 이 필요합니다 .

방법은 다음과 같습니다.

1. 당신은 관례가 필요합니다 UIViewControllerAnimatedTransitioning

  1. 당신은 자신의 부울이 필요합니다 popStyle. (튀어 나오거나 터지는가?)

  2. transitionDuration(사소한) 주요 전화를 포함해야합니다 .animateTransition

  3. 실제로 inside에 대해 두 가지 다른 루틴을 작성 해야합니다animateTransition . 하나는 푸시 용이고 다른 하나는 팝용입니다. 아마 그 이름 animatePushanimatePop. 내부 에서 두 루틴으로 animateTransition분기하십시오.popStyle

  4. 아래 예제는 간단한 이동 / 이동을 수행합니다.

  5. 당신 animatePushanimatePop일상에서. 당신은 해야한다 은 “보기”및 “보기에”를 얻는다. (이를 수행하는 방법은 코드 예제에 나와 있습니다.)

  6. 새로운 “to”보기 를 사용해야합니다 addSubview .

  7. 그리고 당신 completeTransition 애니메이션의 끝에서 전화 해야합니다

그래서 ..

  class SimpleOver: NSObject, UIViewControllerAnimatedTransitioning {

        var popStyle: Bool = false

        func transitionDuration(
            using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.20
        }

        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

            if popStyle {

                animatePop(using: transitionContext)
                return
            }

            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!

            let f = transitionContext.finalFrame(for: tz)

            let fOff = f.offsetBy(dx: f.width, dy: 55)
            tz.view.frame = fOff

            transitionContext.containerView.insertSubview(tz.view, aboveSubview: fz.view)

            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    tz.view.frame = f
            }, completion: {_ in
                    transitionContext.completeTransition(true)
            })
        }

        func animatePop(using transitionContext: UIViewControllerContextTransitioning) {

            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!

            let f = transitionContext.initialFrame(for: fz)
            let fOffPop = f.offsetBy(dx: f.width, dy: 55)

            transitionContext.containerView.insertSubview(tz.view, belowSubview: fz.view)

            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    fz.view.frame = fOffPop
            }, completion: {_ in
                    transitionContext.completeTransition(true)
            })
        }
    }

그리고 …

2. 뷰 컨트롤러에서 사용하십시오.

참고 : 이상하게도 “첫 번째”보기 컨트롤러 에서만이 작업을 수행해야합니다 . (아래에있는 것)

당신이 상단에 팝업 하나 , 아무것도 하지 마십시오 . 쉬운.

수업은 …

class SomeScreen: UIViewController {
}

된다 …

class FrontScreen: UIViewController,
        UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {

    let simpleOver = SimpleOver()


    override func viewDidLoad() {

        super.viewDidLoad()
        navigationController?.delegate = self
    }

    func navigationController(
        _ navigationController: UINavigationController,
        animationControllerFor operation: UINavigationControllerOperation,
        from fromVC: UIViewController,
        to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {

        simpleOver.popStyle = (operation == .pop)
        return simpleOver
    }
}

그게 다야.

정상적으로 정상적으로 밀고 터지십시오. 밀어 …

let n = UIStoryboard(name: "nextScreenStoryboardName", bundle: nil)
          .instantiateViewController(withIdentifier: "nextScreenStoryboardID")
          as! NextScreen
navigationController?.pushViewController(n, animated: true)

다음 화면에서 원하는 경우 팝업을 표시 할 수 있습니다.

class NextScreen: TotallyOrdinaryUIViewController {

    @IBAction func userClickedBackOrDismissOrSomethingLikeThat() {

        navigationController?.popViewController(animated: true)
    }
}


3.이 페이지에서 AnimatedTransitioning을 재정의하는 방법을 설명하는 다른 답변도 즐기십시오

AnimatedTransitioning요즘 iOS 앱 사용 방법에 대한 자세한 내용은 @AlanZeino 및 @elias 답변으로 스크롤하십시오 !


답변

나는 다음을했고 잘 작동합니다 .. 간단하고 이해하기 쉽습니다 ..

CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
//transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[[self navigationController] popViewControllerAnimated:NO];

그리고 똑같은 것도 ..


스위프트 3.0 버전 :

let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
self.navigationController?.view.layer.add(transition, forKey: nil)
_ = self.navigationController?.popToRootViewController(animated: false)


답변

이것이 내가 항상이 작업을 완료 한 방법입니다.

푸시의 경우 :

MainView *nextView=[[MainView alloc] init];
[UIView  beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController:nextView animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
[nextView release];

팝의 경우 :

[UIView  beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[UIView commitAnimations];

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:0.375];
[self.navigationController popViewControllerAnimated:NO];
[UIView commitAnimations];

나는 여전히 이것으로부터 많은 피드백을 얻으므로 어쨌든 애니메이션을 수행하는 Apple 권장 방법 인 애니메이션 블록을 사용하도록 업데이트 할 것입니다.

푸시의 경우 :

MainView *nextView = [[MainView alloc] init];
[UIView animateWithDuration:0.75
                         animations:^{
                             [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                             [self.navigationController pushViewController:nextView animated:NO];
                             [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
                         }];

팝의 경우 :

[UIView animateWithDuration:0.75
                         animations:^{
                             [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                             [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
                         }];
[self.navigationController popViewControllerAnimated:NO];


답변

푸시

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
//transition.subtype = kCATransitionFromTop;

[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:ViewControllerYouWantToPush animated:NO];

CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionFade;
//transition.subtype = kCATransitionFromTop;

[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popViewControllerAnimated:NO];


답변

@Magnus는 Swift (2.0)에 대해서만 대답합니다.

    let transition = CATransition()
    transition.duration = 0.5
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromTop
    self.navigationController!.view.layer.addAnimation(transition, forKey: nil)
    let writeView : WriteViewController = self.storyboard?.instantiateViewControllerWithIdentifier("WriteView") as! WriteViewController
    self.navigationController?.pushViewController(writeView, animated: false)

일부 주석 :

Segue와 함께이 작업을 수행 할 수 있습니다 . prepareForSegue또는 에서 구현하십시오 shouldPerformSegueWithIdentifier. 하나 기본 애니메이션도 그대로 유지됩니다. 이 문제를 해결하려면 스토리 보드로 이동하여 Segue를 클릭하고 ‘Animates’상자를 선택 취소하십시오. 그러나 이것은 IOS 9.0 이상의 앱을 제한합니다 (Xcode 7에서 가장 좋았습니다).

segue에서 수행 할 때 마지막 두 줄은 다음과 같이 바꿔야합니다.

self.navigationController?.popViewControllerAnimated(false)

내가 잘못 설정했지만 무시합니다.


답변

에 그 기억 스위프트 , 확장은 확실히 당신의 친구!

public extension UINavigationController {

    /**
     Pop current view controller to previous view controller.

     - parameter type:     transition animation type.
     - parameter duration: transition animation duration.
     */
    func pop(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
        self.addTransition(transitionType: type, duration: duration)
        self.popViewControllerAnimated(false)
    }

    /**
     Push a new view controller on the view controllers's stack.

     - parameter vc:       view controller to push.
     - parameter type:     transition animation type.
     - parameter duration: transition animation duration.
     */
    func push(viewController vc: UIViewController, transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
        self.addTransition(transitionType: type, duration: duration)
        self.pushViewController(vc, animated: false)
    }

    private func addTransition(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
        let transition = CATransition()
        transition.duration = duration
        transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.type = type
        self.view.layer.addAnimation(transition, forKey: nil)
    }

}


답변

Apple이 더 이상 앱을 승인하지 않기 때문에 개인 통화를 사용하는 것은 좋지 않습니다. 아마도 당신은 이것을 시도 할 수 있습니다 :

//Init Animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.50];


[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];

//Create ViewController
MyViewController *myVC = [[MyViewController alloc] initWith...];

[self.navigationController pushViewController:myVC animated:NO];
[myVC release];

//Start Animation
[UIView commitAnimations];