├── CodeSnapshot ├── 01.png ├── 02.png ├── 03.png ├── 04.png ├── 05.png ├── 06.png ├── 07.png ├── 08.png ├── 09.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 17.png ├── 18.png ├── 19.png ├── 20.png ├── 21.png ├── 22.png ├── 23.png ├── 24.png ├── 25.png ├── 26.png ├── 27.png ├── 28.png ├── 29.png └── 30.png ├── Figures ├── Push&Pop.gif ├── AlipayDonate.png ├── MaskAnimtion.gif ├── ModalTransition.gif ├── SlideAnimation.gif ├── ContainerVC VS Modal.png ├── ContainerVCTransition.mov.gif ├── Reference in Transition.png ├── The Anatomy of Transition.png ├── Truth behind BubbleTransition.gif ├── CustomContainerVCButtonTransition.gif └── Reference in Transition with Interactor.png ├── ScrollTabBarController ├── ScrollTabBarController │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Icon.png │ │ │ ├── Icon@2x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Icon-Small@3x.png │ │ │ ├── Icon-Spotlight-40@2x-1.png │ │ │ ├── Icon-Spotlight-40@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_me.imageset │ │ │ ├── tabbar_me@2x.png │ │ │ ├── tabbar_me@3x.png │ │ │ └── Contents.json │ │ ├── LaunchImage.launchimage │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@2x-1.png │ │ │ ├── LaunchImage-568h@2x.png │ │ │ ├── LaunchImage-568h@2x-1.png │ │ │ ├── LaunchImage-800-667h@2x.png │ │ │ ├── LaunchImage-800-Portrait-736h@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_meHL.imageset │ │ │ ├── tabbar_meHL@2x.png │ │ │ ├── tabbar_meHL@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_contacts.imageset │ │ │ ├── tabbar_contacts@2x.png │ │ │ ├── tabbar_contacts@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_discover.imageset │ │ │ ├── tabbar_discover@2x.png │ │ │ ├── tabbar_discover@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_wechat.imageset │ │ │ ├── tabbar_mainframe@2x.png │ │ │ ├── tabbar_mainframe@3x.png │ │ │ └── Contents.json │ │ ├── barbuttonicon_add.imageset │ │ │ ├── barbuttonicon_add.png │ │ │ ├── barbuttonicon_add@2x.png │ │ │ ├── barbuttonicon_add@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_wechatHL.imageset │ │ │ ├── tabbar_mainframeHL@2x.png │ │ │ ├── tabbar_mainframeHL@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_contactsHL.imageset │ │ │ ├── tabbar_contactsHL@2x.png │ │ │ ├── tabbar_contactsHL@3x.png │ │ │ └── Contents.json │ │ ├── tabbar_discoverHL.imageset │ │ │ ├── tabbar_discoverHL@2x.png │ │ │ ├── tabbar_discoverHL@3x.png │ │ │ └── Contents.json │ │ └── Brand Assets.launchimage │ │ │ └── Contents.json │ ├── ViewController.swift │ ├── SDETabBarVCDelegate.swift │ ├── Info.plist │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── AppDelegate.swift │ ├── ScrollTabBarController.swift │ └── SlideAnimationController.swift └── ScrollTabBarController.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── seedante.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ └── seedante.xcuserdatad │ ├── xcschemes │ ├── xcschememanagement.plist │ └── ScrollTabBarController.xcscheme │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── iOS10PushPop ├── iOS10PushPop.xcodeproj │ ├── xcuserdata │ │ └── seedante.xcuserdatad │ │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── iOS10PushPop.xcscheme │ └── project.xcworkspace │ │ ├── xcuserdata │ │ └── seedante.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ └── contents.xcworkspacedata └── InterruptibleTransition │ ├── ViewController.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── AppDelegate.swift │ ├── SDENavigationDelegate.swift │ └── InterruptibleNavigationController.swift ├── CustomModalTransition ├── CustomModalTransitionDemo.xcodeproj │ ├── xcuserdata │ │ └── seedante.xcuserdatad │ │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── CustomModalTransition.xcscheme │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── seedante.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── CustomModalTransition │ ├── SDEModalTransitionDelegate.swift │ ├── PresentingViewController.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── OverlayPresentationController.swift │ ├── PresentedViewController.swift │ ├── AppDelegate.swift │ ├── OverlayAnimationController.swift │ └── SlideAnimationController.swift ├── NavigationControllerTransition ├── NavigationControllerTransitionDemo.xcodeproj │ ├── xcuserdata │ │ └── seedante.xcuserdatad │ │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── NavigationControllerTransitionDemo.xcscheme │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── seedante.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── NavigationControllerTransitionDemo │ ├── PushViewController.swift │ ├── SDENavigationDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── AppDelegate.swift │ ├── PopViewController.swift │ └── SlideAnimationController.swift ├── CustomContainerVCTransition ├── CustomContainerVCTransition.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── seedante.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── seedante.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── CustomContainerVCTransition.xcscheme └── CustomContainerVCTransition │ ├── ViewController.swift │ ├── SDEPercentDrivenInteractiveTransition.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── AppDelegate.swift │ ├── ContainerTransitionDelegate.swift │ ├── SDETabBarViewController.swift │ └── SlideAnimationController.swift ├── CollectionViewControllerLayoutTransition ├── CollectionViewControllerLayoutTransition.xcodeproj │ ├── project.xcworkspace │ │ ├── xcuserdata │ │ │ └── seedante.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── contents.xcworkspacedata │ └── xcuserdata │ │ └── seedante.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── CollectionVCLayoutTransition.xcscheme └── CollectionViewControllerLayoutTransition │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── CollectionVCTestOne.swift │ └── CollectionVCTestTwo.swift └── README.md /CodeSnapshot/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/01.png -------------------------------------------------------------------------------- /CodeSnapshot/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/02.png -------------------------------------------------------------------------------- /CodeSnapshot/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/03.png -------------------------------------------------------------------------------- /CodeSnapshot/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/04.png -------------------------------------------------------------------------------- /CodeSnapshot/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/05.png -------------------------------------------------------------------------------- /CodeSnapshot/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/06.png -------------------------------------------------------------------------------- /CodeSnapshot/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/07.png -------------------------------------------------------------------------------- /CodeSnapshot/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/08.png -------------------------------------------------------------------------------- /CodeSnapshot/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/09.png -------------------------------------------------------------------------------- /CodeSnapshot/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/10.png -------------------------------------------------------------------------------- /CodeSnapshot/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/11.png -------------------------------------------------------------------------------- /CodeSnapshot/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/12.png -------------------------------------------------------------------------------- /CodeSnapshot/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/13.png -------------------------------------------------------------------------------- /CodeSnapshot/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/14.png -------------------------------------------------------------------------------- /CodeSnapshot/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/15.png -------------------------------------------------------------------------------- /CodeSnapshot/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/16.png -------------------------------------------------------------------------------- /CodeSnapshot/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/17.png -------------------------------------------------------------------------------- /CodeSnapshot/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/18.png -------------------------------------------------------------------------------- /CodeSnapshot/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/19.png -------------------------------------------------------------------------------- /CodeSnapshot/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/20.png -------------------------------------------------------------------------------- /CodeSnapshot/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/21.png -------------------------------------------------------------------------------- /CodeSnapshot/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/22.png -------------------------------------------------------------------------------- /CodeSnapshot/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/23.png -------------------------------------------------------------------------------- /CodeSnapshot/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/24.png -------------------------------------------------------------------------------- /CodeSnapshot/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/25.png -------------------------------------------------------------------------------- /CodeSnapshot/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/26.png -------------------------------------------------------------------------------- /CodeSnapshot/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/27.png -------------------------------------------------------------------------------- /CodeSnapshot/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/28.png -------------------------------------------------------------------------------- /CodeSnapshot/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/29.png -------------------------------------------------------------------------------- /CodeSnapshot/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CodeSnapshot/30.png -------------------------------------------------------------------------------- /Figures/Push&Pop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/Push&Pop.gif -------------------------------------------------------------------------------- /Figures/AlipayDonate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/AlipayDonate.png -------------------------------------------------------------------------------- /Figures/MaskAnimtion.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/MaskAnimtion.gif -------------------------------------------------------------------------------- /Figures/ModalTransition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/ModalTransition.gif -------------------------------------------------------------------------------- /Figures/SlideAnimation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/SlideAnimation.gif -------------------------------------------------------------------------------- /Figures/ContainerVC VS Modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/ContainerVC VS Modal.png -------------------------------------------------------------------------------- /Figures/ContainerVCTransition.mov.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/ContainerVCTransition.mov.gif -------------------------------------------------------------------------------- /Figures/Reference in Transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/Reference in Transition.png -------------------------------------------------------------------------------- /Figures/The Anatomy of Transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/The Anatomy of Transition.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Figures/Truth behind BubbleTransition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/Truth behind BubbleTransition.gif -------------------------------------------------------------------------------- /Figures/CustomContainerVCButtonTransition.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/CustomContainerVCButtonTransition.gif -------------------------------------------------------------------------------- /Figures/Reference in Transition with Interactor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/Figures/Reference in Transition with Interactor.png -------------------------------------------------------------------------------- /iOS10PushPop/iOS10PushPop.xcodeproj/xcuserdata/seedante.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransitionDemo.xcodeproj/xcuserdata/seedante.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo.xcodeproj/xcuserdata/seedante.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_me.imageset/tabbar_me@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_me.imageset/tabbar_me@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_me.imageset/tabbar_me@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_me.imageset/tabbar_me@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_meHL.imageset/tabbar_meHL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_meHL.imageset/tabbar_meHL@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_meHL.imageset/tabbar_meHL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_meHL.imageset/tabbar_meHL@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x-1.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage@2x-1.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-568h@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contacts.imageset/tabbar_contacts@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contacts.imageset/tabbar_contacts@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contacts.imageset/tabbar_contacts@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contacts.imageset/tabbar_contacts@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discover.imageset/tabbar_discover@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discover.imageset/tabbar_discover@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discover.imageset/tabbar_discover@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discover.imageset/tabbar_discover@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechat.imageset/tabbar_mainframe@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechat.imageset/tabbar_mainframe@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechat.imageset/tabbar_mainframe@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechat.imageset/tabbar_mainframe@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-568h@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-568h@2x-1.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/barbuttonicon_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/barbuttonicon_add.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechatHL.imageset/tabbar_mainframeHL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechatHL.imageset/tabbar_mainframeHL@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechatHL.imageset/tabbar_mainframeHL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechatHL.imageset/tabbar_mainframeHL@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-800-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-800-667h@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/barbuttonicon_add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/barbuttonicon_add@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/barbuttonicon_add@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/barbuttonicon_add@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contactsHL.imageset/tabbar_contactsHL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contactsHL.imageset/tabbar_contactsHL@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contactsHL.imageset/tabbar_contactsHL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contactsHL.imageset/tabbar_contactsHL@3x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discoverHL.imageset/tabbar_discoverHL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discoverHL.imageset/tabbar_discoverHL@2x.png -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discoverHL.imageset/tabbar_discoverHL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discoverHL.imageset/tabbar_discoverHL@3x.png -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS10PushPop/iOS10PushPop.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/iOS10PushPop/iOS10PushPop.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-800-Portrait-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/LaunchImage-800-Portrait-736h@3x.png -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS10PushPop/iOS10PushPop.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/ScrollTabBarController/ScrollTabBarController.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransitionDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransitionDemo.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CustomModalTransition/CustomModalTransitionDemo.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CustomContainerVCTransition/CustomContainerVCTransition.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/NavigationControllerTransition/NavigationControllerTransitionDemo.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seedante/iOS-ViewController-Transition-Demo/HEAD/CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition.xcodeproj/project.xcworkspace/xcuserdata/seedante.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_me.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_me@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_me@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_meHL.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_meHL@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_meHL@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discover.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_discover@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_discover@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechat.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_mainframe@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_mainframe@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contactsHL.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_contactsHL@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_contactsHL@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_discoverHL.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_discoverHL@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_discoverHL@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_wechatHL.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_mainframeHL@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_mainframeHL@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/barbuttonicon_add.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "barbuttonicon_add.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "barbuttonicon_add@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "barbuttonicon_add@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/tabbar_contacts.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tabbar_contacts@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "tabbar_contacts@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "template" 24 | } 25 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ScrollTabBarController 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /iOS10PushPop/iOS10PushPop.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOS10PushPop.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FD8D55E81C187C01001143EA 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition.xcodeproj/xcuserdata/seedante.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CollectionVCLayoutTransitionDemo 4 | // 5 | // Created by seedante on 15/12/23. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransitionDemo.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CustomModalTransition.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FD368ACD1C1F26C9001D204F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ScrollTabBarController.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FD8D55C81C1825AB001143EA 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CustomContainerVCTransition.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FD8AFED71C2B2A93008EC7F9 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/PushViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PushViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | NavigationControllerTransitionDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FD8D55E81C187C01001143EA 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CollectionVCLayoutTransition.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | FD8AFEB11C2AD954008EC7F9 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // iOS10PushPop 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | convenience init(red: Int, green: Int, blue: Int) { 13 | assert(red >= 0 && red <= 255, "Invalid red component") 14 | assert(green >= 0 && green <= 255, "Invalid green component") 15 | assert(blue >= 0 && blue <= 255, "Invalid blue component") 16 | 17 | self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0) 18 | } 19 | 20 | convenience init(netHex:Int) { 21 | self.init(red:(netHex >> 16) & 0xff, green:(netHex >> 8) & 0xff, blue:netHex & 0xff) 22 | } 23 | } 24 | 25 | class ViewController: UIViewController { 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | view.backgroundColor = UIColor(netHex: 0x007AFF) 30 | 31 | } 32 | 33 | @IBAction func pop(_ sender: AnyObject) { 34 | _ = self.navigationController?.popViewController(animated: true) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/SDENavigationDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationControllerDelegate.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SDENavigationDelegate: NSObject, UINavigationControllerDelegate { 12 | 13 | var interactive = false 14 | let interactionController = UIPercentDrivenInteractiveTransition() 15 | 16 | func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { 17 | let transitionType = SDETransitionType.navigationTransition(operation) 18 | return SlideAnimationController(type: transitionType) 19 | } 20 | 21 | func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?{ 22 | return interactive ? self.interactionController : nil 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // CustomContainerVCTransition 4 | // 5 | // Created by seedante on 15/12/24. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | let label = UILabel() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | // Do any additional setup after loading the view, typically from a nib. 18 | } 19 | 20 | override func viewWillAppear(_ animated: Bool) { 21 | super.viewWillAppear(animated) 22 | if label.superview == nil{ 23 | label.text = title 24 | label.sizeToFit() 25 | view.addSubview(label) 26 | 27 | label.translatesAutoresizingMaskIntoConstraints = false 28 | view.addConstraint(NSLayoutConstraint(item: view, attribute: .centerX, relatedBy: .equal, toItem: label, attribute: .centerX, multiplier: 1, constant: 0)) 29 | view.addConstraint(NSLayoutConstraint(item: view, attribute: .centerY, relatedBy: .equal, toItem: label, attribute: .centerY, multiplier: 1, constant: 0)) 30 | } 31 | 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/Brand Assets.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "ipad", 6 | "minimum-system-version" : "7.0", 7 | "extent" : "full-screen", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "landscape", 12 | "idiom" : "ipad", 13 | "minimum-system-version" : "7.0", 14 | "extent" : "full-screen", 15 | "scale" : "1x" 16 | }, 17 | { 18 | "orientation" : "landscape", 19 | "idiom" : "ipad", 20 | "minimum-system-version" : "7.0", 21 | "extent" : "full-screen", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "orientation" : "portrait", 26 | "idiom" : "iphone", 27 | "minimum-system-version" : "7.0", 28 | "scale" : "2x" 29 | }, 30 | { 31 | "orientation" : "portrait", 32 | "idiom" : "iphone", 33 | "minimum-system-version" : "7.0", 34 | "subtype" : "retina4", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "orientation" : "portrait", 39 | "idiom" : "ipad", 40 | "minimum-system-version" : "7.0", 41 | "extent" : "full-screen", 42 | "scale" : "1x" 43 | } 44 | ], 45 | "info" : { 46 | "version" : 1, 47 | "author" : "xcode" 48 | } 49 | } -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/SDEPercentDrivenInteractiveTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SDEPercentDrivenInteractiveTransition.swift 3 | // CustomContainerVCTransition 4 | // 5 | // Created by seedante on 15/12/27. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SDEPercentDrivenInteractiveTransition: NSObject, UIViewControllerInteractiveTransitioning { 12 | 13 | weak var containerTransitionContext: ContainerTransitionContext? 14 | 15 | func startInteractiveTransition(_ transitionContext: UIViewControllerContextTransitioning) { 16 | if let context = transitionContext as? ContainerTransitionContext{ 17 | containerTransitionContext = context 18 | containerTransitionContext?.activateInteractiveTransition() 19 | }else{ 20 | fatalError("\(transitionContext) is not class or subclass of ContainerTransitionContext") 21 | } 22 | } 23 | 24 | func updateInteractiveTransition(_ percentComplete: CGFloat){ 25 | containerTransitionContext?.updateInteractiveTransition(percentComplete) 26 | } 27 | 28 | func cancelInteractiveTransition(){ 29 | containerTransitionContext?.cancelInteractiveTransition() 30 | } 31 | 32 | func finishInteractiveTransition(){ 33 | containerTransitionContext?.finishInteractiveTransition() 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/SDEModalTransitionDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PresentTransitionDelegate.swift 3 | // CustomPresentationTransition 4 | // 5 | // Created by seedante on 15/12/17. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SDEModalTransitionDelegate: NSObject, UIViewControllerTransitioningDelegate { 12 | 13 | func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 14 | return OverlayAnimationController() 15 | //Or 16 | // let transitionType = SDETransitionType.modalTransition(.presentation) 17 | // return SlideAnimationController(type: transitionType) 18 | } 19 | 20 | func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 21 | return OverlayAnimationController() 22 | //Or 23 | // let transitionType = SDETransitionType.modalTransition(.dismissal) 24 | // return SlideAnimationController(type: transitionType) 25 | } 26 | 27 | func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { 28 | return OverlayPresentationController(presentedViewController: presented, presenting: presenting) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/SDETabBarVCDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SDETabBarControllerDelegate.swift 3 | // ScrollTabBarController 4 | // 5 | // Created by seedante on 15/12/20. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SDETabBarVCDelegate: NSObject, UITabBarControllerDelegate { 12 | 13 | var interactive = false 14 | let interactionController = UIPercentDrivenInteractiveTransition() 15 | 16 | func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?{ 17 | let fromIndex = tabBarController.viewControllers!.index(of: fromVC)! 18 | let toIndex = tabBarController.viewControllers!.index(of: toVC)! 19 | 20 | let tabChangeDirection: TabOperationDirection = toIndex < fromIndex ? TabOperationDirection.left : TabOperationDirection.right 21 | let transitionType = SDETransitionType.tabTransition(tabChangeDirection) 22 | let slideAnimationController = SlideAnimationController(type: transitionType) 23 | return slideAnimationController 24 | } 25 | 26 | func tabBarController(_ tabBarController: UITabBarController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning?{ 27 | return interactive ? interactionController : nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/PresentingViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PresentingViewController.swift 3 | // CustomPresentationTransition 4 | // 5 | // Created by seedante on 15/12/15. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PresentingViewController: UIViewController{ 12 | 13 | let presentTransitionDelegate = SDEModalTransitionDelegate() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | // Do any additional setup after loading the view. 18 | 19 | } 20 | 21 | override func didReceiveMemoryWarning() { 22 | super.didReceiveMemoryWarning() 23 | // Dispose of any resources that can be recreated. 24 | } 25 | 26 | /* 27 | .FullScreen 的时候,presentingView 的移除和添加由 UIKit 负责,在 presentation 转场结束后被移除,dismissal 转场结束时重新回到原来的位置; 28 | .Custom 的时候,presentingView 依然由 UIKit 负责,但 presentation 转场结束后不会被移除。 29 | */ 30 | 31 | // In a storyboard-based application, you will often want to do a little preparation before navigation 32 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 33 | // Get the new view controller using segue.destinationViewController. 34 | // Pass the selected object to the new view controller. 35 | let toVC = segue.destination as! PresentedViewController 36 | toVC.transitioningDelegate = presentTransitionDelegate 37 | toVC.modalPresentationStyle = .custom 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "Icon-Small.png", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "Icon-Small@2x.png", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "size" : "29x29", 27 | "idiom" : "iphone", 28 | "filename" : "Icon-Small@3x.png", 29 | "scale" : "3x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "Icon-Spotlight-40@2x-1.png", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "size" : "40x40", 39 | "idiom" : "iphone", 40 | "filename" : "Icon-Spotlight-40@3x.png", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "size" : "57x57", 45 | "idiom" : "iphone", 46 | "filename" : "Icon.png", 47 | "scale" : "1x" 48 | }, 49 | { 50 | "size" : "57x57", 51 | "idiom" : "iphone", 52 | "filename" : "Icon@2x.png", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "size" : "60x60", 57 | "idiom" : "iphone", 58 | "filename" : "Icon-60@2x.png", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "size" : "60x60", 63 | "idiom" : "iphone", 64 | "filename" : "Icon-60@3x.png", 65 | "scale" : "3x" 66 | } 67 | ], 68 | "info" : { 69 | "version" : 1, 70 | "author" : "xcode" 71 | } 72 | } -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | PUSH&POP 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/OverlayPresentationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OverlayPresentationController.swift 3 | // CustomPresentationTransition 4 | // 5 | // Created by seedante on 15/12/17. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class OverlayPresentationController: UIPresentationController { 12 | let dimmingView = UIView() 13 | 14 | override func presentationTransitionWillBegin() { 15 | containerView?.addSubview(dimmingView) 16 | 17 | let dimmingViewInitailWidth = containerView!.frame.width * 2 / 3, dimmingViewInitailHeight = containerView!.frame.height * 2 / 3 18 | dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5) 19 | dimmingView.center = containerView!.center 20 | dimmingView.bounds = CGRect(x: 0, y: 0, width: dimmingViewInitailWidth , height: dimmingViewInitailHeight) 21 | 22 | _ = presentedViewController.transitionCoordinator?.animate(alongsideTransition: { 23 | _ in 24 | self.dimmingView.bounds = self.containerView!.bounds 25 | }, completion: nil) 26 | } 27 | 28 | override func dismissalTransitionWillBegin() { 29 | _ = presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in 30 | self.dimmingView.alpha = 0.0 31 | }, completion: nil) 32 | } 33 | 34 | override func containerViewWillLayoutSubviews(){ 35 | dimmingView.center = containerView!.center 36 | dimmingView.bounds = containerView!.bounds 37 | 38 | let width = containerView!.frame.width * 2 / 3, height = containerView!.frame.height * 2 / 3 39 | presentedView?.center = containerView!.center 40 | presentedView?.bounds = CGRect(x: 0, y: 0, width: width, height: height) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CustomContainerVCTransition 4 | // 5 | // Created by seedante on 15/12/24. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | var containerVCDelegate: SDEContainerViewControllerDelegate? 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | window = UIWindow(frame: UIScreen.main.bounds) 20 | window?.rootViewController = configureRootViewController() 21 | window?.makeKeyAndVisible() 22 | return true 23 | } 24 | 25 | func configureRootViewController() -> UIViewController{ 26 | 27 | let subVC0 = ViewController() 28 | subVC0.view.backgroundColor = UIColor(red: 0.4, green: 0.8, blue: 1, alpha: 1) 29 | subVC0.title = "DC" 30 | let subVC1 = ViewController() 31 | subVC1.view.backgroundColor = UIColor(red: 0.1, green: 0.4, blue: 0.8, alpha: 1) 32 | subVC1.title = "Marvel" 33 | let subVC2 = ViewController() 34 | subVC2.view.backgroundColor = UIColor(red: 0.3, green: 0.8, blue: 0.4, alpha: 1) 35 | subVC2.title = "DHC" 36 | let subVC3 = ViewController() 37 | subVC3.view.backgroundColor = UIColor(red: 0.5, green: 0.4, blue: 0.5, alpha: 1) 38 | subVC3.title = "Image" 39 | 40 | let containerController = SDETabBarViewController(viewControllers: [subVC0 ,subVC1, subVC2, subVC3]) 41 | containerVCDelegate = SDEContainerViewControllerDelegate() 42 | containerController.containerTransitionDelegate = containerVCDelegate 43 | 44 | return containerController 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "LaunchImage-800-Portrait-736h@3x.png", 8 | "minimum-system-version" : "8.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "orientation" : "landscape", 14 | "idiom" : "iphone", 15 | "extent" : "full-screen", 16 | "minimum-system-version" : "8.0", 17 | "subtype" : "736h", 18 | "scale" : "3x" 19 | }, 20 | { 21 | "extent" : "full-screen", 22 | "idiom" : "iphone", 23 | "subtype" : "667h", 24 | "filename" : "LaunchImage-800-667h@2x.png", 25 | "minimum-system-version" : "8.0", 26 | "orientation" : "portrait", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "orientation" : "portrait", 31 | "idiom" : "iphone", 32 | "filename" : "LaunchImage@2x.png", 33 | "extent" : "full-screen", 34 | "minimum-system-version" : "7.0", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "extent" : "full-screen", 39 | "idiom" : "iphone", 40 | "subtype" : "retina4", 41 | "filename" : "LaunchImage-568h@2x.png", 42 | "minimum-system-version" : "7.0", 43 | "orientation" : "portrait", 44 | "scale" : "2x" 45 | }, 46 | { 47 | "orientation" : "portrait", 48 | "idiom" : "iphone", 49 | "filename" : "LaunchImage.png", 50 | "extent" : "full-screen", 51 | "scale" : "1x" 52 | }, 53 | { 54 | "orientation" : "portrait", 55 | "idiom" : "iphone", 56 | "filename" : "LaunchImage@2x-1.png", 57 | "extent" : "full-screen", 58 | "scale" : "2x" 59 | }, 60 | { 61 | "orientation" : "portrait", 62 | "idiom" : "iphone", 63 | "filename" : "LaunchImage-568h@2x-1.png", 64 | "extent" : "full-screen", 65 | "subtype" : "retina4", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/PresentedViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // CustomPresentationTransition 4 | // 5 | // Created by seedante on 15/12/15. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PresentedViewController: UIViewController{ 12 | 13 | let presentTransitionDelegate = SDEModalTransitionDelegate() 14 | @IBOutlet weak var dismissButton: UIButton! 15 | @IBOutlet weak var inputTextField: UITextField! 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | dismissButton.alpha = 0 20 | // Do any additional setup after loading the view, typically from a nib. 21 | } 22 | 23 | override func didReceiveMemoryWarning() { 24 | super.didReceiveMemoryWarning() 25 | // Dispose of any resources that can be recreated. 26 | } 27 | 28 | override func viewDidAppear(_ animated: Bool) { 29 | super.viewDidAppear(animated) 30 | let widthContraint = inputTextField.constraints.filter({constraint in 31 | constraint.identifier == "Width" 32 | }).first 33 | widthContraint?.constant = view.frame.width * 2 / 3 34 | 35 | UIView.animate(withDuration: 0.3, animations: { 36 | self.dismissButton.alpha = 1 37 | self.view.layoutIfNeeded() 38 | }) 39 | } 40 | 41 | @IBAction func dismiss(_ sender: AnyObject) { 42 | var applyTransform = CGAffineTransform( rotationAngle: 3 * CGFloat(M_PI)) 43 | applyTransform = applyTransform.scaledBy(x: 0.1, y: 0.1) 44 | 45 | let widthContraint = inputTextField.constraints.filter({constraint in 46 | constraint.identifier == "Width" 47 | }).first 48 | widthContraint?.constant = 0 49 | 50 | UIView.animate(withDuration: 0.4, animations: { 51 | self.dismissButton.transform = applyTransform 52 | self.view.layoutIfNeeded() 53 | }, completion: { _ in 54 | self.dismiss(animated: true, completion: nil) 55 | }) 56 | 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/CollectionVCTestOne.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewController.swift 3 | // CollectionVCLayoutTransitionDemo 4 | // 5 | // Created by seedante on 15/12/23. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CollectionVCTestOne: UICollectionViewController { 12 | 13 | let reuseIdentifier = "Cell" 14 | 15 | override func viewDidAppear(_ animated: Bool) { 16 | super.viewDidAppear(animated) 17 | let count = self.navigationController!.viewControllers.count 18 | self.title = "Level \(count)" 19 | } 20 | 21 | /* 22 | 进行布局转场时,数据源的数量(section 和 cell 数量)要保持一致,尽管你可以在中途修改数量,但是回到最初的 CollectionViewController 时会出错。 23 | */ 24 | // MARK: UICollectionViewDataSource 25 | override func numberOfSections(in collectionView: UICollectionView) -> Int { 26 | return 2 27 | } 28 | 29 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 30 | return 15 31 | } 32 | 33 | 34 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 35 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) 36 | if indexPath.section == 0{ 37 | cell.backgroundColor = UIColor.red 38 | }else{ 39 | cell.backgroundColor = UIColor.brown 40 | } 41 | 42 | return cell 43 | } 44 | 45 | //MARK: UICollectionViewDelegate 46 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 47 | //根据点击 cell 的位置来决定下一级的 CollectionView 的布局 48 | let layout = UICollectionViewFlowLayout() 49 | layout.itemSize = CGSize(width: indexPath.item * 10, height: indexPath.item * 10) 50 | layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 10) 51 | let nextCVC = CollectionVCTestOne(collectionViewLayout: layout) 52 | nextCVC.useLayoutToLayoutNavigationTransitions = true 53 | navigationController?.pushViewController(nextCVC, animated: true) 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ScrollTabBarController 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // iOS10PushPop 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CustomPresentationTransition 4 | // 5 | // Created by seedante on 15/12/15. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/ContainerTransitionDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContainerTransitionDelegate.swift 3 | // CustomContainerVCTransition 4 | // 5 | // Created by seedante on 15/12/26. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | import UIKit 9 | 10 | @objc protocol ContainerViewControllerDelegate{ 11 | //Swift don't support protocol object in protocol now. if you want to support interactive transition, set SDEContainerViewController's containerTransitionDelegate to class 'SDEContainerViewControllerDelegate', not protocol 'ContainerViewControllerDelegate' 12 | //var interactionController: UIViewControllerInteractiveTransitioning? 13 | func containerController(_ containerController: SDEContainerViewController, animationControllerForTransitionFromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? 14 | @objc optional func containerController(_ containerController: SDEContainerViewController, interactionControllerForAnimation animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? 15 | } 16 | 17 | class SDEContainerViewControllerDelegate: NSObject, ContainerViewControllerDelegate { 18 | 19 | var interactionController = SDEPercentDrivenInteractiveTransition() 20 | 21 | func containerController(_ containerController: SDEContainerViewController, animationControllerForTransitionFromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { 22 | let fromIndex = containerController.viewControllers!.index(of: fromVC)! 23 | let toIndex = containerController.viewControllers!.index(of: toVC)! 24 | let tabChangeDirection: TabOperationDirection = toIndex < fromIndex ? TabOperationDirection.left : TabOperationDirection.right 25 | let transitionType = SDETransitionType.tabTransition(tabChangeDirection) 26 | let slideAnimationController = SlideAnimationController(type: transitionType) 27 | return slideAnimationController 28 | } 29 | 30 | func containerController(_ containerController: SDEContainerViewController, interactionControllerForAnimation animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { 31 | return interactionController 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | @nonobjc func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/PopViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopViewController.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PopViewController: UIViewController { 12 | 13 | let edgePanGesture = UIScreenEdgePanGestureRecognizer() 14 | var navigationDelegate: SDENavigationDelegate? 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | navigationItem.title = "StackTop" 19 | // Do any additional setup after loading the view. 20 | edgePanGesture.edges = .left 21 | edgePanGesture.addTarget(self, action: #selector(PopViewController.handleEdgePanGesture(gesture:))) 22 | view.addGestureRecognizer(edgePanGesture) 23 | } 24 | 25 | override func didReceiveMemoryWarning() { 26 | super.didReceiveMemoryWarning() 27 | // Dispose of any resources that can be recreated. 28 | } 29 | 30 | func handleEdgePanGesture(gesture: UIScreenEdgePanGestureRecognizer){ 31 | let translationX = gesture.translation(in: view).x 32 | let translationBase: CGFloat = view.frame.width / 3 33 | let translationAbs = translationX > 0 ? translationX : -translationX 34 | let percent = translationAbs > translationBase ? 1.0 : translationAbs / translationBase 35 | switch gesture.state{ 36 | case .began: 37 | navigationDelegate = self.navigationController?.delegate as? SDENavigationDelegate 38 | navigationDelegate?.interactive = true 39 | _ = self.navigationController?.popViewController(animated: true) 40 | case .changed: 41 | navigationDelegate?.interactionController.update(percent) 42 | case .cancelled, .ended: 43 | if percent > 0.5{ 44 | navigationDelegate?.interactionController.finish() 45 | }else{ 46 | navigationDelegate?.interactionController.cancel() 47 | } 48 | navigationDelegate?.interactive = false 49 | default: break 50 | } 51 | } 52 | 53 | @IBAction func popMe(_ sender: Any) { 54 | _ = navigationController?.popViewController(animated: true) 55 | } 56 | 57 | deinit{ 58 | edgePanGesture.removeTarget(self, action: #selector(PopViewController.handleEdgePanGesture(gesture:))) 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/SDETabBarViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SDETabBarViewController.swift 3 | // CustomContainerVCTransition 4 | // 5 | // Created by seedante on 15/12/29. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. 11 | // Consider refactoring the code to use the non-optional operators. 12 | fileprivate func < (lhs: T?, rhs: T?) -> Bool { 13 | switch (lhs, rhs) { 14 | case let (l?, r?): 15 | return l < r 16 | case (nil, _?): 17 | return true 18 | default: 19 | return false 20 | } 21 | } 22 | 23 | 24 | class SDETabBarViewController: SDEContainerViewController { 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | //Configure Interactive Transiton 29 | let pangesture = UIPanGestureRecognizer(target: self, action: #selector(SDETabBarViewController.handlePan(_:))) 30 | view.addGestureRecognizer(pangesture) 31 | } 32 | 33 | func handlePan(_ gesture: UIPanGestureRecognizer){ 34 | if viewControllers == nil || viewControllers?.count < 2 || containerTransitionDelegate == nil || !(containerTransitionDelegate is SDEContainerViewControllerDelegate) { 35 | return 36 | } 37 | 38 | let delegate = containerTransitionDelegate as! SDEContainerViewControllerDelegate 39 | 40 | let translationX = gesture.translation(in: view).x 41 | let translationAbs = translationX > 0 ? translationX : -translationX 42 | let progress = translationAbs / view.frame.width 43 | switch gesture.state{ 44 | case .began: 45 | interactive = true 46 | let velocityX = gesture.velocity(in: view).x 47 | if velocityX < 0{ 48 | if selectedIndex < viewControllers!.count - 1{ 49 | selectedIndex += 1 50 | } 51 | }else{ 52 | if selectedIndex > 0{ 53 | selectedIndex -= 1 54 | } 55 | } 56 | case .changed: 57 | delegate.interactionController.updateInteractiveTransition(progress) 58 | case .cancelled, .ended: 59 | interactive = false 60 | if progress > 0.6{ 61 | delegate.interactionController.finishInteractiveTransition() 62 | }else{ 63 | delegate.interactionController.cancelInteractiveTransition() 64 | } 65 | default: break 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS-ViewController-Transition-Demo 2 | Update: 更新到了 Swift 3.0,意味着不再支持 iOS 7;依然在使用 Xcode 7 的用户可切换至 Swift 2.2 分支。 3 | 4 | [《iOS 视图控制器转场详解》](https://github.com/seedante/iOS-Note/wiki/ViewController-Transition)已发布到微信公众号「iOSDevTips」,这是配套 Demo,使用 Swift 实现。本文并非华丽的转场动画教程,相反,为了不让文章过于复杂和冗长,范例的转场动画效果都是入门级别的。为何弄这么简单的动画效果?转场动画=转场+动画,转场的部分与动画的部分是独立的,无论是简单的转场动画还是复杂的转场动画,他们在转场部分的复杂度几乎是一样的。文章着眼于探索视图控制器转场背后的机制,缺陷以及实现过程中的技巧与陷阱。 5 | 6 | 7 | ### 系统内建支持的转场 8 | 9 | 官方支持的四种转场: 10 | 11 | 1. UINavigationController 的 push 和 pop,Demo: NavigationControllerTransition,实现了交互控制。 12 | 2. UITabBarController 的 Tab 切换,Demo: ScrollTabBarController,实现了交互控制。 13 | 3. Modal 转场:presentation 和 dismissal,Demo: CustomModalTransition,当然也支持交互控制,但因为没有合适的交互手段,我在 Demo 里没有为这种转场实现交互控制。 14 | 4. UICollectionViewController 布局转场,Demo: CollectionViewControllerLayoutTransition,并非布局转换,而是 CollectionViewController 与 NavigationViewController 结合的转场,不支持交互控制。 15 | 16 | 17 | ### 自定义容器控制器转场 18 | 唯一算是有点技术含量的 Demo 是 CustomContainerVCTransition,系统并不支持自定义容器控制器的转场,这个话题其实在差不多2年前就有人讨论过, objc.io 在第12期动画专题里实现了[非交互控制的版本](https://www.objc.io/issues/12-animations/custom-container-view-controller-transitions/),并且把实现交互控制留给了读者,不过早已有读者完成了这道作业,依然是国外的开发者。如果你把 [WWDC 2013 Session 218:Custom Transitions Using View Controllers](https://developer.apple.com/videos/play/wwdc2013/218/) 和 [View Controller Programming Guide for iOS](https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/index.html#//apple_ref/doc/uid/TP40007457-CH2-SW1) 看个好几遍,自己再动手把主流的三种模式的转场动画都写一遍,即使是非常简单的动画,并且对协议有点感觉的话,到这个阶段基本上你该知道自定义容器控制器转场该怎么实现了,比较棘手的是交互控制,实际上 objc.io 在更早的 iOS 7专题里对这个话题有所涉及,objc.io 真是个宝库,不过另外一个关键的技术点在 Core Animation 文档里。objc.io 讨论这个话题时 Swift 还没发布,为了避免读者两头跑,我尝试了一个不同的动画效果从头探讨这个话题,如下: 19 | 20 | ![非交互转场](https://github.com/seedante/iOS-ViewController-Transition-Demo/blob/master/Figures/CustomContainerVCButtonTransition.gif) 21 | ![交互转场](https://github.com/seedante/iOS-ViewController-Transition-Demo/blob/master/Figures/ContainerVCTransition.mov.gif) 22 | 23 | 熟能生巧,转场动画多写几次就知道了整个转场过程,你会发现转场其实蛮简单的,如果不考虑交互控制以及使用第三方的动画控制器,即使实现自定义容器控制器转场十几行代码就可以搞定,在文章里给出了具体代码。转场动画最困难的往往是动画效果本身,这取决于你对动画基础的掌握以及经验。 24 | 25 | ### iOS 10: 全程可交互的转场动画 26 | 上个月的 [WWDC 2016 Session 216: Advances in UIKit Animations and Transitions](https://developer.apple.com/videos/play/wwdc2016/216/) 介绍了全新的交互动画 API,并在 iOS 10 中将其引入了转场协议,之前的转场动画在非交互与交互状态之间有明显的界限:如果以交互转场开始,尽管在交互结束后会切换到非交互状态,但之后无法再次切换到交互状态,只能等待其结束;如果以非交互转场开始,在转场动画结束前是无法切换到交互控制状态的,只能等待其结束。新的交互动画 API 打破了这种界限,使得转场动画全程都可以在这两种状态之间自由切换。 27 | 28 | 不过,转场协议本身已略显臃肿,iOS 10在此基础上又添加了多个 optional,使得转场协议看上去复杂无比。我实践一番后,发现依靠新的交互动画 API,在实现转场动画可全程在非交互与交互之间自由切换的基础上,可以大幅精简转场协议。 29 | 30 | 这部分的内容在[《iOS 视图控制器转场详解》](https://github.com/seedante/iOS-Note/wiki/ViewController-Transition)更新,Demo: iOS10PushPop,需要使用 Xcode 8。 31 | 32 | 全新的交互动画 API 可以用于普通动画的交互。我在 [ControlPanelAnimation](https://github.com/seedante/ControlPanelAnimation) 里演示了如何使用 UIView Animation 和这个新交互动画 API 实现普通动画的交互。 33 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/CollectionVCTestTwo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewControllerTestTwo.swift 3 | // CollectionViewControllerLayoutTransition 4 | // 5 | // Created by seedante on 16/1/7. 6 | // Copyright © 2016年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /* 12 | 通过单例的数据源来测试布局转场在修改数据源下的表现,测试表明,这很不稳定,建议不要这么做。在 storyboard 将类切换到 CollectionVCTestTwo 便可以测试这种情况 13 | */ 14 | class CollectionVCTestTwo: UICollectionViewController { 15 | 16 | var dataSource = CollectionViewDataSource.sharedInstance 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | self.collectionView?.dataSource = dataSource 21 | } 22 | 23 | override func didReceiveMemoryWarning() { 24 | super.didReceiveMemoryWarning() 25 | // Dispose of any resources that can be recreated. 26 | } 27 | 28 | override func viewDidAppear(_ animated: Bool) { 29 | super.viewDidAppear(animated) 30 | let count = self.navigationController!.viewControllers.count 31 | self.title = "Level \(count)" 32 | } 33 | 34 | //根据点击 cell 的位置来决定下一级的 CollectionView 的布局 35 | override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 36 | let layout = UICollectionViewFlowLayout() 37 | layout.itemSize = CGSize(width: indexPath.item * 10, height: indexPath.item * 10) 38 | layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 10) 39 | //随机更改 cell 的数量 40 | dataSource.cellCount = Int(UInt32(arc4random()) % UInt32(10)) + 5 41 | let nextCVC = CollectionVCTestTwo(collectionViewLayout: layout) 42 | nextCVC.useLayoutToLayoutNavigationTransitions = true 43 | navigationController?.pushViewController(nextCVC, animated: true) 44 | } 45 | } 46 | 47 | class CollectionViewDataSource:NSObject, UICollectionViewDataSource { 48 | 49 | let reuseIdentifier = "Cell" 50 | static let sharedInstance = CollectionViewDataSource() 51 | 52 | var sectionCount = 2 53 | var cellCount = 15 54 | 55 | private override init() {} 56 | 57 | func numberOfSections(in collectionView: UICollectionView) -> Int { 58 | return sectionCount 59 | } 60 | 61 | 62 | @objc func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 63 | return cellCount 64 | } 65 | 66 | @available(iOS 6.0, *) 67 | public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 68 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) 69 | if indexPath.section == 0{ 70 | cell.backgroundColor = UIColor.red 71 | }else{ 72 | cell.backgroundColor = UIColor.brown 73 | } 74 | 75 | return cell 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/SDENavigationDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SDENavigationDelegate.swift 3 | // iOS10PushPop 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIViewAnimatingPosition{ 12 | var description: String{ 13 | switch self { 14 | case .end: 15 | return "end" 16 | case .current: 17 | return "current" 18 | case .start: 19 | return "start" 20 | } 21 | } 22 | } 23 | 24 | @available(iOS 10.0, *) 25 | class SDENavigationDelegate: NSObject, UINavigationControllerDelegate, UIViewControllerAnimatedTransitioning { 26 | 27 | var operation: UINavigationControllerOperation = .push 28 | let duration: TimeInterval = 1 29 | 30 | // MARK: UINavigationControllerDelegate 31 | func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { 32 | self.operation = operation 33 | return self 34 | } 35 | 36 | // MARK: UIViewControllerAnimatedTransitioning 37 | /// If you change any of 'duration', keep two 'duration' same. 38 | var transitionAnimator: UIViewPropertyAnimator = UIViewPropertyAnimator(duration: 1, timingParameters: UISpringTimingParameters(dampingRatio: 1, initialVelocity: CGVector(dx: 1, dy: 0))) 39 | 40 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 41 | return duration 42 | } 43 | 44 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning){ 45 | let containerView = transitionContext.containerView 46 | guard let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from), 47 | let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) 48 | else { 49 | return 50 | } 51 | 52 | var translation = containerView.frame.width 53 | translation = operation == .push ? translation : -translation 54 | containerView.addSubview(toView) 55 | toView.center.x += translation 56 | 57 | transitionAnimator.addAnimations({ 58 | fromView.center.x -= translation 59 | toView.center.x -= translation 60 | }) 61 | 62 | transitionAnimator.addCompletion({ position in 63 | fromView.center.x = containerView.center.x 64 | toView.center.x = containerView.center.x 65 | 66 | let completed = position == .end ? true : false 67 | transitionContext.completeTransition(completed) 68 | print("TransitionAnimation complete at position: \(position.description)") 69 | }) 70 | transitionAnimator.startAnimation() 71 | print("Transition did start") 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/ScrollTabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollTabBarController.swift 3 | // ScrollTabBarController 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ScrollTabBarController: UITabBarController { 12 | 13 | private var panGesture: UIPanGestureRecognizer = UIPanGestureRecognizer() 14 | private let tabBarVCDelegate = SDETabBarVCDelegate() 15 | private var subViewControllerCount: Int{ 16 | let count = viewControllers != nil ? viewControllers!.count : 0 17 | return count 18 | } 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | delegate = tabBarVCDelegate 23 | self.tabBar.tintColor = UIColor.green 24 | 25 | panGesture.addTarget(self, action: #selector(ScrollTabBarController.handlePan(panGesture:))) 26 | view.addGestureRecognizer(panGesture) 27 | } 28 | 29 | override func didReceiveMemoryWarning() { 30 | super.didReceiveMemoryWarning() 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | func handlePan(panGesture: UIPanGestureRecognizer){ 35 | let translationX = panGesture.translation(in: view).x 36 | let translationAbs = translationX > 0 ? translationX : -translationX 37 | let progress = translationAbs / view.frame.width 38 | switch panGesture.state{ 39 | case .began: 40 | tabBarVCDelegate.interactive = true 41 | let velocityX = panGesture.velocity(in: view).x 42 | if velocityX < 0{ 43 | if selectedIndex < subViewControllerCount - 1{ 44 | selectedIndex += 1 45 | } 46 | }else { 47 | if selectedIndex > 0{ 48 | selectedIndex -= 1 49 | } 50 | } 51 | case .changed: 52 | tabBarVCDelegate.interactionController.update(progress) 53 | case .cancelled, .ended: 54 | /*这里有个小问题,转场结束或是取消时有很大几率出现动画不正常的问题。在8.1以上版本的模拟器中都有发现,7.x 由于缺乏条件尚未测试, 55 | 但在我的 iOS 9.2 的真机设备上没有发现,而且似乎只在 UITabBarController 的交互转场中发现了这个问题。在 NavigationController 暂且没发现这个问题, 56 | Modal 转场尚未测试,因为我在 Demo 里没给它添加交互控制功能。 57 | 58 | 测试不完整,具体原因也未知,不过解决手段找到了。多谢 @llwenDeng 发现这个 Bug 并且找到了解决手段。 59 | 解决手段是修改交互控制器的 completionSpeed 为1以下的数值,这个属性用来控制动画速度,我猜测是内部实现在边界判断上有问题。 60 | 这里其修改为0.99,既解决了 Bug 同时尽可能贴近原来的动画设定。 61 | */ 62 | if progress > 0.3{ 63 | tabBarVCDelegate.interactionController.completionSpeed = 0.99 64 | tabBarVCDelegate.interactionController.finish() 65 | }else{ 66 | //转场取消后,UITabBarController 自动恢复了 selectedIndex 的值,不需要我们手动恢复。 67 | tabBarVCDelegate.interactionController.completionSpeed = 0.99 68 | tabBarVCDelegate.interactionController.cancel() 69 | } 70 | tabBarVCDelegate.interactive = false 71 | default: break 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/OverlayAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OverlayAnimationController.swift 3 | // CustomPresentationTransition 4 | // 5 | // Created by seedante on 15/12/20. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class OverlayAnimationController: NSObject, UIViewControllerAnimatedTransitioning { 12 | 13 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 14 | return 0.3 15 | } 16 | 17 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 18 | let containerView = transitionContext.containerView 19 | guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 20 | return 21 | } 22 | 23 | let fromView = fromVC.view 24 | let toView = toVC.view 25 | let duration = self.transitionDuration(using: transitionContext) 26 | 27 | if toVC.isBeingPresented{ 28 | containerView.addSubview(toView!) 29 | let toViewWidth = containerView.frame.width * 2 / 3, toViewHeight = containerView.frame.height * 2 / 3 30 | toView?.center = containerView.center 31 | toView?.bounds = CGRect(x: 0, y: 0, width: 1, height: toViewHeight) 32 | 33 | if #available(iOS 8, *){ 34 | UIView.animate(withDuration: duration, delay: 0, options: .curveEaseInOut, animations: { 35 | toView?.bounds = CGRect(x: 0, y: 0, width: toViewWidth, height: toViewHeight) 36 | }, completion: {_ in 37 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 38 | }) 39 | }else{ 40 | // 文章里的示范代码是基于 iOS 7 以上的系统的,但是升级到 Swift 3.0 后,这段代码就没用了,仅对应文章里的旧代码。 41 | // 这段代码给 toView 添加了一个半透明的背景,在 iOS 8 中,这个背景由 OverlayPresentationController.swift 去添加。 42 | let dimmingView = UIView() 43 | containerView.insertSubview(dimmingView, belowSubview: toView!) 44 | dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5) 45 | dimmingView.center = containerView.center 46 | dimmingView.bounds = CGRect(x: 0, y: 0, width: toViewWidth, height: toViewHeight) 47 | UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: { 48 | dimmingView.bounds = containerView.bounds 49 | toView?.bounds = CGRect(x: 0, y: 0, width: toViewWidth, height: toViewHeight) 50 | }, completion: { _ in 51 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 52 | }) 53 | 54 | } 55 | } 56 | //Dismissal 转场中不要将 toView 添加到 containerView 57 | if fromVC.isBeingDismissed{ 58 | let fromViewHeight = fromView?.frame.height 59 | UIView.animate(withDuration: duration, animations: { 60 | fromView?.bounds = CGRect(x: 0, y: 0, width: 1, height: fromViewHeight!) 61 | }, completion: { _ in 62 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 63 | }) 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /iOS10PushPop/iOS10PushPop.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/iOS10PushPop.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/ScrollTabBarController.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransitionDemo.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/CustomModalTransition.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/CustomContainerVCTransition.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/NavigationControllerTransitionDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition.xcodeproj/xcuserdata/seedante.xcuserdatad/xcschemes/CollectionVCLayoutTransition.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/InterruptibleNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InterruptibleNavigationController.swift 3 | // iOS10PushPop 4 | // 5 | // Created by seedante on 16/6/28. 6 | // Copyright © 2016年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | @available(iOS 10.0, *) 13 | class InterruptibleNavigationController: UINavigationController 14 | { 15 | 16 | var pan = UIPanGestureRecognizer() 17 | var tap = UITapGestureRecognizer() 18 | var navigationDelegate: SDENavigationDelegate = SDENavigationDelegate() 19 | var fractionComplete: CGFloat = 0 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | // Do any additional setup after loading the view. 25 | pan.addTarget(self, action: #selector(InterruptibleNavigationController.handlePan(gesture:))) 26 | tap.addTarget(self, action: #selector(InterruptibleNavigationController.handleTap(gesture:))) 27 | view.addGestureRecognizer(pan) 28 | view.addGestureRecognizer(tap) 29 | 30 | delegate = navigationDelegate 31 | } 32 | 33 | func handleTap(gesture: UITapGestureRecognizer){ 34 | let animator = navigationDelegate.transitionAnimator 35 | 36 | switch gesture.state { 37 | case .ended, .cancelled: 38 | switch animator.state { 39 | case .active: 40 | animator.pauseAnimation() 41 | animator.isReversed = !(animator.isReversed) 42 | animator.startAnimation() 43 | default:break 44 | } 45 | default:break 46 | } 47 | } 48 | 49 | 50 | func handlePan(gesture: UIPanGestureRecognizer){ 51 | let animator = navigationDelegate.transitionAnimator 52 | 53 | let translationX = gesture.translation(in: view).x 54 | let operation: UINavigationControllerOperation = translationX > 0 ? .pop : .push 55 | let translationBase: CGFloat = view.frame.width 56 | let translationAbs = translationX > 0 ? translationX : -translationX 57 | let percent = translationAbs > translationBase ? 1.0 : translationX / translationBase 58 | 59 | switch gesture.state{ 60 | case .began: 61 | if animator.isRunning == false{ 62 | switch operation { 63 | case .pop: 64 | if viewControllers.count == 2{ 65 | popViewController(animated: true) 66 | } 67 | case .push: 68 | if viewControllers.count == 1{ 69 | let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "BlueVC") 70 | pushViewController(nextVC!, animated: true) 71 | } 72 | default:break 73 | } 74 | }else{ 75 | animator.pauseAnimation() 76 | fractionComplete = animator.fractionComplete 77 | } 78 | case .changed: 79 | if animator.isRunning{ 80 | animator.pauseAnimation() 81 | fractionComplete = animator.fractionComplete 82 | }else if animator.state == .active{ 83 | if operation == navigationDelegate.operation{ 84 | animator.fractionComplete = abs(percent) + fractionComplete 85 | }else{ 86 | animator.fractionComplete = fractionComplete - abs(percent) 87 | } 88 | } 89 | case .cancelled, .ended: 90 | if animator.state == .active{ 91 | if animator.fractionComplete < 0.3{ 92 | animator.isReversed = true 93 | } 94 | let velocityX = abs(gesture.velocity(in: view).x) / (view.frame.width * (1 - animator.fractionComplete)) 95 | let initialVelocity = CGVector(dx: velocityX, dy: 0) 96 | animator.continueAnimation(withTimingParameters: UISpringTimingParameters(dampingRatio: 0.9, initialVelocity: initialVelocity), durationFactor: 0) 97 | } 98 | default: break 99 | } 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController.xcodeproj/xcuserdata/seedante.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 67 | 68 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CollectionViewControllerLayoutTransition/CollectionViewControllerLayoutTransition/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /iOS10PushPop/InterruptibleTransition/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/SlideAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PushAndPopAnimationController.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum SDETransitionType{ 12 | case navigationTransition(UINavigationControllerOperation) 13 | case tabTransition(TabOperationDirection) 14 | case modalTransition(ModalOperation) 15 | } 16 | 17 | enum TabOperationDirection{ 18 | case left, right 19 | } 20 | 21 | enum ModalOperation{ 22 | case presentation, dismissal 23 | } 24 | 25 | class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning { 26 | 27 | private var transitionType: SDETransitionType 28 | 29 | init(type: SDETransitionType) { 30 | transitionType = type 31 | super.init() 32 | } 33 | 34 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 35 | return 0.3 36 | } 37 | 38 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 39 | let containerView = transitionContext.containerView 40 | guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 41 | return 42 | } 43 | 44 | let fromView = fromVC.view 45 | let toView = toVC.view 46 | 47 | var translation = containerView.frame.width 48 | var toViewTransform = CGAffineTransform.identity 49 | var fromViewTransform = CGAffineTransform.identity 50 | 51 | switch transitionType{ 52 | case .navigationTransition(let operation): 53 | translation = operation == .push ? translation : -translation 54 | toViewTransform = CGAffineTransform(translationX: translation, y: 0) 55 | fromViewTransform = CGAffineTransform(translationX: -translation, y: 0) 56 | case .tabTransition(let direction): 57 | translation = direction == .left ? translation : -translation 58 | fromViewTransform = CGAffineTransform(translationX: translation, y: 0) 59 | toViewTransform = CGAffineTransform(translationX: -translation, y: 0) 60 | case .modalTransition(let operation): 61 | translation = containerView.frame.height 62 | toViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? translation : 0)) 63 | fromViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? 0 : translation)) 64 | } 65 | 66 | switch transitionType{ 67 | case .modalTransition(let operation): 68 | switch operation{ 69 | case .presentation: containerView.addSubview(toView!) 70 | case .dismissal: break 71 | } 72 | default: containerView.addSubview(toView!) 73 | } 74 | 75 | toView?.transform = toViewTransform 76 | UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 77 | fromView?.transform = fromViewTransform 78 | toView?.transform = CGAffineTransform.identity 79 | }, completion: { finished in 80 | fromView?.transform = CGAffineTransform.identity 81 | toView?.transform = CGAffineTransform.identity 82 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 83 | }) 84 | } 85 | 86 | /* 87 | 下面这段被注释的代码是使用 Core Animation 来实现转场,在非交互转场时没有问题,在交互转场下会有点瑕疵,要达到完美要麻烦一点。 88 | 89 | 交互转场必须用 UIView Animtion API 才能实现完美的控制,其实并不是 Core Animation 做不到, 90 | 毕竟 UIView Animation 是基于 Core Animation 的,那为什么苹果的工程师在 WWDC 上说必须使用前者呢。 91 | 因为使用 Core Animation 来实现成本高啊,在转场中做到与 UIView Animation 同样的事情配置麻烦些,估计很多人都不会配置, 92 | 而且在交互转场中会比较麻烦,本来转场 API 已经分裂得够复杂了,老老实实用高级 API 吧。 93 | 94 | 上面说的 UIView Animation API 指的是带 completion 闭包的 API,使用 Core Animation 来实现这个闭包需要配置 95 | CATransaction,这就是麻烦的地方,还是用高级的 API 吧。 96 | 97 | 在自定义的容器控制器转场中,交互部分需要我们自己动手实现控制动画的进度,此时 使用 Core Animation 或 UIView Animation 98 | 区别不大,重点在于在手势中如何控制动画。 99 | */ 100 | 101 | // func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 102 | // let containerView = transitionContext.containerView 103 | // guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 104 | // return 105 | // } 106 | // 107 | // 108 | // let fromView = fromVC.view 109 | // let toView = toVC.view 110 | // 111 | // var translation = containerView.frame.width 112 | // var toViewTransform = CATransform3DIdentity 113 | // var fromViewTransform = CATransform3DIdentity 114 | // 115 | // switch transitionType{ 116 | // case .navigationTransition(let operation): 117 | // translation = operation == .push ? translation : -translation 118 | // toViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 119 | // fromViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 120 | // case .tabTransition(let direction): 121 | // translation = direction == .left ? translation : -translation 122 | // fromViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 123 | // toViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 124 | // case .modalTransition(let operation): 125 | // translation = containerView.frame.height 126 | // toViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? translation : 0), 0) 127 | // fromViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? 0 : translation), 0) 128 | // } 129 | // 130 | // switch transitionType{ 131 | // case .modalTransition(let operation): 132 | // switch operation{ 133 | // case .presentation: containerView.addSubview(toView!) 134 | // //在 dismissal 转场中,不要添加 toView,否则黑屏 135 | // case .dismissal: break 136 | // } 137 | // default: containerView.addSubview(toView!) 138 | // } 139 | // 140 | // let duration = transitionDuration(using: transitionContext) 141 | // CATransaction.setCompletionBlock({ 142 | // fromView?.layer.transform = CATransform3DIdentity 143 | // toView?.layer.transform = CATransform3DIdentity 144 | // transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 145 | // }) 146 | // 147 | // CATransaction.setAnimationDuration(duration) 148 | // CATransaction.begin() 149 | // 150 | // let toViewAnimation = CABasicAnimation(keyPath: "transform") 151 | // toViewAnimation.fromValue = NSValue.init(caTransform3D: toViewTransform) 152 | // toViewAnimation.toValue = NSValue.init(caTransform3D: CATransform3DIdentity) 153 | // toViewAnimation.duration = duration 154 | // toView?.layer.add(toViewAnimation, forKey: "move") 155 | // 156 | // let fromViewAnimation = CABasicAnimation(keyPath: "transform") 157 | // fromViewAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DIdentity) 158 | // fromViewAnimation.toValue = NSValue.init(caTransform3D: fromViewTransform) 159 | // fromViewAnimation.duration = duration 160 | // fromView?.layer.add(fromViewAnimation, forKey: "move") 161 | // 162 | // CATransaction.commit() 163 | // } 164 | 165 | } 166 | 167 | -------------------------------------------------------------------------------- /ScrollTabBarController/ScrollTabBarController/SlideAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PushAndPopAnimationController.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum SDETransitionType{ 12 | case navigationTransition(UINavigationControllerOperation) 13 | case tabTransition(TabOperationDirection) 14 | case modalTransition(ModalOperation) 15 | } 16 | 17 | enum TabOperationDirection{ 18 | case left, right 19 | } 20 | 21 | enum ModalOperation{ 22 | case presentation, dismissal 23 | } 24 | 25 | class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning { 26 | 27 | private var transitionType: SDETransitionType 28 | 29 | init(type: SDETransitionType) { 30 | transitionType = type 31 | super.init() 32 | } 33 | 34 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 35 | return 0.3 36 | } 37 | 38 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 39 | let containerView = transitionContext.containerView 40 | guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 41 | return 42 | } 43 | 44 | let fromView = fromVC.view 45 | let toView = toVC.view 46 | 47 | var translation = containerView.frame.width 48 | var toViewTransform = CGAffineTransform.identity 49 | var fromViewTransform = CGAffineTransform.identity 50 | 51 | switch transitionType{ 52 | case .navigationTransition(let operation): 53 | translation = operation == .push ? translation : -translation 54 | toViewTransform = CGAffineTransform(translationX: translation, y: 0) 55 | fromViewTransform = CGAffineTransform(translationX: -translation, y: 0) 56 | case .tabTransition(let direction): 57 | translation = direction == .left ? translation : -translation 58 | fromViewTransform = CGAffineTransform(translationX: translation, y: 0) 59 | toViewTransform = CGAffineTransform(translationX: -translation, y: 0) 60 | case .modalTransition(let operation): 61 | translation = containerView.frame.height 62 | toViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? translation : 0)) 63 | fromViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? 0 : translation)) 64 | } 65 | 66 | switch transitionType{ 67 | case .modalTransition(let operation): 68 | switch operation{ 69 | case .presentation: containerView.addSubview(toView!) 70 | case .dismissal: break 71 | } 72 | default: containerView.addSubview(toView!) 73 | } 74 | 75 | toView?.transform = toViewTransform 76 | UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 77 | fromView?.transform = fromViewTransform 78 | toView?.transform = CGAffineTransform.identity 79 | }, completion: { finished in 80 | fromView?.transform = CGAffineTransform.identity 81 | toView?.transform = CGAffineTransform.identity 82 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 83 | }) 84 | } 85 | 86 | /* 87 | 下面这段被注释的代码是使用 Core Animation 来实现转场,在非交互转场时没有问题,在交互转场下会有点瑕疵,要达到完美要麻烦一点。 88 | 89 | 交互转场必须用 UIView Animtion API 才能实现完美的控制,其实并不是 Core Animation 做不到, 90 | 毕竟 UIView Animation 是基于 Core Animation 的,那为什么苹果的工程师在 WWDC 上说必须使用前者呢。 91 | 因为使用 Core Animation 来实现成本高啊,在转场中做到与 UIView Animation 同样的事情配置麻烦些,估计很多人都不会配置, 92 | 而且在交互转场中会比较麻烦,本来转场 API 已经分裂得够复杂了,老老实实用高级 API 吧。 93 | 94 | 上面说的 UIView Animation API 指的是带 completion 闭包的 API,使用 Core Animation 来实现这个闭包需要配置 95 | CATransaction,这就是麻烦的地方,还是用高级的 API 吧。 96 | 97 | 在自定义的容器控制器转场中,交互部分需要我们自己动手实现控制动画的进度,此时 使用 Core Animation 或 UIView Animation 98 | 区别不大,重点在于在手势中如何控制动画。 99 | */ 100 | 101 | // func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 102 | // let containerView = transitionContext.containerView 103 | // guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 104 | // return 105 | // } 106 | // 107 | // 108 | // let fromView = fromVC.view 109 | // let toView = toVC.view 110 | // 111 | // var translation = containerView.frame.width 112 | // var toViewTransform = CATransform3DIdentity 113 | // var fromViewTransform = CATransform3DIdentity 114 | // 115 | // switch transitionType{ 116 | // case .navigationTransition(let operation): 117 | // translation = operation == .push ? translation : -translation 118 | // toViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 119 | // fromViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 120 | // case .tabTransition(let direction): 121 | // translation = direction == .left ? translation : -translation 122 | // fromViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 123 | // toViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 124 | // case .modalTransition(let operation): 125 | // translation = containerView.frame.height 126 | // toViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? translation : 0), 0) 127 | // fromViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? 0 : translation), 0) 128 | // } 129 | // 130 | // switch transitionType{ 131 | // case .modalTransition(let operation): 132 | // switch operation{ 133 | // case .presentation: containerView.addSubview(toView!) 134 | // //在 dismissal 转场中,不要添加 toView,否则黑屏 135 | // case .dismissal: break 136 | // } 137 | // default: containerView.addSubview(toView!) 138 | // } 139 | // 140 | // let duration = transitionDuration(using: transitionContext) 141 | // CATransaction.setCompletionBlock({ 142 | // fromView?.layer.transform = CATransform3DIdentity 143 | // toView?.layer.transform = CATransform3DIdentity 144 | // transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 145 | // }) 146 | // 147 | // CATransaction.setAnimationDuration(duration) 148 | // CATransaction.begin() 149 | // 150 | // let toViewAnimation = CABasicAnimation(keyPath: "transform") 151 | // toViewAnimation.fromValue = NSValue.init(caTransform3D: toViewTransform) 152 | // toViewAnimation.toValue = NSValue.init(caTransform3D: CATransform3DIdentity) 153 | // toViewAnimation.duration = duration 154 | // toView?.layer.add(toViewAnimation, forKey: "move") 155 | // 156 | // let fromViewAnimation = CABasicAnimation(keyPath: "transform") 157 | // fromViewAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DIdentity) 158 | // fromViewAnimation.toValue = NSValue.init(caTransform3D: fromViewTransform) 159 | // fromViewAnimation.duration = duration 160 | // fromView?.layer.add(fromViewAnimation, forKey: "move") 161 | // 162 | // CATransaction.commit() 163 | // } 164 | 165 | } 166 | 167 | -------------------------------------------------------------------------------- /CustomContainerVCTransition/CustomContainerVCTransition/SlideAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PushAndPopAnimationController.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum SDETransitionType{ 12 | case navigationTransition(UINavigationControllerOperation) 13 | case tabTransition(TabOperationDirection) 14 | case modalTransition(ModalOperation) 15 | } 16 | 17 | enum TabOperationDirection{ 18 | case left, right 19 | } 20 | 21 | enum ModalOperation{ 22 | case presentation, dismissal 23 | } 24 | 25 | class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning { 26 | 27 | fileprivate var transitionType: SDETransitionType 28 | 29 | init(type: SDETransitionType) { 30 | transitionType = type 31 | super.init() 32 | } 33 | 34 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 35 | return 0.3 36 | } 37 | 38 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 39 | let containerView = transitionContext.containerView 40 | guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 41 | return 42 | } 43 | 44 | let fromView = fromVC.view 45 | let toView = toVC.view 46 | 47 | var translation = containerView.frame.width 48 | var toViewTransform = CGAffineTransform.identity 49 | var fromViewTransform = CGAffineTransform.identity 50 | 51 | switch transitionType{ 52 | case .navigationTransition(let operation): 53 | translation = operation == .push ? translation : -translation 54 | toViewTransform = CGAffineTransform(translationX: translation, y: 0) 55 | fromViewTransform = CGAffineTransform(translationX: -translation, y: 0) 56 | case .tabTransition(let direction): 57 | translation = direction == .left ? translation : -translation 58 | fromViewTransform = CGAffineTransform(translationX: translation, y: 0) 59 | toViewTransform = CGAffineTransform(translationX: -translation, y: 0) 60 | case .modalTransition(let operation): 61 | translation = containerView.frame.height 62 | toViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? translation : 0)) 63 | fromViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? 0 : translation)) 64 | } 65 | 66 | switch transitionType{ 67 | case .modalTransition(let operation): 68 | switch operation{ 69 | case .presentation: containerView.addSubview(toView!) 70 | case .dismissal: break 71 | } 72 | default: containerView.addSubview(toView!) 73 | } 74 | 75 | toView?.transform = toViewTransform 76 | UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 77 | fromView?.transform = fromViewTransform 78 | toView?.transform = CGAffineTransform.identity 79 | }, completion: { finished in 80 | fromView?.transform = CGAffineTransform.identity 81 | toView?.transform = CGAffineTransform.identity 82 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 83 | }) 84 | } 85 | 86 | /* 87 | 下面这段被注释的代码是使用 Core Animation 来实现转场,在非交互转场时没有问题,在交互转场下会有点瑕疵,要达到完美要麻烦一点。 88 | 89 | 交互转场必须用 UIView Animtion API 才能实现完美的控制,其实并不是 Core Animation 做不到, 90 | 毕竟 UIView Animation 是基于 Core Animation 的,那为什么苹果的工程师在 WWDC 上说必须使用前者呢。 91 | 因为使用 Core Animation 来实现成本高啊,在转场中做到与 UIView Animation 同样的事情配置麻烦些,估计很多人都不会配置, 92 | 而且在交互转场中会比较麻烦,本来转场 API 已经分裂得够复杂了,老老实实用高级 API 吧。 93 | 94 | 上面说的 UIView Animation API 指的是带 completion 闭包的 API,使用 Core Animation 来实现这个闭包需要配置 95 | CATransaction,这就是麻烦的地方,还是用高级的 API 吧。 96 | 97 | 在自定义的容器控制器转场中,交互部分需要我们自己动手实现控制动画的进度,此时 使用 Core Animation 或 UIView Animation 98 | 区别不大,重点在于在手势中如何控制动画。 99 | */ 100 | 101 | // func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 102 | // let containerView = transitionContext.containerView 103 | // guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 104 | // return 105 | // } 106 | // 107 | // 108 | // let fromView = fromVC.view 109 | // let toView = toVC.view 110 | // 111 | // var translation = containerView.frame.width 112 | // var toViewTransform = CATransform3DIdentity 113 | // var fromViewTransform = CATransform3DIdentity 114 | // 115 | // switch transitionType{ 116 | // case .navigationTransition(let operation): 117 | // translation = operation == .push ? translation : -translation 118 | // toViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 119 | // fromViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 120 | // case .tabTransition(let direction): 121 | // translation = direction == .left ? translation : -translation 122 | // fromViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 123 | // toViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 124 | // case .modalTransition(let operation): 125 | // translation = containerView.frame.height 126 | // toViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? translation : 0), 0) 127 | // fromViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? 0 : translation), 0) 128 | // } 129 | // 130 | // switch transitionType{ 131 | // case .modalTransition(let operation): 132 | // switch operation{ 133 | // case .presentation: containerView.addSubview(toView!) 134 | // //在 dismissal 转场中,不要添加 toView,否则黑屏 135 | // case .dismissal: break 136 | // } 137 | // default: containerView.addSubview(toView!) 138 | // } 139 | // 140 | // let duration = transitionDuration(using: transitionContext) 141 | // CATransaction.setCompletionBlock({ 142 | // fromView?.layer.transform = CATransform3DIdentity 143 | // toView?.layer.transform = CATransform3DIdentity 144 | // transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 145 | // }) 146 | // 147 | // CATransaction.setAnimationDuration(duration) 148 | // CATransaction.begin() 149 | // 150 | // let toViewAnimation = CABasicAnimation(keyPath: "transform") 151 | // toViewAnimation.fromValue = NSValue.init(caTransform3D: toViewTransform) 152 | // toViewAnimation.toValue = NSValue.init(caTransform3D: CATransform3DIdentity) 153 | // toViewAnimation.duration = duration 154 | // toView?.layer.add(toViewAnimation, forKey: "move") 155 | // 156 | // let fromViewAnimation = CABasicAnimation(keyPath: "transform") 157 | // fromViewAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DIdentity) 158 | // fromViewAnimation.toValue = NSValue.init(caTransform3D: fromViewTransform) 159 | // fromViewAnimation.duration = duration 160 | // fromView?.layer.add(fromViewAnimation, forKey: "move") 161 | // 162 | // CATransaction.commit() 163 | // } 164 | 165 | } 166 | 167 | -------------------------------------------------------------------------------- /NavigationControllerTransition/NavigationControllerTransitionDemo/SlideAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PushAndPopAnimationController.swift 3 | // NavigationControllerTransitionDemo 4 | // 5 | // Created by seedante on 15/12/9. 6 | // Copyright © 2015年 seedante. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum SDETransitionType{ 12 | case navigationTransition(UINavigationControllerOperation) 13 | case tabTransition(TabOperationDirection) 14 | case modalTransition(ModalOperation) 15 | } 16 | 17 | enum TabOperationDirection{ 18 | case left, right 19 | } 20 | 21 | enum ModalOperation{ 22 | case presentation, dismissal 23 | } 24 | 25 | class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning { 26 | 27 | private var transitionType: SDETransitionType 28 | 29 | init(type: SDETransitionType) { 30 | transitionType = type 31 | super.init() 32 | } 33 | 34 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 35 | return 0.3 36 | } 37 | 38 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 39 | let containerView = transitionContext.containerView 40 | guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 41 | return 42 | } 43 | 44 | let fromView = fromVC.view 45 | let toView = toVC.view 46 | 47 | var translation = containerView.frame.width 48 | var toViewTransform = CGAffineTransform.identity 49 | var fromViewTransform = CGAffineTransform.identity 50 | 51 | switch transitionType{ 52 | case .navigationTransition(let operation): 53 | translation = operation == .push ? translation : -translation 54 | toViewTransform = CGAffineTransform(translationX: translation, y: 0) 55 | fromViewTransform = CGAffineTransform(translationX: -translation, y: 0) 56 | case .tabTransition(let direction): 57 | translation = direction == .left ? translation : -translation 58 | fromViewTransform = CGAffineTransform(translationX: translation, y: 0) 59 | toViewTransform = CGAffineTransform(translationX: -translation, y: 0) 60 | case .modalTransition(let operation): 61 | translation = containerView.frame.height 62 | toViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? translation : 0)) 63 | fromViewTransform = CGAffineTransform(translationX: 0, y: (operation == .presentation ? 0 : translation)) 64 | } 65 | 66 | switch transitionType{ 67 | case .modalTransition(let operation): 68 | switch operation{ 69 | case .presentation: containerView.addSubview(toView!) 70 | case .dismissal: break 71 | } 72 | default: containerView.addSubview(toView!) 73 | } 74 | 75 | toView?.transform = toViewTransform 76 | UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 77 | fromView?.transform = fromViewTransform 78 | toView?.transform = CGAffineTransform.identity 79 | }, completion: { finished in 80 | fromView?.transform = CGAffineTransform.identity 81 | toView?.transform = CGAffineTransform.identity 82 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 83 | }) 84 | } 85 | 86 | /* 87 | 下面这段被注释的代码是使用 Core Animation 来实现转场,在非交互转场时没有问题,在交互转场下会有点瑕疵,要达到完美要麻烦一点。 88 | 89 | 交互转场必须用 UIView Animtion API 才能实现完美的控制,其实并不是 Core Animation 做不到, 90 | 毕竟 UIView Animation 是基于 Core Animation 的,那为什么苹果的工程师在 WWDC 上说必须使用前者呢。 91 | 因为使用 Core Animation 来实现成本高啊,在转场中做到与 UIView Animation 同样的事情配置麻烦些,估计很多人都不会配置, 92 | 而且在交互转场中会比较麻烦,本来转场 API 已经分裂得够复杂了,老老实实用高级 API 吧。 93 | 94 | 上面说的 UIView Animation API 指的是带 completion 闭包的 API,使用 Core Animation 来实现这个闭包需要配置 95 | CATransaction,这就是麻烦的地方,还是用高级的 API 吧。 96 | 97 | 在自定义的容器控制器转场中,交互部分需要我们自己动手实现控制动画的进度,此时 使用 Core Animation 或 UIView Animation 98 | 区别不大,重点在于在手势中如何控制动画。 99 | */ 100 | 101 | // func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 102 | // let containerView = transitionContext.containerView 103 | // guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else{ 104 | // return 105 | // } 106 | // 107 | // 108 | // let fromView = fromVC.view 109 | // let toView = toVC.view 110 | // 111 | // var translation = containerView.frame.width 112 | // var toViewTransform = CATransform3DIdentity 113 | // var fromViewTransform = CATransform3DIdentity 114 | // 115 | // switch transitionType{ 116 | // case .navigationTransition(let operation): 117 | // translation = operation == .push ? translation : -translation 118 | // toViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 119 | // fromViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 120 | // case .tabTransition(let direction): 121 | // translation = direction == .left ? translation : -translation 122 | // fromViewTransform = CATransform3DMakeTranslation(translation, 0, 0) 123 | // toViewTransform = CATransform3DMakeTranslation(-translation, 0, 0) 124 | // case .modalTransition(let operation): 125 | // translation = containerView.frame.height 126 | // toViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? translation : 0), 0) 127 | // fromViewTransform = CATransform3DMakeTranslation(0, (operation == .presentation ? 0 : translation), 0) 128 | // } 129 | // 130 | // switch transitionType{ 131 | // case .modalTransition(let operation): 132 | // switch operation{ 133 | // case .presentation: containerView.addSubview(toView!) 134 | // //在 dismissal 转场中,不要添加 toView,否则黑屏 135 | // case .dismissal: break 136 | // } 137 | // default: containerView.addSubview(toView!) 138 | // } 139 | // 140 | // let duration = transitionDuration(using: transitionContext) 141 | // CATransaction.setCompletionBlock({ 142 | // fromView?.layer.transform = CATransform3DIdentity 143 | // toView?.layer.transform = CATransform3DIdentity 144 | // transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 145 | // }) 146 | // 147 | // CATransaction.setAnimationDuration(duration) 148 | // CATransaction.begin() 149 | // 150 | // let toViewAnimation = CABasicAnimation(keyPath: "transform") 151 | // toViewAnimation.fromValue = NSValue.init(caTransform3D: toViewTransform) 152 | // toViewAnimation.toValue = NSValue.init(caTransform3D: CATransform3DIdentity) 153 | // toViewAnimation.duration = duration 154 | // toView?.layer.add(toViewAnimation, forKey: "move") 155 | // 156 | // let fromViewAnimation = CABasicAnimation(keyPath: "transform") 157 | // fromViewAnimation.fromValue = NSValue.init(caTransform3D: CATransform3DIdentity) 158 | // fromViewAnimation.toValue = NSValue.init(caTransform3D: fromViewTransform) 159 | // fromViewAnimation.duration = duration 160 | // fromView?.layer.add(fromViewAnimation, forKey: "move") 161 | // 162 | // CATransaction.commit() 163 | // } 164 | 165 | } 166 | 167 | -------------------------------------------------------------------------------- /CustomModalTransition/CustomModalTransition/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | --------------------------------------------------------------------------------