রুটভিউ কনট্রোলার স্যুইচ ট্রানজিশন অ্যানিমেশন


125

একটি বিদ্যমান ভিউকন্ট্রোলারকে অ্যাপডিজিয়েটে নতুনের সাথে রুটভিউ কনট্রোলার হিসাবে প্রতিস্থাপন করার সময় কোনও ট্রানজিশন / অ্যানিমেশন প্রভাব রাখার কোনও উপায় আছে কি?

উত্তর:


272

আপনি rootViewControllerএকটি রূপান্তর অ্যানিমেশন ব্লক মধ্যে স্যুইচিং মোড়ানো করতে পারেন :

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionFlipFromLeft
                animations:^{ self.window.rootViewController = newViewController; }
                completion:nil];

5
ওহে ওলে, আমি এই পদ্ধতির চেষ্টা করেছি, এটি আংশিকভাবে কাজ করেছে, জিনিসটি আমার অ্যাপ্লিকেশনটি কেবল ল্যান্ডস্কেপ মোডে থাকবে, তবে রুটভিউ কনট্রোলার ট্রানজিশনটি দ্বারা, সদ্য-উপস্থাপিত ভিউ কন্ট্রোলার শুরুতে প্রতিকৃতিতে লোড হয় এবং দ্রুত ল্যান্ডস্কেপ মোডে ঘোরানো হয় the কীভাবে সমাধান করব?
ক্রিস চেন

4
আমি ক্রিস চেনের প্রশ্নের উত্তর দিয়েছি (আশা করি! সম্ভবত?) তার পৃথক প্রশ্নের এখানে: স্ট্যাকওভারফ্লো.com
প্রশ্নস

1
আরে আমি কি একই অ্যানিমেশনে একটি ধাক্কা ট্রানজিশন চাই তা অর্জন করতে পারি?
ব্যবহারকারী 1531343

14
আমি এটির সাথে কিছু সমস্যা লক্ষ্য করেছি, যথা: উপাদানগুলি / অলসভাবে বোঝা উপাদানগুলি ভুল জায়গায় প্রতিস্থাপিত। উদাহরণস্বরূপ, যদি আপনার বিদ্যমান রুট ভিসিতে নেভিগেশন বার না থাকে, তবে একটি নতুন ভিসিতে অ্যানিমেট করুন যার একটি রয়েছে, অ্যানিমেশনটি সম্পূর্ণ হয় এবং তখন ন্যাভি বারটি যুক্ত হয় is এটি মূর্খ দেখাচ্ছে - এটি কেন হতে পারে সে সম্পর্কে কোনও চিন্তা, এবং কী করা যেতে পারে?
anon_dev1234

1
আমি খুঁজে পেয়েছি যে newViewController.view.layoutIfNeeded()অ্যানিমেশন ব্লকের আগে কল করা অলস-বোঝা উপাদানগুলির সাথে সমস্যার সমাধান করে।
আরে

66

আমি এটি পেয়েছি এবং পুরোপুরি কাজ করে:

আপনার অ্যাপ্লিকেশনটিতে:

- (void)changeRootViewController:(UIViewController*)viewController {

    if (!self.window.rootViewController) {
        self.window.rootViewController = viewController;
        return;
    }

    UIView *snapShot = [self.window snapshotViewAfterScreenUpdates:YES];

    [viewController.view addSubview:snapShot];

    self.window.rootViewController = viewController;

    [UIView animateWithDuration:0.5 animations:^{
        snapShot.layer.opacity = 0;
        snapShot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
    } completion:^(BOOL finished) {
        [snapShot removeFromSuperview];
    }];
}

আপনার অ্যাপ্লিকেশন

 if (!app) { app = (AppDelegate *)[[UIApplication sharedApplication] delegate]; }
        [app changeRootViewController:newViewController];

ক্রেডিট:

https://gist.github.com/gimenete/53704124583b5df3b407


এই সমর্থন অটো স্ক্রিন ঘোরানো হয়?
উইংজারো

1
এই সমাধানটি আমার ক্ষেত্রে আরও ভাল কাজ করেছে। ট্রানজিশনওয়িথ ভিউ ব্যবহার করার সময় নতুন রুট ভিউ কন্ট্রোলারটি রূপান্তর সমাপ্ত হওয়ার আগ পর্যন্ত সঠিকভাবে ছড়িয়ে দেওয়া হয়েছিল। এই পদ্ধতির সাহায্যে নতুন রুট ভিউ কন্ট্রোলারটিকে উইন্ডোতে যুক্ত করা, বিছানো এবং তারপরে রূপান্তরিত করা যায়।
ফোস্টাহ

@ উইংজারো কিছুটা দেরি করে, তবে, এটি ইউআইভিউ.অ্যানিমেশনস (যাক, ঘোরানো সহ একটি সিজিএফাইন ট্রান্সফর্ম) বা কাস্টম সিএএনিমেশনের মাধ্যমে যেকোন ধরণের স্থানান্তরের অনুমতি দেয়।
ক্যান

41

আমি দ্রুত Jesusসা মসিহের উত্তর পোস্ট করছি। এটি ভিউকন্ট্রোলারের শনাক্তকারীটিকে একটি আর্গুমেন্ট হিসাবে গ্রহণ করে, স্টোরিবোর্ডের কাঙ্ক্ষিত ভিউকন্ট্রোলার থেকে লোড করে এবং অ্যানিমেশন সহ রুটভিউকন্ট্রোলার পরিবর্তন করে।

সুইফট 3.0 আপডেট:

  func changeRootViewController(with identifier:String!) {
    let storyboard = self.window?.rootViewController?.storyboard
    let desiredViewController = storyboard?.instantiateViewController(withIdentifier: identifier);

    let snapshot:UIView = (self.window?.snapshotView(afterScreenUpdates: true))!
    desiredViewController?.view.addSubview(snapshot);

    self.window?.rootViewController = desiredViewController;

    UIView.animate(withDuration: 0.3, animations: {() in
      snapshot.layer.opacity = 0;
      snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
      }, completion: {
        (value: Bool) in
        snapshot.removeFromSuperview();
    });
  }

সুইফট ২.২ আপডেট:

  func changeRootViewControllerWithIdentifier(identifier:String!) {
    let storyboard = self.window?.rootViewController?.storyboard
    let desiredViewController = storyboard?.instantiateViewControllerWithIdentifier(identifier);

    let snapshot:UIView = (self.window?.snapshotViewAfterScreenUpdates(true))!
    desiredViewController?.view.addSubview(snapshot);

    self.window?.rootViewController = desiredViewController;

    UIView.animateWithDuration(0.3, animations: {() in
      snapshot.layer.opacity = 0;
      snapshot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
      }, completion: {
        (value: Bool) in
        snapshot.removeFromSuperview();
    });
  }

  class func sharedAppDelegate() -> AppDelegate? {
    return UIApplication.sharedApplication().delegate as? AppDelegate;
  }

পরে, আপনার যে কোনও জায়গা থেকে খুব সাধারণ ব্যবহার রয়েছে:

let appDelegate = AppDelegate.sharedAppDelegate()
appDelegate?.changeRootViewControllerWithIdentifier("YourViewControllerID")

সুইফট 3.0 আপডেট

let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.changeRootViewController(with: "listenViewController")

25

সুইফট 2

UIView.transitionWithView(self.window!, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: {
  self.window?.rootViewController = anyViewController
}, completion: nil)

সুইফট 3, 4, 5

UIView.transition(with: self.window!, duration: 0.5, options: UIView.AnimationOptions.transitionFlipFromLeft, animations: {
  self.window?.rootViewController = anyViewController
}, completion: nil)

এক্সকোডটি আমার কোডটিকে এইভাবে স্থির করেছে: IV `` ইউআইভিউ.ট্রান্সিশন (এর সাথে: সেল্ফ.ভিউ.উইনডো! `` `
ভয়ঙ্কর

10

শুধু এই চেষ্টা করুন। আমার জন্য ভাল কাজ করে।

BOOL oldState = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
self.window.rootViewController = viewController;
[UIView transitionWithView:self.window duration:0.5 options:transition animations:^{
    //
} completion:^(BOOL finished) {
    [UIView setAnimationsEnabled:oldState];
}];

সম্পাদনা করুন:

এটা বরং ভালো.

- (void)setRootViewController:(UIViewController *)viewController
               withTransition:(UIViewAnimationOptions)transition
                   completion:(void (^)(BOOL finished))completion {
    UIViewController *oldViewController = self.window.rootViewController;
    [UIView transitionFromView:oldViewController.view 
                        toView:viewController.view
                      duration:0.5f
                       options:(UIViewAnimationOptions)(transition|UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews)
                    completion:^(BOOL finished) {
        self.window.rootViewController = viewController;
        if (completion) {
            completion(finished);
        }
    }];
}

আমি কেবলমাত্র রুট ভিসি স্যুইচ করার সময় আমার একটি অদ্ভুত ডিফল্ট অ্যানিমেশন ছিল। প্রথম সংস্করণটি আমার জন্য তা থেকে মুক্তি পেয়েছে।
জুহান_ ঘন্টা

দ্বিতীয় সংস্করণটি জুহান_এফ দ্বারা উল্লিখিত মতামত বিন্যাসটি প্রাণবন্ত করবে। যদি এটির প্রয়োজন না হয়, হয় অপসারণের সাথে পরীক্ষা করুন UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionLayoutSubviews, অথবা প্রথম সংস্করণ ব্যবহার করুন বা অন্য কোনও পদ্ধতি।
ftvs

3

অ্যাপ্লিকেশনটিতে পরে ট্রানজিশন ফ্লিপ করতে সমস্যা না হওয়ার পাশাপাশি স্ট্যাক থেকে পুরানো ভিউ সাফ করা ভাল

UIViewController *oldController=self.window.rootViewController;

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{ self.window.rootViewController = nav; }
                completion:^(BOOL finished) {
                    if(oldController!=nil)
                        [oldController.view removeFromSuperview];
                }];

2

সঠিক উত্তরটি হ'ল rootViewControllerআপনার উইন্ডোটির প্রতিস্থাপনের দরকার নেই । পরিবর্তে, একটি কাস্টম তৈরি করুন UIViewController, এটি একবার বরাদ্দ করুন এবং এটি একবারে একটি শিশু নিয়ামক প্রদর্শন করতে দিন এবং প্রয়োজনে এনিমেশন সহ এটি প্রতিস্থাপন করুন। আপনি নীচের কোডটির টুকরোটি একটি সূচনা পয়েন্ট হিসাবে ব্যবহার করতে পারেন:

সুইফট 3.0

import Foundation
import UIKit

/// Displays a single child controller at a time.
/// Replaces the current child controller optionally with animation.
class FrameViewController: UIViewController {

    private(set) var displayedViewController: UIViewController?

    func display(_ viewController: UIViewController, animated: Bool = false) {

        addChildViewController(viewController)

        let oldViewController = displayedViewController

        view.addSubview(viewController.view)
        viewController.view.layoutIfNeeded()

        let finishDisplay: (Bool) -> Void = {
            [weak self] finished in
            if !finished { return }
            oldViewController?.view.removeFromSuperview()
            oldViewController?.removeFromParentViewController()
            viewController.didMove(toParentViewController: self)
        }

        if (animated) {
            viewController.view.alpha = 0
            UIView.animate(
                withDuration: 0.5,
                animations: { viewController.view.alpha = 1; oldViewController?.view.alpha = 0 },
                completion: finishDisplay
            )
        }
        else {
            finishDisplay(true)
        }

        displayedViewController = viewController
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return displayedViewController?.preferredStatusBarStyle ?? .default
    }
}

এবং আপনি যেভাবে এটি ব্যবহার করছেন তা হ'ল:

...
let rootController = FrameViewController()
rootController.display(UINavigationController(rootViewController: MyController()))
window.rootViewController = rootController
window.makeKeyAndVisible()
...

উপরের উদাহরণটি প্রমাণ করে যে আপনি UINavigationControllerভিতরে বাসা বাঁধতে পারেন FrameViewControllerএবং এটি ঠিক কাজ করে। এই পদ্ধতির আপনাকে উচ্চ স্তরের অনুকূলিতকরণ এবং নিয়ন্ত্রণ দেয়। FrameViewController.display(_)আপনি আপনার উইন্ডোতে রুট কন্ট্রোলারটি প্রতিস্থাপন করতে যে কোনও সময় কেবল কল করুন এবং এটি আপনার পক্ষে সেই কাজটি করবে।


2

এটি সুইফট 3-র জন্য আপডেট this

func logOutAnimation() {
    let storyBoard = UIStoryboard.init(name: "SignIn", bundle: nil)
    let viewController = storyBoard.instantiateViewController(withIdentifier: "signInVC")
    UIView.transition(with: self.window!, duration: 0.5, options: UIViewAnimationOptions.transitionFlipFromLeft, animations: {
        self.window?.rootViewController = viewController
        self.window?.makeKeyAndVisible()
    }, completion: nil)
}

উপরের বিভিন্ন প্রশ্ন থেকে যে অংশটি অনুপস্থিত তা হ'ল

    self.window?.makeKeyAndVisible()

আশা করি এটি কাউকে সাহায্য করবে।


1

AppDelegate.h এ:

#define ApplicationDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)]

আপনার নিয়ামক মধ্যে:

[UIView transitionWithView:self.window
                  duration:0.5
                   options:UIViewAnimationOptionTransitionFlipFromLeft
                animations:^{
    ApplicationDelegate.window.rootViewController = newViewController;
    }
                completion:nil];

6
এটি স্বীকৃত উত্তর হিসাবে একই, বিন্যাসটি ভুল ব্যতীত। কেন বিরক্ত হও?
jrturton

1
এটি কোনও ভিউ বা ভিউকন্ট্রোলারে থাকার উপর নির্ভর করে না। আপনার ভিউ এবং ভিউকন্ট্রোলারগুলি কতটা পুরু বা পাতলা হতে চান তার ক্ষেত্রে সর্বাধিক পার্থক্যটি আরও দার্শনিক।
সর্বোচ্চ

0

আমি আমার প্রকল্পটি এটি ভালভাবে কাজ করে যা আমার প্রকল্পে প্রস্তাব করি এবং এটি আমাকে ভাল অ্যানিমেশন দেয়। আমি এই পোস্টে পাওয়া অন্যান্য প্রস্তাবগুলি পরীক্ষা করেছি, তবে তাদের কিছু প্রত্যাশার মতো কাজ করে না।

- (void)transitionToViewController:(UIViewController *)viewController withTransition:(UIViewAnimationOptions)transition completion:(void (^)(BOOL finished))completion {
// Reset new RootViewController to be sure that it have not presented any controllers
[viewController dismissViewControllerAnimated:NO completion:nil];

[UIView transitionWithView:self.window
                  duration:0.5f
                   options:transition
                animations:^{
                    for (UIView *view in self.window.subviews) {
                        [view removeFromSuperview];
                    }
                    [self.window addSubview:viewController.view];

                    self.window.rootViewController = viewController;
                } completion:completion];
}

0

দুর্দান্ত মিষ্টি অ্যানিমেশন (সুইফট 4.x দিয়ে পরীক্ষা করা):

extension AppDelegate {
   public func present(viewController: UIViewController) {
        guard let window = window else { return }
        UIView.transition(with: window, duration: 0.5, options: .transitionFlipFromLeft, animations: {
            window.rootViewController = viewController
        }, completion: nil)
    }
}

সাথে কল

guard let delegate = UIApplication.shared.delegate as? AppDelegate else { return }
delegate.present(viewController: UIViewController())
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.