├── Package.swift
├── IBAnimatableApp
├── Assets.xcassets
│ ├── Contents.json
│ ├── icon
│ │ ├── Contents.json
│ │ ├── add.imageset
│ │ │ ├── add.pdf
│ │ │ └── Contents.json
│ │ ├── back.imageset
│ │ │ ├── back.pdf
│ │ │ └── Contents.json
│ │ ├── done.imageset
│ │ │ ├── done.pdf
│ │ │ └── Contents.json
│ │ ├── email.imageset
│ │ │ ├── email.pdf
│ │ │ └── Contents.json
│ │ ├── home.imageset
│ │ │ ├── home.pdf
│ │ │ └── Contents.json
│ │ ├── left.imageset
│ │ │ ├── left-1.pdf
│ │ │ └── Contents.json
│ │ ├── lists.imageset
│ │ │ ├── lists.pdf
│ │ │ └── Contents.json
│ │ ├── menu.imageset
│ │ │ ├── menu.pdf
│ │ │ └── Contents.json
│ │ ├── more.imageset
│ │ │ ├── more.pdf
│ │ │ └── Contents.json
│ │ ├── right.imageset
│ │ │ ├── right.pdf
│ │ │ └── Contents.json
│ │ ├── filter.imageset
│ │ │ ├── filter.pdf
│ │ │ └── Contents.json
│ │ ├── gender.imageset
│ │ │ ├── gender.pdf
│ │ │ └── Contents.json
│ │ ├── groups.imageset
│ │ │ ├── groups.pdf
│ │ │ └── Contents.json
│ │ ├── logo.imageset
│ │ │ ├── logo@2x.png
│ │ │ ├── logo@3x.png
│ │ │ └── Contents.json
│ │ ├── logout.imageset
│ │ │ ├── logout.pdf
│ │ │ └── Contents.json
│ │ ├── checked.imageset
│ │ │ ├── checked.pdf
│ │ │ └── Contents.json
│ │ ├── profile.imageset
│ │ │ ├── profile.pdf
│ │ │ └── Contents.json
│ │ ├── birthday.imageset
│ │ │ ├── birthday.pdf
│ │ │ └── Contents.json
│ │ ├── calendar.imageset
│ │ │ ├── calendar.pdf
│ │ │ └── Contents.json
│ │ ├── overview.imageset
│ │ │ ├── overview.pdf
│ │ │ └── Contents.json
│ │ ├── password.imageset
│ │ │ ├── password.pdf
│ │ │ └── Contents.json
│ │ ├── settings.imageset
│ │ │ ├── settings.pdf
│ │ │ └── Contents.json
│ │ ├── timeline.imageset
│ │ │ ├── timeline.pdf
│ │ │ └── Contents.json
│ │ ├── username.imageset
│ │ │ ├── username.pdf
│ │ │ └── Contents.json
│ │ ├── add-photo.imageset
│ │ │ ├── add-photo.pdf
│ │ │ └── Contents.json
│ │ ├── attention.imageset
│ │ │ ├── attention.pdf
│ │ │ └── Contents.json
│ │ ├── playground.imageset
│ │ │ ├── playground.pdf
│ │ │ └── Contents.json
│ │ └── unchecked.imageset
│ │ │ ├── unchecked.pdf
│ │ │ └── Contents.json
│ ├── avatar
│ │ ├── Contents.json
│ │ ├── jakelin.imageset
│ │ │ ├── jakelin.jpg
│ │ │ └── Contents.json
│ │ ├── avatar1.imageset
│ │ │ ├── avatar1@2x.png
│ │ │ ├── avatar1@3x.png
│ │ │ └── Contents.json
│ │ ├── avatar2.imageset
│ │ │ ├── avatar2@2x.png
│ │ │ ├── avatar2@3x.png
│ │ │ └── Contents.json
│ │ ├── avatar3.imageset
│ │ │ ├── avatar3@2x.png
│ │ │ ├── avatar3@3x.png
│ │ │ └── Contents.json
│ │ └── jakelin-small.imageset
│ │ │ ├── jakelin-small@2x.png
│ │ │ ├── jakelin-small@3x.png
│ │ │ └── Contents.json
│ ├── background
│ │ ├── Contents.json
│ │ ├── auto-bg.imageset
│ │ │ ├── auto-bg.png
│ │ │ └── Contents.json
│ │ ├── food-bg.imageset
│ │ │ ├── food-bg.png
│ │ │ └── Contents.json
│ │ ├── home-bg.imageset
│ │ │ ├── home-bg.png
│ │ │ └── Contents.json
│ │ ├── work-bg.imageset
│ │ │ ├── work-bg.png
│ │ │ └── Contents.json
│ │ ├── login-bg.imageset
│ │ │ ├── login-bg@2x.png
│ │ │ └── Contents.json
│ │ ├── profile-bg.imageset
│ │ │ ├── profile-bg.png
│ │ │ └── Contents.json
│ │ ├── calendar-bg.imageset
│ │ │ ├── calendar-bg.png
│ │ │ └── Contents.json
│ │ ├── overview-bg.imageset
│ │ │ ├── overview-bg.png
│ │ │ └── Contents.json
│ │ ├── timeline-bg.imageset
│ │ │ ├── timeline-bg.png
│ │ │ └── Contents.json
│ │ └── walkthrough-bg.imageset
│ │ │ ├── walkthrough-bg@2x.png
│ │ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ ├── Icon-76.png
│ │ ├── Icon-29@2x.png
│ │ ├── Icon-29@3x.png
│ │ ├── Icon-40@2x.png
│ │ ├── Icon-40@3x.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-76@2x.png
│ │ ├── Icon-83.5@2x.png
│ │ └── Contents.json
├── Functions.swift
├── README.md
├── InteractionTableViewController.swift
├── TransitionViewController.swift
├── UIViewControllerExtension.swift
├── TransitionPushedViewController.swift
├── Base.lproj
│ └── LaunchScreen.storyboard
├── Info.plist
├── AppDelegate.swift
├── ContainerTransitionViewController.swift
├── Animations.storyboard
└── UserInterface.storyboard
├── .swiftlint.yml
├── IBAnimatable.playground
├── Pages
│ ├── Animation Properties.xcplaygroundpage
│ │ ├── timeline.xctimeline
│ │ └── Contents.swift
│ ├── Chaining Animations.xcplaygroundpage
│ │ ├── timeline.xctimeline
│ │ └── Contents.swift
│ └── Predefined Animations.xcplaygroundpage
│ │ ├── timeline.xctimeline
│ │ └── Contents.swift
├── playground.xcworkspace
│ └── contents.xcworkspacedata
└── contents.xcplayground
├── IBAnimatableApp.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── IBAnimatable.xcscheme
├── IBAnimatable
├── TransitionPageType.swift
├── StatusBarDesignable.swift
├── BlurEffectStyle.swift
├── BorderSide.swift
├── TransitionHollowState.swift
├── Typealias.swift
├── MaskType.swift
├── DismissSegue.swift
├── Constants.swift
├── GradientStartPoint.swift
├── GestureDirection.swift
├── CALayerExtension.swift
├── TransitionType.swift
├── PresentFadeSegue.swift
├── PresentExplodeSegue.swift
├── PresentFlipSegue.swift
├── PresentTurnSegue.swift
├── CornerDesignable.swift
├── PresentCardsSegue.swift
├── PresentNatGeoSegue.swift
├── PresentFoldSegue.swift
├── PresentSlideSegue.swift
├── PresentPortalSegue.swift
├── PresentFadeWithDismissInteractionSegue.swift
├── PresentFlipWithDismissInteractionSegue.swift
├── PresentTurnWithDismissInteractionSegue.swift
├── PresentNatGeoWithDismissInteractionSegue.swift
├── ViewControllerDesignable.swift
├── PresentFoldWithDismissInteractionSegue.swift
├── PresentSlideWithDismissInteractionSegue.swift
├── PresentPortalWithDismissInteractionSegue.swift
├── RotationDesignable.swift
├── BarButtonItemDesignable.swift
├── ColorType.swift
├── UIViewControllerExtension.swift
├── PlaceholderDesignable.swift
├── DesignableNavigationBar.swift
├── TransitionAnimatable.swift
├── RootWindowDesignable.swift
├── TableViewCellDesignable.swift
├── Info.plist
├── InteractiveAnimatorFactory.swift
├── SystemTransitionType.swift
├── UIColorExtension.swift
├── NavigationBarDesginable.swift
├── CheckBoxDesignable.swift
├── TransitionFromDirection.swift
├── SystemRotateAnimator.swift
├── SystemSuckEffectAnimator.swift
├── SystemRippleEffectAnimator.swift
├── AnimationType.swift
├── PaddingDesignable.swift
├── BlurDesignable.swift
├── AnimatableBarButtonItem.swift
├── PresenterManager.swift
├── SystemPageAnimator.swift
├── TintDesignable.swift
├── AnimatableNavigationController.swift
├── ShadowDesignable.swift
├── SystemRevealAnimator.swift
├── SystemMoveInAnimator.swift
├── SystemPushAnimator.swift
├── SystemCubeAnimator.swift
├── PanInteractiveAnimator.swift
├── PinchInteractiveAnimator.swift
├── SystemCameraIrisAnimator.swift
├── SystemFlipAnimator.swift
├── AnimatableViewController.swift
├── AnimatableTextView.swift
├── InteractiveGestureType.swift
├── AnimatableTableView.swift
├── FadeAnimator.swift
├── AnimatableLabel.swift
├── AnimatableTableViewCell.swift
├── AnimatedTransitioning.swift
├── ScreenEdgePanInteractiveAnimator.swift
├── Navigator.swift
├── AnimatableCollectionViewCell.swift
├── AnimatorFactory.swift
├── GradientType.swift
├── SideImageDesignable.swift
├── InteractiveAnimator.swift
├── AnimatableButton.swift
├── Presenter.swift
├── FillDesignable.swift
└── SlideAnimator.swift
├── .travis.yml
├── IBAnimatable.podspec
├── LICENSE
├── Scripts
├── GradientsTypeScript.swift
└── FlatColorsTypeScript.swift
└── .gitignore
/Package.swift:
--------------------------------------------------------------------------------
1 | import PackageDescription
2 |
3 | let package = Package(name: "IBAnimatable")
4 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/add.imageset/add.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/add.imageset/add.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/back.imageset/back.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/back.imageset/back.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/done.imageset/done.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/done.imageset/done.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/email.imageset/email.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/email.imageset/email.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/home.imageset/home.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/home.imageset/home.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/left.imageset/left-1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/left.imageset/left-1.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/lists.imageset/lists.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/lists.imageset/lists.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/menu.imageset/menu.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/menu.imageset/menu.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/more.imageset/more.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/more.imageset/more.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/right.imageset/right.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/right.imageset/right.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/filter.imageset/filter.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/filter.imageset/filter.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/gender.imageset/gender.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/gender.imageset/gender.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/groups.imageset/groups.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/groups.imageset/groups.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/logo.imageset/logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/logo.imageset/logo@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/logo.imageset/logo@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/logo.imageset/logo@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/logout.imageset/logout.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/logout.imageset/logout.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/checked.imageset/checked.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/checked.imageset/checked.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/profile.imageset/profile.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/profile.imageset/profile.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/jakelin.imageset/jakelin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/jakelin.imageset/jakelin.jpg
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/birthday.imageset/birthday.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/birthday.imageset/birthday.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/calendar.imageset/calendar.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/calendar.imageset/calendar.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/overview.imageset/overview.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/overview.imageset/overview.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/password.imageset/password.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/password.imageset/password.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/settings.imageset/settings.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/settings.imageset/settings.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/timeline.imageset/timeline.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/timeline.imageset/timeline.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/username.imageset/username.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/username.imageset/username.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar1.imageset/avatar1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/avatar1.imageset/avatar1@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar1.imageset/avatar1@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/avatar1.imageset/avatar1@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar2.imageset/avatar2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/avatar2.imageset/avatar2@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar2.imageset/avatar2@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/avatar2.imageset/avatar2@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar3.imageset/avatar3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/avatar3.imageset/avatar3@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar3.imageset/avatar3@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/avatar3.imageset/avatar3@3x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/auto-bg.imageset/auto-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/auto-bg.imageset/auto-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/food-bg.imageset/food-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/food-bg.imageset/food-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/home-bg.imageset/home-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/home-bg.imageset/home-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/work-bg.imageset/work-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/work-bg.imageset/work-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/add-photo.imageset/add-photo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/add-photo.imageset/add-photo.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/attention.imageset/attention.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/attention.imageset/attention.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/playground.imageset/playground.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/playground.imageset/playground.pdf
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/unchecked.imageset/unchecked.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/icon/unchecked.imageset/unchecked.pdf
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - trailing_whitespace
3 | - todo
4 | - variable_name
5 | - line_length
6 | - file_length
7 | - function_body_length
8 | - cyclomatic_complexity
9 | - type_name
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/login-bg.imageset/login-bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/login-bg.imageset/login-bg@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/profile-bg.imageset/profile-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/profile-bg.imageset/profile-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/calendar-bg.imageset/calendar-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/calendar-bg.imageset/calendar-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/overview-bg.imageset/overview-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/overview-bg.imageset/overview-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/timeline-bg.imageset/timeline-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/timeline-bg.imageset/timeline-bg.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/jakelin-small.imageset/jakelin-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/jakelin-small.imageset/jakelin-small@2x.png
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/jakelin-small.imageset/jakelin-small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/avatar/jakelin-small.imageset/jakelin-small@3x.png
--------------------------------------------------------------------------------
/IBAnimatable.playground/Pages/Animation Properties.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/Pages/Chaining Animations.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/Pages/Predefined Animations.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/IBAnimatableApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/walkthrough-bg.imageset/walkthrough-bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielPeart/IBAnimatable/HEAD/IBAnimatableApp/Assets.xcassets/background/walkthrough-bg.imageset/walkthrough-bg@2x.png
--------------------------------------------------------------------------------
/IBAnimatable/TransitionPageType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 31/03/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum TransitionPageType {
9 | case Curl
10 | case UnCurl
11 | }
12 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/add.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "add.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "back.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/done.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "done.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/home.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "home.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/menu.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "menu.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/more.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "more.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatable/StatusBarDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/15/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol StatusBarDesignable {
9 | var lightStatusBar: Bool { get set }
10 | }
11 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/email.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "email.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/filter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "filter.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/gender.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "gender.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/groups.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "groups.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/left.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "left-1.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/lists.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "lists.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/logout.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "logout.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/right.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "right.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/add-photo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "add-photo.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/attention.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "attention.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/birthday.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "birthday.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/calendar.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "calendar.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/checked.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "checked.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/overview.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "overview.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/password.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "password.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/profile.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "profile.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/settings.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "settings.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/timeline.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "timeline.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/unchecked.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "unchecked.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/username.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "username.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/playground.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "playground.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/IBAnimatable/BlurEffectStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/5/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum BlurEffectStyle: String {
9 | case ExtraLight
10 | case Light
11 | case Dark
12 | }
13 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | osx_image: xcode7.3
2 | language: objective-c
3 | script:
4 | - |
5 | xcodebuild build \
6 | -project IBAnimatableApp.xcodeproj \
7 | -scheme IBAnimatable \
8 | -sdk iphonesimulator \
9 | -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest'
10 |
--------------------------------------------------------------------------------
/IBAnimatable/BorderSide.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/9/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum BorderSide: String {
9 | case Top
10 | case Right
11 | case Bottom
12 | case Left
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/TransitionHollowState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 30/03/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum TransitionHollowState {
9 | case None
10 | case Open
11 | case Close
12 | }
13 |
--------------------------------------------------------------------------------
/IBAnimatable/Typealias.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/23/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public typealias AnimatableCompletion = () -> Void
9 | public typealias AnimatableExecution = () -> Void
10 | public typealias Duration = NSTimeInterval
11 |
--------------------------------------------------------------------------------
/IBAnimatable/MaskType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/13/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum MaskType: String {
9 | case Circle
10 | case Polygon
11 | case Star
12 | case Triangle
13 | case Wave
14 | case Parallelogram
15 | }
16 |
--------------------------------------------------------------------------------
/IBAnimatable/DismissSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/14/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class DismissSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | sourceViewController.dismissViewControllerAnimated(true, completion: nil)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IBAnimatable/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/29/16.
3 | // Copyright (c) 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | // Default transition duration.
9 | // The default UIKit transtion animation duration is 0.35, but too fast for most of custom transition animations.
10 | let defaultTransitionDuration: Duration = 0.75
11 |
--------------------------------------------------------------------------------
/IBAnimatable/GradientStartPoint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/2/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum GradientStartPoint: String {
9 | case Top
10 | case TopRight
11 | case Right
12 | case BottomRight
13 | case Bottom
14 | case BottomLeft
15 | case Left
16 | case TopLeft
17 | }
18 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/jakelin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "jakelin.jpg",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/auto-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "auto-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/food-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "food-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/home-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "home-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/work-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "work-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/login-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "login-bg@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatable/GestureDirection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 4/5/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | /**
9 | GestureDirection: Used to specify the direction in `InteractiveGestureType`
10 | */
11 | public enum GestureDirection: String {
12 | case Horizontal
13 | case Vertical
14 | case Left
15 | case Right
16 | case Top
17 | case Bottom
18 | case Close
19 | case Open
20 | }
21 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/calendar-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "calendar-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/overview-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "overview-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/profile-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "profile-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/timeline-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "timeline-bg.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/background/walkthrough-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "walkthrough-bg@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/icon/logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "logo@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "logo@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "avatar1@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "avatar1@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "avatar2@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "avatar2@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/avatar3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "avatar3@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "avatar3@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/IBAnimatable/CALayerExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/23/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public extension CALayer {
9 | class func animate(animation: AnimatableExecution, completion: AnimatableCompletion? = nil) {
10 | CATransaction.begin()
11 | if let completion = completion {
12 | CATransaction.setCompletionBlock { completion() }
13 | }
14 | animation()
15 | CATransaction.commit()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/IBAnimatable/TransitionType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 3/16/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | enum TransitionType {
9 | case NavigationTransition(UINavigationControllerOperation)
10 | case PresentationTransition(PresentationOperation)
11 | case TabTransition(TabOperation)
12 | }
13 |
14 | enum PresentationOperation {
15 | case Presentation, Dismissal
16 | }
17 |
18 | enum TabOperation {
19 | case ToLeft, ToRight
20 | }
21 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/avatar/jakelin-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "jakelin-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "jakelin-small@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/IBAnimatable/PresentFadeSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/28/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentFadeSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Fade(direction: .Cross))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentExplodeSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 03/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentExplodeSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Explode(params: []))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentFlipSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 05/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentFlipSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Flip(fromDirection: .Left))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentTurnSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 01/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentTurnSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Turn(fromDirection: .Left))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/CornerDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/1/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol CornerDesignable {
9 | /**
10 | `border-radius`
11 | */
12 | var cornerRadius: CGFloat { get set }
13 | }
14 |
15 | public extension CornerDesignable where Self: UIView {
16 | public func configCornerRadius() {
17 | if !cornerRadius.isNaN && cornerRadius > 0 {
18 | layer.cornerRadius = cornerRadius
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentCardsSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 01/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentCardsSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Cards(direction: .Forward))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentNatGeoSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 24/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentNatGeoSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.NatGeo(toDirection: .Left))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentFoldSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 09/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentFoldSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Fold(fromDirection: .Left, params: []))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentSlideSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 08/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentSlideSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Slide(toDirection: .Left, params: []))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentPortalSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 17/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentPortalSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Portal(direction: .Forward, params: []))
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentFadeWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 3/14/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentFadeWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Fade(direction: .Cross), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentFlipWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 05/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentFlipWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Flip(fromDirection: .Left), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentTurnWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 01/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentTurnWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Turn(fromDirection: .Left), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentNatGeoWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 24/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentNatGeoWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.NatGeo(toDirection: .Left), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/ViewControllerDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/14/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol ViewControllerDesignable {
9 | var hideNavigationBar: Bool { get set }
10 | }
11 |
12 | public extension ViewControllerDesignable where Self: UIViewController {
13 | public func confingHideNavigationBar() {
14 | navigationController?.navigationBarHidden = hideNavigationBar
15 | }
16 |
17 | public func resetHideNavigationBar() {
18 | navigationController?.navigationBarHidden = false
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentFoldWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 09/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentFoldWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Fold(fromDirection: .Left, params: []), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentSlideWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 08/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentSlideWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Slide(toDirection: .Left, params: []), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/PresentPortalWithDismissInteractionSegue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 17/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PresentPortalWithDismissInteractionSegue: UIStoryboardSegue {
9 | public override func perform() {
10 | destinationViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(.Portal(direction: .Forward, params: []), interactiveGestureType: .Default)
11 | sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/IBAnimatable/RotationDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/5/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | import Darwin
8 |
9 | /**
10 | It is not able to preview the rotation in IB.
11 | */
12 | public protocol RotationDesignable {
13 | var rotate: CGFloat { get set }
14 | }
15 |
16 | public extension RotationDesignable where Self: UIView {
17 | public func configRotate() {
18 | if !rotate.isNaN && rotate > -360 && rotate < 360 {
19 | self.transform = CGAffineTransformMakeRotation(CGFloat(M_PI) * rotate / 180)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/IBAnimatable.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "IBAnimatable"
3 | s.version = "2.2"
4 | s.summary = "Design and prototype UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable."
5 | s.homepage = "https://github.com/JakeLin/IBAnimatable"
6 | s.license = { :type => "MIT", :file => "LICENSE" }
7 | s.author = { "Jake Lin" => "JakeLinAu@gmail.com" }
8 | s.platform = :ios, '8.0'
9 | s.source = { :git => "https://github.com/JakeLin/IBAnimatable.git", tag: "#{s.version}" }
10 | s.source_files = "IBAnimatable/*.swift"
11 | end
12 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Functions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Mark Hamilton on 4/9/16.
3 | // Copyright © 2016 dryverless. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | // Source: https://gist.github.com/TheDarkCode/2f65c1a25d5886ed210c3b33d73fe8a9
9 | // Based on earlier version: http://stackoverflow.com/a/28341290/749786
10 | public func iterateEnum(_: T.Type) -> AnyGenerator {
11 | var x = 0
12 | return AnyGenerator {
13 | let next = withUnsafePointer(&x) {
14 | UnsafePointer($0).memory
15 | }
16 | defer {
17 | x += 1
18 | }
19 | return next.hashValue == x ? next : nil
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/IBAnimatableApp/README.md:
--------------------------------------------------------------------------------
1 | # IBAnimatable Playground
2 | **IBAnimatable Playground** is a playground to see the features IBAnimatable can support for prototyping and designing UI, animations, transitions and interactions. You can find your favourite effects and apply them in Interface Builder.
3 |
4 | The `code` folder is not mandatory for the demo App. **The app was made in Interface Builder with `IBAnimatable` without a single line of code**.
5 |
6 | Because we want to demonstrate more effects (e.g. animations, transitions) with only one Scene in Interface Builder. In most of Apps, we usually apply one effect to one View or Scene, then we can configurate that effect in Interface Builder without any code.
7 |
--------------------------------------------------------------------------------
/IBAnimatable/BarButtonItemDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/16/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol BarButtonItemDesignable {
9 | var roundedImage: UIImage? { get set }
10 | }
11 |
12 | public extension BarButtonItemDesignable where Self: UIBarButtonItem {
13 | public func confingBarButtonItemImage() {
14 | guard let unwrappedRoundedImage = roundedImage else {
15 | return
16 | }
17 |
18 | let originalImage: UIImage? = unwrappedRoundedImage.imageWithRenderingMode(.AlwaysOriginal)
19 | if let unwrappedImage = originalImage {
20 | image = unwrappedImage
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/IBAnimatable/ColorType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 13/02/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum ColorType: String {
9 | case FlatEmerland
10 | case FlatPomegranate
11 | case FlatWetAsphalt
12 | case FlatTurquoise
13 | case FlatConcrete
14 | case FlatOrange
15 | case FlatAsbestos
16 | case FlatPeterRiver
17 | case FlatSilver
18 | case FlatSunFlower
19 | case FlatAmethyst
20 | case FlatAlizarin
21 | case FlatGreenSea
22 | case FlatBelizeHole
23 | case FlatNephritis
24 | case FlatMidnightBlue
25 | case FlatClouds
26 | case FlatWisteria
27 | case FlatCarrot
28 | case FlatPumpkin
29 | }
30 |
--------------------------------------------------------------------------------
/IBAnimatable/UIViewControllerExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/14/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | // MARK: - UIStoryboardSegue
9 | public extension UIViewController {
10 | @IBAction public func unwindToViewController(sender: UIStoryboardSegue) {
11 | }
12 |
13 | @IBAction public func dismissCurrentViewController(sender: UIStoryboardSegue) {
14 | sender.sourceViewController.dismissViewControllerAnimated(true, completion: nil)
15 | }
16 |
17 | @IBAction public func popToRootViewController(sender: UIStoryboardSegue) {
18 | sender.sourceViewController.navigationController?.popToRootViewControllerAnimated(true)
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/IBAnimatable/PlaceholderDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/19/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol PlaceholderDesignable {
9 | /**
10 | `color` within `::-webkit-input-placeholder`, `::-moz-placeholder` or `:-ms-input-placeholder`
11 | */
12 | var placeholderColor: UIColor? { get set }
13 | }
14 |
15 | public extension PlaceholderDesignable where Self: UITextField {
16 | public func configPlaceholderColor() {
17 | if let unwrappedPlaceholderColor = placeholderColor {
18 | attributedPlaceholder = NSAttributedString(string: placeholder!, attributes: [NSForegroundColorAttributeName: unwrappedPlaceholderColor])
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/IBAnimatable/DesignableNavigationBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/10/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class DesignableNavigationBar: UINavigationBar, NavigationBarDesignable {
9 | @IBInspectable public var solidColor: Bool = false
10 |
11 | // MARK: - Lifecycle
12 | public override func prepareForInterfaceBuilder() {
13 | super.prepareForInterfaceBuilder()
14 | configInspectableProperties()
15 | }
16 |
17 | public override func awakeFromNib() {
18 | super.awakeFromNib()
19 | configInspectableProperties()
20 | }
21 |
22 | // MARK: - Private
23 | private func configInspectableProperties() {
24 | configNavigationBar()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/IBAnimatableApp/InteractionTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 5/12/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | class InteractionTableViewController: UITableViewController {
9 |
10 | }
11 |
12 | // MARK: - UITableViewDataSource / UITableViewDelegate
13 |
14 | extension InteractionTableViewController {
15 |
16 | // MARK: - reset the group heander font color and size
17 | override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
18 | if let header = view as? UITableViewHeaderFooterView {
19 | header.textLabel?.textColor = UIColor.whiteColor()
20 | header.textLabel?.font = UIFont.systemFontOfSize(16, weight: UIFontWeightLight)
21 | }
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/IBAnimatable/TransitionAnimatable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/24/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol TransitionAnimatable: class {
9 | /**
10 | String value of `TransitionAnimationType` enum, used to specify the transition animations
11 | */
12 | var transitionAnimationType: String? { get set }
13 |
14 | /**
15 | Transition duration: default value should be `Double.NaN`. Need to use `Double` instead of `NSTimeInterval` because IB doesn't support `NSTimeInterval`
16 | */
17 | var transitionDuration: Double { get set }
18 |
19 | /**
20 | String value of `InteractiveTransitionType` enum, used to specify the gesture to dismiss/pop current scence
21 | */
22 | var interactiveGestureType: String? { get set }
23 | }
24 |
--------------------------------------------------------------------------------
/IBAnimatable/RootWindowDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/25/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol RootWindowDesignable {
9 | /**
10 | Root window background color
11 | */
12 | var rootWindowBackgroundColor: UIColor? { get set }
13 | }
14 |
15 | public extension RootWindowDesignable where Self: UIViewController {
16 |
17 | public func configRootWindowBackgroundColor() {
18 | #if NS_EXTENSION_UNAVAILABLE_IOS
19 |
20 | if let wrappedRootWindowBackgroundColor = rootWindowBackgroundColor,
21 | delegate = UIApplication.sharedApplication().delegate,
22 | rootWindow = delegate.window {
23 | rootWindow?.backgroundColor = wrappedRootWindowBackgroundColor
24 | }
25 |
26 | #endif
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/IBAnimatable/TableViewCellDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/19/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol TableViewCellDesignable {
9 | var removeSeparatorMargins: Bool { get set }
10 | }
11 |
12 | public extension TableViewCellDesignable where Self: UITableViewCell {
13 | public func configSeparatorMargins() {
14 | if removeSeparatorMargins {
15 | if respondsToSelector(Selector("setSeparatorInset:")) {
16 | separatorInset = UIEdgeInsetsZero
17 | }
18 |
19 | if respondsToSelector(Selector("setPreservesSuperviewLayoutMargins:")) {
20 | preservesSuperviewLayoutMargins = false
21 | }
22 |
23 | if respondsToSelector(Selector("setLayoutMargins:")) {
24 | layoutMargins = UIEdgeInsetsZero
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/IBAnimatable/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 | FMWK
17 | CFBundleShortVersionString
18 | 2.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/IBAnimatable/InteractiveAnimatorFactory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 4/6/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | /**
8 | Interactive Animator Factory
9 | */
10 | struct InteractiveAnimatorFactory {
11 | static func generateInteractiveAnimator(interactiveGestureType: InteractiveGestureType, transitionType: TransitionType) -> InteractiveAnimator? {
12 | switch interactiveGestureType {
13 | case .Pan:
14 | return PanInteractiveAnimator(interactiveGestureType: interactiveGestureType, transitionType: transitionType)
15 | case .ScreenEdgePan:
16 | return ScreenEdgePanInteractiveAnimator(interactiveGestureType: interactiveGestureType, transitionType: transitionType)
17 | case .Pinch:
18 | return PinchInteractiveAnimator(interactiveGestureType: interactiveGestureType, transitionType: transitionType)
19 | default:
20 | return nil
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemTransitionType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/24/16.
3 | // Copyright (c) 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | /**
9 | System Transition Type: map to iOS built-in CATransition Type
10 | refer to http://iphonedevwiki.net/index.php/CATransition
11 | */
12 | public enum SystemTransitionType: String {
13 | case Fade = "fade" // kCATransitionFade
14 | case MoveIn = "moveIn" // kCATransitionMoveIn
15 | case Push = "push" // kCATransitionPush
16 | case Reveal = "reveal" // kCATransitionReveal
17 | case Flip = "flip"
18 | case Cube = "cube"
19 | case PageCurl = "pageCurl"
20 | case PageUnCurl = "pageUnCurl"
21 | case RippleEffect = "rippleEffect"
22 | case SuckEffect = "suckEffect"
23 | case CameraIris = "cameraIris"
24 | case CameraIrisHollowOpen = "cameraIrisHollowOpen"
25 | case CameraIrisHollowClose = "cameraIrisHollowClose"
26 | case Rotate = "rotate"
27 | }
28 |
--------------------------------------------------------------------------------
/IBAnimatable/UIColorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 09/02/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | extension UIColor {
9 |
10 | convenience init(hexString: String) {
11 | let hex = hexString.stringByTrimmingCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet)
12 | var int = UInt32()
13 | NSScanner(string: hex).scanHexInt(&int)
14 | let a, r, g, b: UInt32
15 | switch hex.characters.count {
16 | case 3:
17 | (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
18 | case 6:
19 | (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
20 | case 8:
21 | (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
22 | default:
23 | (a, r, g, b) = (1, 1, 1, 0)
24 | }
25 | self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/IBAnimatable/NavigationBarDesginable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/10/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol NavigationBarDesignable {
9 | /**
10 | Specify whether is solid color only, if `true` will remove hairline from navigation bar
11 | */
12 | var solidColor: Bool { get set }
13 | }
14 |
15 | public extension NavigationBarDesignable where Self: UINavigationBar {
16 | public func configNavigationBar() {
17 | if solidColor {
18 | let emptyImage = UIImage()
19 | setBackgroundImage(emptyImage, forBarPosition: .Any, barMetrics: .Default)
20 | shadowImage = emptyImage
21 | // Need to manually untick translucent in Interface Builder,
22 | // otherwise, it will have constrait issue in IB although it is correct in run time.
23 | // translucent = false
24 | } else {
25 | setBackgroundImage(nil, forBarPosition: .Any, barMetrics: .Default)
26 | shadowImage = nil
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/IBAnimatable/CheckBoxDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/20/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol CheckBoxDesignable {
9 | var checked: Bool { get set }
10 | var checkedImage: UIImage? { get set }
11 | var uncheckedImage: UIImage? { get set }
12 | }
13 |
14 | public extension CheckBoxDesignable where Self: UIButton {
15 | public func configCheckBoxChecked() {
16 | selected = checked
17 | }
18 |
19 | public func configCheckBoxCheckedImage() {
20 | guard let unwrappedCheckedImage = checkedImage else {
21 | return
22 | }
23 |
24 | setBackgroundImage(unwrappedCheckedImage, forState: .Selected)
25 | setBackgroundImage(unwrappedCheckedImage, forState: [.Selected, .Highlighted])
26 | }
27 |
28 | public func configCheckBoxUncheckedImage() {
29 | guard let unwrappedUncheckedImage = uncheckedImage else {
30 | return
31 | }
32 |
33 | setBackgroundImage(unwrappedUncheckedImage, forState: .Normal)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/IBAnimatable/TransitionFromDirection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016 Jake Lin. All rights reserved.
3 | //
4 |
5 | import UIKit
6 |
7 | /**
8 | TransitionDirection: used to specify the direction for the transition
9 | */
10 | public enum TransitionDirection {
11 | case Left
12 | case Right
13 | case Top
14 | case Bottom
15 | case Forward
16 | case Backward
17 | case In
18 | case Out
19 | case Cross
20 |
21 | // Convert from direction to CATransition Subtype used in `CATransition`
22 | var CATransitionSubtype: String {
23 | switch self {
24 | case .Left:
25 | return kCATransitionFromLeft
26 | case .Right:
27 | return kCATransitionFromRight
28 | case .Top:
29 | // The actual transition direction is oposite, need to reverse
30 | return kCATransitionFromBottom
31 | case .Bottom:
32 | // The actual transition direction is oposite, need to reverse
33 | return kCATransitionFromTop
34 | default:
35 | return ""
36 | }
37 | }
38 |
39 | var isHorizontal: Bool {
40 | return self == .Left || self == .Right
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Jake Lin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/IBAnimatableApp/TransitionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 3/1/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | import IBAnimatable
8 |
9 | class TransitionViewController: AnimatableViewController {
10 |
11 | @IBOutlet var presentButton: AnimatableButton!
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | // Transition animations start with `System` do not support Present transition, so hide it
17 | if let animationType = transitionAnimationType where animationType.hasPrefix("System") {
18 | // Cannot use `hidden` here because of `UIStackView`
19 | presentButton.alpha = 0
20 | }
21 | }
22 |
23 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
24 | super.prepareForSegue(segue, sender: sender)
25 |
26 | // Set the transition animation type for `AnimatableViewController`, used for Present/Dismiss transitions
27 | if let toViewController = segue.destinationViewController as? AnimatableViewController {
28 | toViewController.transitionAnimationType = transitionAnimationType
29 | toViewController.interactiveGestureType = interactiveGestureType
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemRotateAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 02/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemRotateAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | public init(transitionDuration: Duration) {
16 | self.transitionDuration = transitionDuration
17 | self.transitionAnimationType = .SystemRotate
18 | self.reverseAnimationType = .SystemRotate
19 |
20 | super.init()
21 | }
22 | }
23 |
24 | extension SystemRotateAnimator: UIViewControllerAnimatedTransitioning {
25 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
26 | return retrieveTransitionDuration(transitionContext)
27 | }
28 |
29 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
30 | animateWithCATransition(transitionContext, type: SystemTransitionType.Rotate, subtype: "90")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemSuckEffectAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 30/03/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemSuckEffectAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | public init(transitionDuration: Duration) {
16 | self.transitionDuration = transitionDuration
17 | self.transitionAnimationType = .SystemSuckEffect
18 | self.reverseAnimationType = .SystemSuckEffect
19 | super.init()
20 | }
21 | }
22 |
23 | extension SystemSuckEffectAnimator: UIViewControllerAnimatedTransitioning {
24 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
25 | return retrieveTransitionDuration(transitionContext)
26 | }
27 |
28 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
29 | animateWithCATransition(transitionContext, type: SystemTransitionType.SuckEffect, subtype: nil)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemRippleEffectAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 30/03/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemRippleEffectAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | public init(transitionDuration: Duration) {
16 | self.transitionDuration = transitionDuration
17 | self.transitionAnimationType = .SystemRippleEffect
18 | self.reverseAnimationType = .SystemRippleEffect
19 | super.init()
20 | }
21 | }
22 |
23 | extension SystemRippleEffectAnimator: UIViewControllerAnimatedTransitioning {
24 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
25 | return retrieveTransitionDuration(transitionContext)
26 | }
27 |
28 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
29 | animateWithCATransition(transitionContext, type: SystemTransitionType.RippleEffect, subtype: nil)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/IBAnimatableApp/UIViewControllerExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 5/16/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | import IBAnimatable
8 |
9 | extension UIViewController {
10 |
11 | func generateRandomGradient() -> GradientType {
12 | var predefinedGradients = [GradientType]()
13 | iterateEnum(GradientType).forEach {
14 | predefinedGradients.append($0)
15 | }
16 |
17 | let randomIndex: Int = Int(arc4random_uniform(UInt32(predefinedGradients.count)))
18 | return predefinedGradients[randomIndex]
19 | }
20 |
21 | func retrieveGestureText(interactiveGestureType: InteractiveGestureType, transitionAnimationType: TransitionAnimationType, exit: String) -> String {
22 | switch interactiveGestureType {
23 | case .Default:
24 | // Default gesture
25 | let transitionAnimator = AnimatorFactory.generateAnimator(transitionAnimationType)
26 | if let interactiveGestureType = transitionAnimator.interactiveGestureType {
27 | return String("or use \(interactiveGestureType.toString()) gesture to \(exit)")
28 | }
29 |
30 | // The transition animator doesn't have default `interactiveGestureType`
31 | return ""
32 | default:
33 | // Specified gesture
34 | return String("or use \(interactiveGestureType.toString()) gesture to \(exit)")
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimationType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/19/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | /**
9 | Predefined Animation Type
10 | */
11 | public enum AnimationType: String {
12 | case SlideInLeft
13 | case SlideInRight
14 | case SlideInDown
15 | case SlideInUp
16 | case SlideOutLeft
17 | case SlideOutRight
18 | case SlideOutDown
19 | case SlideOutUp
20 | case SqueezeInLeft
21 | case SqueezeInRight
22 | case SqueezeInDown
23 | case SqueezeInUp
24 | case SqueezeOutLeft
25 | case SqueezeOutRight
26 | case SqueezeOutDown
27 | case SqueezeOutUp
28 | case FadeIn
29 | case FadeOut
30 | case FadeOutIn
31 | case FadeInOut
32 | case FadeInLeft
33 | case FadeInRight
34 | case FadeInDown
35 | case FadeInUp
36 | case FadeOutLeft
37 | case FadeOutRight
38 | case FadeOutDown
39 | case FadeOutUp
40 | case SqueezeFadeInLeft
41 | case SqueezeFadeInRight
42 | case SqueezeFadeInDown
43 | case SqueezeFadeInUp
44 | case SqueezeFadeOutLeft
45 | case SqueezeFadeOutRight
46 | case SqueezeFadeOutDown
47 | case SqueezeFadeOutUp
48 | case ZoomIn
49 | case ZoomOut
50 | case Shake
51 | case Pop
52 | case FlipX
53 | case FlipY
54 | case Morph
55 | case Squeeze
56 | case Flash
57 | case Wobble
58 | case Swing
59 | case Rotate
60 | case RotateCCW
61 | case MoveTo
62 | case MoveBy
63 | }
64 |
--------------------------------------------------------------------------------
/IBAnimatable/PaddingDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/18/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol PaddingDesignable {
9 | /**
10 | `padding-left`
11 | */
12 | var paddingLeft: CGFloat { get set }
13 |
14 | /**
15 | `padding-right`
16 | */
17 | var paddingRight: CGFloat { get set }
18 |
19 | /**
20 | `padding-left` and `padding-right`
21 | */
22 | var paddingSide: CGFloat { get set }
23 | }
24 |
25 | public extension PaddingDesignable where Self: UITextField {
26 | public func configPaddingLeft() {
27 | if paddingLeft.isNaN {
28 | return
29 | }
30 |
31 | let padding = UIView(frame: CGRect(x: 0, y: 0, width: paddingLeft, height: 0))
32 | leftViewMode = .Always
33 | leftView = padding
34 | }
35 |
36 | public func configPaddingRight() {
37 | if paddingRight.isNaN {
38 | return
39 | }
40 |
41 | let padding = UIView(frame: CGRect(x: 0, y: 0, width: paddingRight, height: 0))
42 | rightViewMode = .Always
43 | rightView = padding
44 | }
45 |
46 | public func configPaddingSide() {
47 | if paddingSide.isNaN {
48 | return
49 | }
50 |
51 | let padding = UIView(frame: CGRect(x: 0, y: 0, width: paddingSide, height: paddingSide))
52 | leftViewMode = .Always
53 | leftView = padding
54 |
55 | rightViewMode = .Always
56 | rightView = padding
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/IBAnimatableApp/TransitionPushedViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 5/13/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | import IBAnimatable
8 |
9 | class TransitionPushedViewController: UIViewController {
10 |
11 | @IBOutlet var gestureLabel: UILabel!
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | if let animatableView = view as? AnimatableView {
17 | animatableView.predefinedGradient = String(generateRandomGradient())
18 | }
19 | configureGestureLabel()
20 | }
21 |
22 | }
23 |
24 | private extension TransitionPushedViewController {
25 |
26 | func configureGestureLabel() {
27 | // Shows nothing by default
28 | gestureLabel.text = "to pop"
29 |
30 | guard let navigationController = self.navigationController as? AnimatableNavigationController else {
31 | return
32 | }
33 |
34 | // No gesture for this animator
35 | guard let interactiveGestureTypeString = navigationController.interactiveGestureType,
36 | interactiveGestureType = InteractiveGestureType.fromString(interactiveGestureTypeString),
37 | transitionAnimationTypeString = navigationController.transitionAnimationType,
38 | transitionAnimationType = TransitionAnimationType.fromString(transitionAnimationTypeString) else {
39 | return
40 | }
41 |
42 | gestureLabel.text = retrieveGestureText(interactiveGestureType, transitionAnimationType: transitionAnimationType, exit: "pop")
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/Pages/Chaining Animations.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | //: ## Chaining Animations
4 |
5 | import UIKit
6 | import XCPlayground
7 | import IBAnimatable
8 |
9 | //: Constants
10 | let iPhoneWidth = 375
11 | let iPhoneHeight = 667
12 | let animatableViewWidth = 100
13 | let animatableViewX = (iPhoneWidth - animatableViewWidth) / 2
14 | let animatableViewY = (iPhoneHeight - animatableViewWidth) / 2
15 |
16 | //: Set up the iPhone View
17 | let iPhoneView = UIView(frame: CGRect(x: 0, y: 0, width: iPhoneWidth, height: iPhoneHeight))
18 | iPhoneView.backgroundColor = .whiteColor()
19 | XCPlaygroundPage.currentPage.liveView = iPhoneView
20 |
21 | //: Set up the animatable View
22 | let view = AnimatableView(frame: CGRect(x: animatableViewX, y: animatableViewY, width: animatableViewWidth, height: animatableViewWidth))
23 | view.configAnimatableProperties()
24 | iPhoneView.addSubview(view)
25 |
26 | view.fillColor = UIColor(red: 0xba/0xff, green: 0x77/0xff, blue: 1, alpha: 1)
27 | view.maskType = String(MaskType.Circle)
28 |
29 | //: Start another animation in completion closure
30 | view.squeezeInDown { view.pop { view.shake { view.squeeze { view.wobble { view.flipX { view.flash { view.flipY { view.fadeOutDown() } } } } } } } }
31 |
32 | //: To apply delay, we can specify the animationType and delay
33 | //view.animationType = String(AnimationType.Pop)
34 | //view.animate{
35 | // view.delay = 0.3
36 | // view.animationType = String(AnimationType.Shake)
37 | // view.animate()
38 | //}
39 |
40 | //: [Next](@next)
41 |
--------------------------------------------------------------------------------
/IBAnimatable/BlurDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/23/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol BlurDesignable {
9 | /**
10 | blur effect style: `ExtraLight`, `Light` or `Dark`
11 | */
12 | var blurEffectStyle: String? { get set }
13 |
14 | var blurOpacity: CGFloat { get set }
15 | }
16 |
17 | public extension BlurDesignable where Self: UIView {
18 | /**
19 | configBlurEffectStyle method, should be called in layoutSubviews() method
20 | */
21 | public func configBlurEffectStyle() {
22 | guard let unwrappedBlurEffectStyle = blurEffectStyle else {
23 | return
24 | }
25 |
26 | var style: UIBlurEffectStyle?
27 | guard let blurEffectStyle = BlurEffectStyle(rawValue: unwrappedBlurEffectStyle) else {
28 | return
29 | }
30 |
31 | switch blurEffectStyle {
32 | case .ExtraLight:
33 | style = .ExtraLight
34 | case .Light:
35 | style = .Light
36 | case .Dark:
37 | style = .Dark
38 | }
39 |
40 | let blurEffect = UIBlurEffect(style: style!)
41 | let blurEffectView = UIVisualEffectView(effect: blurEffect)
42 | blurEffectView.frame = bounds
43 | let opacity = blurOpacity.isNaN ? 1.0 : blurOpacity // Default is 1.0
44 | blurEffectView.alpha = opacity
45 | if layer.cornerRadius > 0 {
46 | blurEffectView.layer.cornerRadius = layer.cornerRadius
47 | blurEffectView.clipsToBounds = true
48 | }
49 | blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
50 | insertSubview(blurEffectView, atIndex: 0)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableBarButtonItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/16/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableBarButtonItem: UIBarButtonItem, BarButtonItemDesignable, Animatable {
9 | // MARK: - BarButtonItemDesignable
10 | @IBInspectable public var roundedImage: UIImage?
11 |
12 | // MARK: - Lifecycle
13 | public override func prepareForInterfaceBuilder() {
14 | super.prepareForInterfaceBuilder()
15 | configInspectableProperties()
16 | }
17 |
18 | public override func awakeFromNib() {
19 | super.awakeFromNib()
20 | configInspectableProperties()
21 | }
22 |
23 | // TODO: animations
24 | // public override func layoutSubviews() {
25 | // super.layoutSubviews()
26 | //
27 | // autoRunAnimation()
28 | // }
29 |
30 | // MARK: - Animatable
31 | @IBInspectable public var animationType: String?
32 | @IBInspectable public var autoRun: Bool = true
33 | @IBInspectable public var duration: Double = Double.NaN
34 | @IBInspectable public var delay: Double = Double.NaN
35 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
36 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
37 | @IBInspectable public var force: CGFloat = CGFloat.NaN
38 | @IBInspectable public var repeatCount: Float = Float.NaN
39 | @IBInspectable public var x: CGFloat = CGFloat.NaN
40 | @IBInspectable public var y: CGFloat = CGFloat.NaN
41 |
42 | // MARK: - Private
43 | private func configInspectableProperties() {
44 | // configAnimatableProperties()
45 | confingBarButtonItemImage()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/IBAnimatable/PresenterManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/29/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | /**
9 | Presenter Manager: Used to cache the Presenters for Present and Dismiss transitions
10 | */
11 | public class PresenterManager {
12 | // MARK: - Singleton Constructor
13 | private init() {}
14 | private struct Shared {
15 | static let instance = PresenterManager()
16 | }
17 |
18 | public static func sharedManager() -> PresenterManager {
19 | return Shared.instance
20 | }
21 |
22 | // MARK: - Private
23 | private var cache = [String: Presenter]()
24 |
25 | // MARK: Internal Interface
26 | public func retrievePresenter(transitionAnimationType: TransitionAnimationType, transitionDuration: Duration = defaultTransitionDuration, interactiveGestureType: InteractiveGestureType? = nil) -> Presenter {
27 | // Get the cached presenter
28 | let presenter = cache[transitionAnimationType.stringValue]
29 | if let presenter = presenter {
30 | // Update the `transitionDuration` and `interactiveGestureType` every time to reuse the same presenter with the same type
31 | presenter.transitionDuration = transitionDuration
32 | presenter.interactiveGestureType = interactiveGestureType
33 | return presenter
34 | }
35 |
36 | // Create a new if cache doesn't exist
37 | let newPresenter = Presenter(transitionAnimationType: transitionAnimationType, transitionDuration: transitionDuration, interactiveGestureType: interactiveGestureType)
38 | cache[transitionAnimationType.stringValue] = newPresenter
39 | return newPresenter
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/IBAnimatableApp/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 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Animatable
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 | 2.1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UIStatusBarHidden
36 |
37 | UIStatusBarStyle
38 | UIStatusBarStyleLightContent
39 | UISupportedInterfaceOrientations
40 |
41 | UIInterfaceOrientationPortrait
42 |
43 | UISupportedInterfaceOrientations~ipad
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationPortraitUpsideDown
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemPageAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 28/03/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemPageAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | // MARK: - private
16 | private var type: TransitionPageType
17 |
18 | public init(type: TransitionPageType, transitionDuration: Duration) {
19 | self.transitionDuration = transitionDuration
20 | self.type = type
21 |
22 | switch type {
23 | case .Curl:
24 | self.transitionAnimationType = .SystemPage(type: .Curl)
25 | self.reverseAnimationType = .SystemPage(type: .UnCurl)
26 | case .UnCurl:
27 | self.transitionAnimationType = .SystemPage(type: .UnCurl)
28 | self.reverseAnimationType = .SystemPage(type: .Curl)
29 | }
30 |
31 | super.init()
32 | }
33 | }
34 |
35 | extension SystemPageAnimator: UIViewControllerAnimatedTransitioning {
36 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
37 | return retrieveTransitionDuration(transitionContext)
38 | }
39 |
40 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
41 | switch self.type {
42 | case .Curl:
43 | animateWithCATransition(transitionContext, type: SystemTransitionType.PageCurl, subtype: nil)
44 | case .UnCurl:
45 | animateWithCATransition(transitionContext, type: SystemTransitionType.PageUnCurl, subtype: nil)
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/IBAnimatable/TintDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/24/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol TintDesignable {
9 | /**
10 | Opacity in tint Color (White): from 0 to 1
11 | */
12 | var tintOpacity: CGFloat { get set }
13 |
14 |
15 | /**
16 | Opacity in shade Color (Black): from 0 to 1
17 | */
18 | var shadeOpacity: CGFloat { get set }
19 |
20 | /**
21 | tone color
22 | */
23 | var toneColor: UIColor? { get set }
24 |
25 | /**
26 | Opacity in tone color: from 0 to 1
27 | */
28 | var toneOpacity: CGFloat { get set }
29 | }
30 |
31 | public extension TintDesignable where Self: UIView {
32 | /**
33 | configTintedColor method, should be called in layoutSubviews() method
34 | */
35 | public func configTintedColor() {
36 | if !tintOpacity.isNaN && tintOpacity >= 0 && tintOpacity <= 1 {
37 | addColorSubview(UIColor.whiteColor(), opacity: tintOpacity)
38 | }
39 |
40 | if !shadeOpacity.isNaN && shadeOpacity >= 0 && shadeOpacity <= 1 {
41 | addColorSubview(UIColor.blackColor(), opacity: shadeOpacity)
42 | }
43 |
44 | if let unwrappedToneColor = toneColor {
45 | if !toneOpacity.isNaN && toneOpacity >= 0 && toneOpacity <= 1 {
46 | addColorSubview(unwrappedToneColor, opacity: toneOpacity)
47 | }
48 | }
49 | }
50 |
51 | private func addColorSubview(color: UIColor, opacity: CGFloat) {
52 | let subview = UIView(frame: self.bounds)
53 | subview.backgroundColor = color
54 | subview.alpha = opacity
55 | if layer.cornerRadius > 0 {
56 | subview.layer.cornerRadius = layer.cornerRadius
57 | }
58 | subview.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
59 | self.insertSubview(subview, atIndex: 0)
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Scripts/GradientsTypeScript.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/swift
2 |
3 | import Foundation
4 |
5 | let gradientTypeURL = "https://raw.githubusercontent.com/Ghosh/uiGradients/master/gradients.json"
6 |
7 | func JSONFromURL(urlToRequest: String) -> NSData {
8 | return NSData(contentsOfURL: NSURL(string: urlToRequest)!)!
9 | }
10 |
11 | func parseJSON(JSONData: NSData) -> [[String: AnyObject]]? {
12 | var json: [[String: AnyObject]]?
13 | do {
14 | json = try NSJSONSerialization.JSONObjectWithData(JSONData, options: .MutableContainers) as? [[String: AnyObject]]
15 | return json
16 | } catch {
17 | print("JSON serialization did fail")
18 | return nil
19 | }
20 | }
21 |
22 | // Generator constants
23 | let enumCase = "\tcase %@\n"
24 | let switchCase = "case .%@:\n"
25 | let colors = "\treturn (UIColor(hexString: \"%@\"), UIColor(hexString: \"%@\"))\n"
26 | let endEnumOrSwitch = "}"
27 |
28 | // Finale string
29 | var enumGradientType = "public enum GradientType: String {\n"
30 | var switchPredefinedGradientType = "switch gradientType {\n"
31 |
32 | // Enum generator
33 | let gradientsType = parseJSON(JSONFromURL(gradientTypeURL))
34 | for gradient in gradientsType! {
35 | if var name = gradient["name"] as? String,
36 | unwrappedColors = gradient["colors"] as? [String],
37 | startColor = unwrappedColors.first,
38 | endColor = unwrappedColors.last {
39 | name = name.stringByReplacingOccurrencesOfString(" ", withString: "")
40 | enumGradientType += String(format: enumCase, name)
41 | switchPredefinedGradientType += String(format: switchCase, name)
42 | switchPredefinedGradientType += String(format: colors, startColor, endColor)
43 | }
44 | }
45 |
46 | enumGradientType += endEnumOrSwitch
47 | switchPredefinedGradientType += endEnumOrSwitch
48 | print(enumGradientType)
49 | print("\n")
50 | print(switchPredefinedGradientType)
51 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-29@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-29@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-40@2x.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-40@3x.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-60@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-60@3x.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "idiom" : "ipad",
41 | "size" : "29x29",
42 | "scale" : "1x"
43 | },
44 | {
45 | "size" : "29x29",
46 | "idiom" : "ipad",
47 | "filename" : "Icon-29@2x.png",
48 | "scale" : "2x"
49 | },
50 | {
51 | "idiom" : "ipad",
52 | "size" : "40x40",
53 | "scale" : "1x"
54 | },
55 | {
56 | "size" : "40x40",
57 | "idiom" : "ipad",
58 | "filename" : "Icon-40@2x.png",
59 | "scale" : "2x"
60 | },
61 | {
62 | "size" : "76x76",
63 | "idiom" : "ipad",
64 | "filename" : "Icon-76.png",
65 | "scale" : "1x"
66 | },
67 | {
68 | "size" : "76x76",
69 | "idiom" : "ipad",
70 | "filename" : "Icon-76@2x.png",
71 | "scale" : "2x"
72 | },
73 | {
74 | "size" : "83.5x83.5",
75 | "idiom" : "ipad",
76 | "filename" : "Icon-83.5@2x.png",
77 | "scale" : "2x"
78 | }
79 | ],
80 | "info" : {
81 | "version" : 1,
82 | "author" : "xcode"
83 | }
84 | }
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableNavigationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/20/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class AnimatableNavigationController: UINavigationController, TransitionAnimatable {
9 |
10 | // MARK: - TransitionAnimatable
11 | @IBInspectable public var transitionAnimationType: String? {
12 | didSet {
13 | configureNavigationControllerDelegate()
14 | }
15 | }
16 | @IBInspectable public var transitionDuration: Double = .NaN {
17 | didSet {
18 | configureNavigationControllerDelegate()
19 | }
20 | }
21 | @IBInspectable public var interactiveGestureType: String? {
22 | didSet {
23 | configureNavigationControllerDelegate()
24 | }
25 | }
26 |
27 | // MARK: - Lifecylce
28 | public override func viewDidLoad() {
29 | super.viewDidLoad()
30 | configureNavigationControllerDelegate()
31 | }
32 |
33 | // MARK: - Private
34 | // Must have a property to keep the reference alive because `UINavigationController.delegate` is `weak`
35 | private var navigator: Navigator?
36 |
37 | private func configureNavigationControllerDelegate() {
38 | guard let transitionAnimationType = transitionAnimationType, animationType = TransitionAnimationType.fromString(transitionAnimationType) else {
39 | navigator = nil
40 | delegate = nil
41 | return
42 | }
43 | var duration = transitionDuration
44 | // Set the default duration for transition
45 | if transitionDuration.isNaN {
46 | duration = defaultTransitionDuration
47 | }
48 | if let interactiveGestureType = interactiveGestureType, gestureType = InteractiveGestureType.fromString(interactiveGestureType) {
49 | navigator = Navigator(transitionAnimationType: animationType, transitionDuration: duration, interactiveGestureType: gestureType)
50 | } else {
51 | navigator = Navigator(transitionAnimationType: animationType, transitionDuration: duration)
52 | }
53 | delegate = navigator
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/IBAnimatable/ShadowDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/18/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | /**
9 | These properties are not able to render in IB correctly, it maybe a bug of IB.
10 |
11 | To use them, `UIView`'s `clipsToBounds` and `CALayer`'s `masksToBounds` (`Clip Subviews` in IB) must be `false`,
12 | */
13 | public protocol ShadowDesignable {
14 | /**
15 | `color` when using with `box-shadow`
16 | */
17 | var shadowColor: UIColor? { get set }
18 |
19 | /**
20 | Radius in `box-shadow`
21 | */
22 | var shadowRadius: CGFloat { get set }
23 |
24 | /**
25 | Opacity in `box-shadow`: from 0 to 1
26 | */
27 | var shadowOpacity: CGFloat { get set }
28 |
29 | /**
30 | Offset in `box-shadow`. `x` is horizontal offset and `y` is vertical offset
31 | */
32 | var shadowOffset: CGPoint { get set }
33 | }
34 |
35 | public extension ShadowDesignable where Self: UIView {
36 | public func configShadowColor() {
37 | if let unwrappedShadowColor = shadowColor {
38 | commonSetup()
39 | layer.shadowColor = unwrappedShadowColor.CGColor
40 | }
41 | }
42 |
43 | public func configShadowRadius() {
44 | if !shadowRadius.isNaN && shadowRadius > 0 {
45 | commonSetup()
46 | layer.shadowRadius = shadowRadius
47 | }
48 | }
49 |
50 | public func configShadowOpacity() {
51 | if !shadowOpacity.isNaN && shadowOpacity >= 0 && shadowOpacity <= 1 {
52 | commonSetup()
53 | layer.shadowOpacity = Float(shadowOpacity)
54 | }
55 | }
56 |
57 | public func configShadowOffset() {
58 | if !shadowOffset.x.isNaN {
59 | commonSetup()
60 | layer.shadowOffset.width = shadowOffset.x
61 | }
62 |
63 | if !shadowOffset.y.isNaN {
64 | commonSetup()
65 | layer.shadowOffset.height = shadowOffset.y
66 | }
67 | }
68 |
69 | private func commonSetup() {
70 | // Need to set `layer.masksToBounds` to `false`.
71 | // If `layer.masksToBounds == true` then shadow doesn't work any more.
72 | if layer.masksToBounds {
73 | layer.masksToBounds = false
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/IBAnimatableApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/18/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @UIApplicationMain
9 | class AppDelegate: UIResponder, UIApplicationDelegate {
10 |
11 | var window: UIWindow?
12 |
13 |
14 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
15 | // Override point for customization after application launch.
16 | return true
17 | }
18 |
19 | func applicationWillResignActive(application: UIApplication) {
20 | // 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.
21 | // 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.
22 | }
23 |
24 | func applicationDidEnterBackground(application: UIApplication) {
25 | // 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.
26 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
27 | }
28 |
29 | func applicationWillEnterForeground(application: UIApplication) {
30 | // 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.
31 | }
32 |
33 | func applicationDidBecomeActive(application: UIApplication) {
34 | // 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.
35 | }
36 |
37 | func applicationWillTerminate(application: UIApplication) {
38 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Scripts/FlatColorsTypeScript.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/swift
2 |
3 | import Foundation
4 |
5 | let colorsTypeURL = "https://gist.githubusercontent.com/tkrugg/a577c32e93eecc6c7991/raw/f7866132e26f9bffcda9caf13dced55e4a99e145/flatuicolors.json"
6 |
7 | func JSONFromURL(urlToRequest: String) -> NSData {
8 | return NSData(contentsOfURL: NSURL(string: urlToRequest)!)!
9 | }
10 |
11 | func parseJSON(JSONData: NSData) -> [String: String]? {
12 | var json: [String: String]?
13 | do {
14 | json = try NSJSONSerialization.JSONObjectWithData(JSONData, options: .MutableContainers) as? [String: String]
15 | return json
16 | } catch {
17 | print("JSON serialization did fail")
18 | return nil
19 | }
20 | }
21 |
22 | // Generator constants
23 | let enumCase = "\tcase %@\n"
24 | let switchCase = "case .%@:\n"
25 | let color = "\treturn UIColor(red: %@ / 255, green: %@ / 255, blue: %@ / 255, alpha: %@)\n"
26 | let endEnumOrSwitch = "}"
27 |
28 | // Finale string
29 | var enumColorType = "public enum ColorType: String {\n"
30 | var switchColorType = "switch colorType {\n"
31 |
32 | // Enum generator
33 | let colorsType: Dictionary? = parseJSON(JSONFromURL(colorsTypeURL))
34 |
35 | // Parsing
36 | if let uwnrappedColorsType = colorsType {
37 | for colorName in uwnrappedColorsType.keys {
38 | if var unwrappedRGBColors = uwnrappedColorsType[colorName] {
39 | var finalName = colorName.capitalizedStringWithLocale(NSLocale.currentLocale())
40 | finalName = finalName.stringByReplacingOccurrencesOfString("-", withString: "")
41 | finalName = "Flat" + finalName
42 | enumColorType += String(format: enumCase, finalName)
43 | switchColorType += String(format: switchCase, finalName)
44 |
45 | unwrappedRGBColors = unwrappedRGBColors.stringByReplacingOccurrencesOfString("rgba(", withString: "")
46 | unwrappedRGBColors = unwrappedRGBColors.stringByReplacingOccurrencesOfString(")", withString: "")
47 | let colors = unwrappedRGBColors.componentsSeparatedByString(",")
48 | switchColorType += String(format: color, colors[0], colors[1], colors[2], colors[3])
49 | }
50 | }
51 |
52 | enumColorType += endEnumOrSwitch
53 | switchColorType += endEnumOrSwitch
54 | print(enumColorType)
55 | print("\n")
56 | print(switchColorType)
57 | }
58 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemRevealAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 02/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemRevealAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | // MARK: - private
16 | private var fromDirection: TransitionDirection
17 |
18 | public init(fromDirection: TransitionDirection, transitionDuration: Duration) {
19 | self.fromDirection = fromDirection
20 | self.transitionDuration = transitionDuration
21 |
22 | switch fromDirection {
23 | case .Right:
24 | self.transitionAnimationType = .SystemReveal(fromDirection: .Right)
25 | self.reverseAnimationType = .SystemReveal(fromDirection: .Left)
26 | self.interactiveGestureType = .Pan(fromDirection: .Left)
27 | case .Top:
28 | self.transitionAnimationType = .SystemReveal(fromDirection: .Top)
29 | self.reverseAnimationType = .SystemReveal(fromDirection: .Bottom)
30 | self.interactiveGestureType = .Pan(fromDirection: .Bottom)
31 | case .Bottom:
32 | self.transitionAnimationType = .SystemReveal(fromDirection: .Bottom)
33 | self.reverseAnimationType = .SystemReveal(fromDirection: .Top)
34 | self.interactiveGestureType = .Pan(fromDirection: .Top)
35 | default:
36 | self.transitionAnimationType = .SystemPush(fromDirection: .Left)
37 | self.reverseAnimationType = .SystemPush(fromDirection: .Right)
38 | self.interactiveGestureType = .Pan(fromDirection: .Right)
39 | }
40 |
41 | super.init()
42 | }
43 | }
44 |
45 | extension SystemRevealAnimator: UIViewControllerAnimatedTransitioning {
46 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
47 | return retrieveTransitionDuration(transitionContext)
48 | }
49 |
50 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
51 | animateWithCATransition(transitionContext, type: SystemTransitionType.Reveal, subtype: fromDirection.CATransitionSubtype)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemMoveInAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 02/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemMoveInAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | // MARK: - private
16 | private var fromDirection: TransitionDirection
17 |
18 | public init(fromDirection: TransitionDirection, transitionDuration: Duration) {
19 | self.fromDirection = fromDirection
20 | self.transitionDuration = transitionDuration
21 |
22 | switch fromDirection {
23 | case .Right:
24 | self.transitionAnimationType = .SystemMoveIn(fromDirection: .Right)
25 | self.reverseAnimationType = .SystemMoveIn(fromDirection: .Left)
26 | self.interactiveGestureType = .Pan(fromDirection: .Left)
27 | case .Top:
28 | self.transitionAnimationType = .SystemMoveIn(fromDirection: .Top)
29 | self.reverseAnimationType = .SystemMoveIn(fromDirection: .Bottom)
30 | self.interactiveGestureType = .Pan(fromDirection: .Bottom)
31 | case .Bottom:
32 | self.transitionAnimationType = .SystemMoveIn(fromDirection: .Bottom)
33 | self.reverseAnimationType = .SystemMoveIn(fromDirection: .Top)
34 | self.interactiveGestureType = .Pan(fromDirection: .Top)
35 | default:
36 | self.transitionAnimationType = .SystemMoveIn(fromDirection: .Left)
37 | self.reverseAnimationType = .SystemMoveIn(fromDirection: .Right)
38 | self.interactiveGestureType = .Pan(fromDirection: .Right)
39 | }
40 |
41 | super.init()
42 | }
43 | }
44 |
45 | extension SystemMoveInAnimator: UIViewControllerAnimatedTransitioning {
46 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
47 | return retrieveTransitionDuration(transitionContext)
48 | }
49 |
50 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
51 | animateWithCATransition(transitionContext, type: SystemTransitionType.MoveIn, subtype: fromDirection.CATransitionSubtype)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemPushAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SystemPushAnimator.swift
3 | // IBAnimatableApp
4 | //
5 | // Created by Tom Baranes on 02/04/16.
6 | // Copyright © 2016 Jake Lin. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class SystemPushAnimator: NSObject, AnimatedTransitioning {
12 | // MARK: - AnimatorProtocol
13 | public var transitionAnimationType: TransitionAnimationType
14 | public var transitionDuration: Duration = defaultTransitionDuration
15 | public var reverseAnimationType: TransitionAnimationType?
16 | public var interactiveGestureType: InteractiveGestureType?
17 |
18 | // MARK: - private
19 | private var fromDirection: TransitionDirection
20 |
21 | public init(fromDirection: TransitionDirection, transitionDuration: Duration) {
22 | self.fromDirection = fromDirection
23 | self.transitionDuration = transitionDuration
24 |
25 | switch fromDirection {
26 | case .Right:
27 | self.transitionAnimationType = .SystemPush(fromDirection: .Right)
28 | self.reverseAnimationType = .SystemPush(fromDirection: .Left)
29 | self.interactiveGestureType = .Pan(fromDirection: .Left)
30 | case .Top:
31 | self.transitionAnimationType = .SystemPush(fromDirection: .Top)
32 | self.reverseAnimationType = .SystemPush(fromDirection: .Bottom)
33 | self.interactiveGestureType = .Pan(fromDirection: .Bottom)
34 | case .Bottom:
35 | self.transitionAnimationType = .SystemPush(fromDirection: .Bottom)
36 | self.reverseAnimationType = .SystemPush(fromDirection: .Top)
37 | self.interactiveGestureType = .Pan(fromDirection: .Top)
38 | default:
39 | self.transitionAnimationType = .SystemPush(fromDirection: .Left)
40 | self.reverseAnimationType = .SystemPush(fromDirection: .Right)
41 | self.interactiveGestureType = .Pan(fromDirection: .Right)
42 | }
43 |
44 | super.init()
45 | }
46 | }
47 |
48 | extension SystemPushAnimator: UIViewControllerAnimatedTransitioning {
49 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
50 | return retrieveTransitionDuration(transitionContext)
51 | }
52 |
53 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
54 | animateWithCATransition(transitionContext, type: SystemTransitionType.Push, subtype: fromDirection.CATransitionSubtype)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemCubeAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright © 2016 Jake Lin. All rights reserved.
3 | //
4 |
5 | import UIKit
6 |
7 | /**
8 | System Cube Animator - To support 3D animation (Four rotation directions supported: left, right, top, bottom)
9 | */
10 | public class SystemCubeAnimator: NSObject, AnimatedTransitioning {
11 | // MARK: - AnimatorProtocol
12 | public var transitionAnimationType: TransitionAnimationType
13 | public var transitionDuration: Duration = defaultTransitionDuration
14 | public var reverseAnimationType: TransitionAnimationType?
15 | public var interactiveGestureType: InteractiveGestureType?
16 |
17 | // MARK: - private
18 | private var fromDirection: TransitionDirection
19 |
20 | public init(fromDirection: TransitionDirection, transitionDuration: Duration) {
21 | self.fromDirection = fromDirection
22 | self.transitionDuration = transitionDuration
23 |
24 | switch fromDirection {
25 | case .Right:
26 | self.transitionAnimationType = .SystemCube(fromDirection: .Right)
27 | self.reverseAnimationType = .SystemCube(fromDirection: .Left)
28 | self.interactiveGestureType = .Pan(fromDirection: .Left)
29 | case .Top:
30 | self.transitionAnimationType = .SystemCube(fromDirection: .Top)
31 | self.reverseAnimationType = .SystemCube(fromDirection: .Bottom)
32 | self.interactiveGestureType = .Pan(fromDirection: .Bottom)
33 | case .Bottom:
34 | self.transitionAnimationType = .SystemCube(fromDirection: .Bottom)
35 | self.reverseAnimationType = .SystemCube(fromDirection: .Top)
36 | self.interactiveGestureType = .Pan(fromDirection: .Top)
37 | default:
38 | self.transitionAnimationType = .SystemCube(fromDirection: .Left)
39 | self.reverseAnimationType = .SystemCube(fromDirection: .Right)
40 | self.interactiveGestureType = .Pan(fromDirection: .Right)
41 | }
42 |
43 | super.init()
44 | }
45 | }
46 |
47 | extension SystemCubeAnimator: UIViewControllerAnimatedTransitioning {
48 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
49 | return retrieveTransitionDuration(transitionContext)
50 | }
51 |
52 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
53 | animateWithCATransition(transitionContext, type: SystemTransitionType.Cube, subtype: fromDirection.CATransitionSubtype)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/IBAnimatable/PanInteractiveAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 3/3/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | // Pan interactive animator: pan gesture transition controller
9 | public class PanInteractiveAnimator: InteractiveAnimator {
10 |
11 | override func createGestureRecognizer() -> UIGestureRecognizer {
12 | return UIPanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
13 | }
14 |
15 | override func calculateProgress(gestureRecognizer: UIGestureRecognizer) -> (progress: CGFloat, shouldFinishInteractiveTransition: Bool) {
16 | guard let gestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer,
17 | superview = gestureRecognizer.view?.superview else {
18 | return (0, false)
19 | }
20 | let translation = gestureRecognizer.translationInView(superview)
21 | let velocity = gestureRecognizer.velocityInView(superview)
22 |
23 | var progress: CGFloat
24 | let distance: CGFloat
25 | let speed: CGFloat
26 | switch interactiveGestureType {
27 | case let .Pan(direction):
28 | switch direction {
29 | case .Horizontal:
30 | distance = superview.frame.width
31 | progress = abs(translation.x / distance)
32 | speed = abs(velocity.x)
33 | case .Left:
34 | distance = superview.frame.width
35 | progress = translation.x / distance
36 | speed = velocity.x
37 | case .Right:
38 | distance = superview.frame.width
39 | progress = -(translation.x / distance)
40 | speed = -velocity.x
41 | case .Vertical:
42 | distance = superview.frame.height
43 | progress = abs(translation.y / distance)
44 | speed = abs(velocity.y)
45 | case .Top:
46 | distance = superview.frame.height
47 | progress = translation.y / distance
48 | speed = velocity.y
49 | case .Bottom:
50 | distance = superview.frame.height
51 | progress = -translation.y / distance
52 | speed = -velocity.y
53 | default:
54 | return (0, false)
55 | }
56 | default:
57 | return (0, false)
58 | }
59 |
60 | progress = min(max(progress, 0), 0.99)
61 |
62 | // Finish the transition when pass the threathold
63 | let shouldFinishInteractiveTransition = progress > 0.5 || speed > 1000
64 | return (progress, shouldFinishInteractiveTransition)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/IBAnimatable/PinchInteractiveAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 4/26/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class PinchInteractiveAnimator: InteractiveAnimator {
9 | private var startScale: CGFloat = 0
10 |
11 | override func createGestureRecognizer() -> UIGestureRecognizer {
12 | let gestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
13 | return gestureRecognizer
14 | }
15 |
16 | override func shouldBeginProgress(gestureRecognizer: UIGestureRecognizer) -> Bool {
17 | guard let gestureRecognizer = gestureRecognizer as? UIPinchGestureRecognizer else {
18 | return false
19 | }
20 |
21 | switch interactiveGestureType {
22 | case let .Pinch(direction):
23 | switch direction {
24 | case .Close:
25 | return gestureRecognizer.velocity < 0
26 | case .Open:
27 | return gestureRecognizer.velocity > 0
28 | default:
29 | return true
30 | }
31 | default:
32 | return false
33 | }
34 | }
35 |
36 | override func calculateProgress(gestureRecognizer: UIGestureRecognizer) -> (progress: CGFloat, shouldFinishInteractiveTransition: Bool) {
37 | guard let gestureRecognizer = gestureRecognizer as? UIPinchGestureRecognizer,
38 | _ = gestureRecognizer.view?.superview else {
39 | return (0, false)
40 | }
41 |
42 | if gestureRecognizer.state == .Began {
43 | startScale = gestureRecognizer.scale
44 | }
45 |
46 | var progress: CGFloat
47 | let _: CGFloat
48 | switch interactiveGestureType {
49 | case let .Pinch(direction):
50 | switch direction {
51 | case .Close:
52 | progress = 1.0 - gestureRecognizer.scale / startScale
53 | case .Open:
54 | let scaleFator: CGFloat = 1.2 // To make the pinch open gesture more natural 😓
55 | progress = gestureRecognizer.scale / scaleFator - 1.0
56 | default:
57 | // For both `.Close` and `.Open`
58 | progress = abs(1.0 - gestureRecognizer.scale / startScale)
59 | }
60 | default:
61 | return (0, false)
62 | }
63 |
64 | progress = min(max(progress, 0), 0.99)
65 |
66 | // Finish the transition when pass the threathold
67 | let shouldFinishInteractiveTransition = progress > 0.5
68 |
69 | return (progress, shouldFinishInteractiveTransition)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemCameraIrisAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 30/03/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SystemCameraIrisAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | // MARK: - private
16 | private var hollowState: TransitionHollowState
17 |
18 | public init(hollowState: TransitionHollowState, transitionDuration: Duration) {
19 | self.transitionDuration = transitionDuration
20 | self.hollowState = hollowState
21 |
22 | switch hollowState {
23 | case .Open:
24 | self.transitionAnimationType = .SystemCameraIris(hollowState: .Open)
25 | self.reverseAnimationType = .SystemCameraIris(hollowState: .Close)
26 | self.interactiveGestureType = .Pinch(direction: .Close)
27 | case .Close:
28 | self.transitionAnimationType = .SystemCameraIris(hollowState: .Close)
29 | self.reverseAnimationType = .SystemCameraIris(hollowState: .Open)
30 | self.interactiveGestureType = .Pinch(direction: .Open)
31 | case .None:
32 | self.transitionAnimationType = .SystemCameraIris(hollowState: .None)
33 | self.reverseAnimationType = .SystemCameraIris(hollowState: .None)
34 | self.interactiveGestureType = .Pinch(direction: .Close)
35 | }
36 |
37 | super.init()
38 | }
39 | }
40 |
41 | extension SystemCameraIrisAnimator: UIViewControllerAnimatedTransitioning {
42 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
43 | return retrieveTransitionDuration(transitionContext)
44 | }
45 |
46 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
47 | switch self.hollowState {
48 | case .Open:
49 | animateWithCATransition(transitionContext, type: SystemTransitionType.CameraIrisHollowOpen, subtype: nil)
50 | case .Close:
51 | animateWithCATransition(transitionContext, type: SystemTransitionType.CameraIrisHollowClose, subtype: nil)
52 | case .None:
53 | animateWithCATransition(transitionContext, type: SystemTransitionType.CameraIris, subtype: nil)
54 |
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/IBAnimatable/SystemFlipAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/25/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | /**
9 | System Flip Animator - To support Flip animation (Four flip directions supported: left, right, top, bottom)
10 | */
11 | public class SystemFlipAnimator: NSObject, AnimatedTransitioning {
12 | // MARK: - AnimatorProtocol
13 | public var transitionAnimationType: TransitionAnimationType
14 | public var transitionDuration: Duration = defaultTransitionDuration
15 | public var reverseAnimationType: TransitionAnimationType?
16 | public var interactiveGestureType: InteractiveGestureType?
17 |
18 | // MARK: - private
19 | private var fromDirection: TransitionDirection
20 |
21 | public init(fromDirection: TransitionDirection, transitionDuration: Duration) {
22 | self.fromDirection = fromDirection
23 | self.transitionDuration = transitionDuration
24 |
25 | switch fromDirection {
26 | case .Right:
27 | self.transitionAnimationType = .SystemFlip(fromDirection: .Right)
28 | self.reverseAnimationType = .SystemFlip(fromDirection: .Left)
29 | self.interactiveGestureType = .Pan(fromDirection: .Left)
30 | case .Top:
31 | self.transitionAnimationType = .SystemFlip(fromDirection: .Top)
32 | self.reverseAnimationType = .SystemFlip(fromDirection: .Bottom)
33 | self.interactiveGestureType = .Pan(fromDirection: .Bottom)
34 | case .Bottom:
35 | self.transitionAnimationType = .SystemFlip(fromDirection: .Bottom)
36 | self.reverseAnimationType = .SystemFlip(fromDirection: .Top)
37 | self.interactiveGestureType = .Pan(fromDirection: .Top)
38 | default:
39 | self.transitionAnimationType = .SystemFlip(fromDirection: .Left)
40 | self.reverseAnimationType = .SystemFlip(fromDirection: .Right)
41 | self.interactiveGestureType = .Pan(fromDirection: .Right)
42 | }
43 |
44 | super.init()
45 | }
46 | }
47 |
48 | extension SystemFlipAnimator: UIViewControllerAnimatedTransitioning {
49 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
50 | return retrieveTransitionDuration(transitionContext)
51 | }
52 |
53 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
54 | animateWithCATransition(transitionContext, type: SystemTransitionType.Flip, subtype: fromDirection.CATransitionSubtype)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/14/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableViewController: UIViewController, ViewControllerDesignable, StatusBarDesignable, RootWindowDesignable, TransitionAnimatable {
9 | // MARK: - ViewControllerDesignable
10 | @IBInspectable public var hideNavigationBar: Bool = false
11 |
12 | // MARK: - StatusBarDesignable
13 | @IBInspectable public var lightStatusBar: Bool = false
14 |
15 | // MARK: - RootWindowDesignable
16 | @IBInspectable public var rootWindowBackgroundColor: UIColor?
17 |
18 | // MARK: - TransitionAnimatable
19 | @IBInspectable public var transitionAnimationType: String?
20 | @IBInspectable public var transitionDuration: Double = .NaN
21 | @IBInspectable public var interactiveGestureType: String?
22 |
23 | // MARK: - Lifecylce
24 | public override func viewWillAppear(animated: Bool) {
25 | super.viewWillAppear(animated)
26 | confingHideNavigationBar()
27 | configRootWindowBackgroundColor()
28 | }
29 |
30 | public override func viewWillDisappear(animated: Bool) {
31 | super.viewWillDisappear(animated)
32 | resetHideNavigationBar()
33 | }
34 |
35 | public override func preferredStatusBarStyle() -> UIStatusBarStyle {
36 | if lightStatusBar {
37 | return .LightContent
38 | }
39 | return .Default
40 | }
41 |
42 | public override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
43 | super.prepareForSegue(segue, sender: sender)
44 |
45 | // Configure custom transition animation
46 | guard let transitionAnimationType = transitionAnimationType, animationType = TransitionAnimationType.fromString(transitionAnimationType) else {
47 | super.prepareForSegue(segue, sender: sender)
48 | return
49 | }
50 |
51 | let toViewController = segue.destinationViewController
52 | // If interactiveGestureType has been set
53 | if let interactiveGestureType = interactiveGestureType, interactiveGestureTypeValue = InteractiveGestureType.fromString(interactiveGestureType) {
54 | toViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(animationType, transitionDuration: transitionDuration, interactiveGestureType: interactiveGestureTypeValue)
55 | } else {
56 | toViewController.transitioningDelegate = PresenterManager.sharedManager().retrievePresenter(animationType, transitionDuration: transitionDuration)
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableTextView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/19/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableTextView: UITextView, CornerDesignable, FillDesignable, BorderDesignable, Animatable {
9 |
10 | // MARK: - CornerDesignable
11 | @IBInspectable public var cornerRadius: CGFloat = CGFloat.NaN {
12 | didSet {
13 | configCornerRadius()
14 | }
15 | }
16 |
17 | // MARK: - FillDesignable
18 | @IBInspectable public var fillColor: UIColor? {
19 | didSet {
20 | configFillColor()
21 | }
22 | }
23 |
24 | @IBInspectable public var predefinedColor: String? {
25 | didSet {
26 | configFillColor()
27 | }
28 | }
29 |
30 | @IBInspectable public var opacity: CGFloat = CGFloat.NaN {
31 | didSet {
32 | configOpacity()
33 | }
34 | }
35 |
36 | // MARK: - BorderDesignable
37 | @IBInspectable public var borderColor: UIColor? {
38 | didSet {
39 | configBorder()
40 | }
41 | }
42 |
43 | @IBInspectable public var borderWidth: CGFloat = CGFloat.NaN {
44 | didSet {
45 | configBorder()
46 | }
47 | }
48 |
49 | @IBInspectable public var borderSide: String? {
50 | didSet {
51 | configBorder()
52 | }
53 | }
54 |
55 | // MARK: - Animatable
56 | @IBInspectable public var animationType: String?
57 | @IBInspectable public var autoRun: Bool = true
58 | @IBInspectable public var duration: Double = Double.NaN
59 | @IBInspectable public var delay: Double = Double.NaN
60 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
61 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
62 | @IBInspectable public var force: CGFloat = CGFloat.NaN
63 | @IBInspectable public var repeatCount: Float = Float.NaN
64 | @IBInspectable public var x: CGFloat = CGFloat.NaN
65 | @IBInspectable public var y: CGFloat = CGFloat.NaN
66 |
67 | // MARK: - Lifecycle
68 | public override func prepareForInterfaceBuilder() {
69 | super.prepareForInterfaceBuilder()
70 | configInspectableProperties()
71 | }
72 |
73 | public override func awakeFromNib() {
74 | super.awakeFromNib()
75 | configInspectableProperties()
76 | }
77 |
78 | public override func layoutSubviews() {
79 | super.layoutSubviews()
80 | configAfterLayoutSubviews()
81 | autoRunAnimation()
82 | }
83 |
84 | // MARK: - Private
85 | private func configInspectableProperties() {
86 | configAnimatableProperties()
87 | }
88 |
89 | private func configAfterLayoutSubviews() {
90 | configBorder()
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/Pages/Animation Properties.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | //: ## Animation Properties
4 |
5 | import UIKit
6 | import XCPlayground
7 | import IBAnimatable
8 |
9 | //: Constants
10 | let iPhoneWidth = 375
11 | let iPhoneHeight = 667
12 | let animatableViewWidth = 100
13 | let animatableViewX = (iPhoneWidth - animatableViewWidth) / 2
14 | let animatableViewY = (iPhoneHeight - animatableViewWidth) / 2
15 |
16 | //: Set up the iPhone View
17 | let iPhoneView = UIView(frame: CGRect(x: 0, y: 0, width: iPhoneWidth, height: iPhoneHeight))
18 | iPhoneView.backgroundColor = .whiteColor()
19 | XCPlaygroundPage.currentPage.liveView = iPhoneView
20 |
21 | //: Set up the animatable View
22 | let view = AnimatableView(frame: CGRect(x: animatableViewX, y: animatableViewY, width: animatableViewWidth, height: animatableViewWidth))
23 | view.configAnimatableProperties()
24 | iPhoneView.addSubview(view)
25 |
26 | view.fillColor = UIColor(red: 0xba/0xff, green: 0x77/0xff, blue: 1, alpha: 1)
27 | view.maskType = String(MaskType.Circle)
28 |
29 | //: animationType: all supported predefined animations can be found in `enum AnimationType`
30 | view.animationType = String(AnimationType.SqueezeInLeft)
31 |
32 | //: duration: used to specify the duration of animation. Default value is 0.7
33 | view.duration = 0.8
34 |
35 | //: delay: used to delay the animation in seconds. Default value is 0
36 | view.delay = 0.5
37 |
38 | //: damping: used in UIView Spring animation (0 ~ 1). To smoothly decelerate the animation without oscillation, use a value of 1. Employ a damping ratio closer to zero to increase oscillation. Default is 0.7. Notice: FadeOutIn, FadeInOut, Shake, Pop, Morph, Squeeze, Flash, Wobble and Swing animations do not use damping.
39 | view.damping = 0.5
40 |
41 | //: velocity: used in UIView Spring animation. A value of 1 corresponds to the total animation distance traversed in one second. For example, if the total animation distance is 200 points and you want the start of the animation to match a view velocity of 100 pt/s, use a value of 0.5. Default is 0.7. Notice: FadeOutIn, FadeInOut, Shake, Pop, Morph, Squeeze, Flash, Wobble and Swing animations do not use damping.
42 | view.velocity = 2
43 |
44 | //: force: used to apply force to the animation. The number is higher, the animation property has more changes. eg. for Pop animation, higher force causes the view poping bigger. Default is 1
45 | view.force = 1
46 |
47 | //: repeatCount: used to sepecify the count to repeat the animation. Can noly used in Shake, Pop, Morph, Squeeze, Flash, Wobble, Swing and Rotate animations
48 | view.repeatCount = 5
49 |
50 | view.animate()
51 |
52 | //: [Next](@next)
53 |
--------------------------------------------------------------------------------
/IBAnimatable.playground/Pages/Predefined Animations.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: ## Predefined Animations
2 |
3 | import UIKit
4 | import XCPlayground
5 | import IBAnimatable
6 |
7 | //: Constants
8 | let iPhoneWidth = 375
9 | let iPhoneHeight = 667
10 | let animatableViewWidth = 100
11 | let animatableViewX = (iPhoneWidth - animatableViewWidth) / 2
12 | let animatableViewY = (iPhoneHeight - animatableViewWidth) / 2
13 |
14 | //: Set up the iPhone View
15 | let iPhoneView = UIView(frame: CGRect(x: 0, y: 0, width: iPhoneWidth, height: iPhoneHeight))
16 | iPhoneView.backgroundColor = .whiteColor()
17 | XCPlaygroundPage.currentPage.liveView = iPhoneView
18 |
19 | //: Set up the animatable View
20 | let view = AnimatableView(frame: CGRect(x: animatableViewX, y: animatableViewY, width: animatableViewWidth, height: animatableViewWidth))
21 | view.configAnimatableProperties()
22 | iPhoneView.addSubview(view)
23 |
24 | view.fillColor = UIColor(red: 0xba/0xff, green: 0x77/0xff, blue: 1, alpha: 1)
25 | view.borderWidth = 2
26 | view.borderColor = UIColor.purpleColor()
27 | view.maskType = String(MaskType.Circle)
28 |
29 | // For moveTo or moveBy animation
30 | view.x = -100
31 | view.y = 200
32 |
33 | //: Animations, all supported predefined animations can be found in `enum AnimationType`
34 |
35 | // Uncomment one line to play the animation
36 |
37 | //view.moveX()
38 | //view.moveY()
39 | //view.moveXY()
40 | //view.slideInLeft()
41 | //view.slideInRight()
42 | //view.slideInDown()
43 | //view.slideInUp()
44 | //view.slideOutLeft()
45 | //view.slideOutRight()
46 | //view.slideOutDown()
47 | //view.slideOutUp()
48 | //view.squeezeInLeft()
49 | //view.squeezeInRight()
50 | //view.squeezeInDown()
51 | //view.squeezeInUp()
52 | //view.squeezeOutLeft()
53 | //view.squeezeOutRight()
54 | //view.squeezeOutDown()
55 | //view.squeezeOutUp()
56 | //view.fadeIn()
57 | //view.fadeOut()
58 | //view.fadeOutIn()
59 | //view.fadeInOut()
60 | //view.fadeInLeft()
61 | //view.fadeInRight()
62 | //view.fadeInDown()
63 | //view.fadeInUp()
64 | //view.fadeOutLeft()
65 | //view.fadeOutRight()
66 | //view.fadeOutDown()
67 | //view.fadeOutUp()
68 | //view.squeezeFadeInLeft()
69 | //view.squeezeFadeInRight()
70 | //view.squeezeFadeInDown()
71 | //view.squeezeFadeInUp()
72 | //view.squeezeFadeOutLeft()
73 | //view.squeezeFadeOutRight()
74 | //view.squeezeFadeOutDown()
75 | //view.squeezeFadeOutUp()
76 | //view.zoomIn()
77 | //view.zoomOut()
78 | //view.shake()
79 | //view.pop()
80 | //view.flipX()
81 | //view.flipY()
82 | //view.morph()
83 | //view.squeeze()
84 | //view.flash()
85 | //view.wobble()
86 | //view.swing()
87 | //view.rotate()
88 | //view.rotate(clockwise: false)
89 | //view.moveTo()
90 | view.moveBy()
91 |
92 | //: [Next](@next)
93 |
--------------------------------------------------------------------------------
/IBAnimatable/InteractiveGestureType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 3/3/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | /**
9 | The interactive gesture type
10 | */
11 | public enum InteractiveGestureType {
12 | case Default // Will use the default interactive gesture type from `AnimatedTransitioning`
13 | case Pan(fromDirection: GestureDirection)
14 | case ScreenEdgePan(fromDirection: GestureDirection)
15 | case Pinch(direction: GestureDirection)
16 |
17 | var stringValue: String {
18 | return String(self)
19 | }
20 |
21 | public static func fromString(interactiveGestureType: String) -> InteractiveGestureType? {
22 | if interactiveGestureType.hasPrefix("Default") {
23 | return .Default
24 | } else if interactiveGestureType.hasPrefix("Pan") || interactiveGestureType.hasPrefix("ScreenEdgePan") ||
25 | interactiveGestureType.hasPrefix("Pinch") {
26 | return fromStringWithDirection(interactiveGestureType)
27 | }
28 | return nil
29 | }
30 |
31 | // Return the `String` without qualification
32 | public func toString() -> String {
33 | let namespace = "IBAnimatable." + String(GestureDirection) + "."
34 | return String(self).stringByReplacingOccurrencesOfString(namespace, withString: "")
35 | }
36 | }
37 |
38 | // MARK: - InteractiveGestureType from string
39 |
40 | private extension InteractiveGestureType {
41 | static func cleanInteractiveGestureType(interactiveGestureType: String) -> String {
42 | let range = interactiveGestureType.rangeOfString("(")
43 | let interactiveGestureType = interactiveGestureType.stringByReplacingOccurrencesOfString(" ", withString: "")
44 | .lowercaseString
45 | .substringFromIndex(range?.startIndex ?? interactiveGestureType.endIndex)
46 | .stringByReplacingOccurrencesOfString("(", withString: "")
47 | .stringByReplacingOccurrencesOfString(")", withString: "")
48 | .capitalizedString
49 | return interactiveGestureType
50 | }
51 |
52 | static func fromStringWithDirection(interactiveGestureType: String) -> InteractiveGestureType? {
53 | let gestureDirectionString = cleanInteractiveGestureType(interactiveGestureType)
54 |
55 | guard let direction = GestureDirection(rawValue: gestureDirectionString) else {
56 | return nil
57 | }
58 |
59 | if interactiveGestureType.hasPrefix("Pan") {
60 | return .Pan(fromDirection: direction)
61 | } else if interactiveGestureType.hasPrefix("ScreenEdgePan") {
62 | return .ScreenEdgePan(fromDirection: direction)
63 | } else if interactiveGestureType.hasPrefix("Pinch") {
64 | return .Pinch(direction: direction)
65 | }
66 |
67 | return nil
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableTableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/15/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableTableView: UITableView, FillDesignable, BorderDesignable, GradientDesignable, Animatable {
9 |
10 | // MARK: - FillDesignable
11 | @IBInspectable public var fillColor: UIColor? {
12 | didSet {
13 | configFillColor()
14 | }
15 | }
16 |
17 | @IBInspectable public var predefinedColor: String? {
18 | didSet {
19 | configFillColor()
20 | }
21 | }
22 |
23 | @IBInspectable public var opacity: CGFloat = CGFloat.NaN {
24 | didSet {
25 | configOpacity()
26 | }
27 | }
28 |
29 | // MARK: - BorderDesignable
30 | @IBInspectable public var borderColor: UIColor? {
31 | didSet {
32 | configBorder()
33 | }
34 | }
35 |
36 | @IBInspectable public var borderWidth: CGFloat = CGFloat.NaN {
37 | didSet {
38 | configBorder()
39 | }
40 | }
41 |
42 | @IBInspectable public var borderSide: String? {
43 | didSet {
44 | configBorder()
45 | }
46 | }
47 |
48 | // MARK: - GradientDesignable
49 | @IBInspectable public var startColor: UIColor?
50 | @IBInspectable public var endColor: UIColor?
51 | @IBInspectable public var predefinedGradient: String?
52 | @IBInspectable public var startPoint: String?
53 |
54 | // MARK: - Animatable
55 | @IBInspectable public var animationType: String?
56 | @IBInspectable public var autoRun: Bool = true
57 | @IBInspectable public var duration: Double = Double.NaN
58 | @IBInspectable public var delay: Double = Double.NaN
59 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
60 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
61 | @IBInspectable public var force: CGFloat = CGFloat.NaN
62 | @IBInspectable public var repeatCount: Float = Float.NaN
63 | @IBInspectable public var x: CGFloat = CGFloat.NaN
64 | @IBInspectable public var y: CGFloat = CGFloat.NaN
65 |
66 | // MARK: - Lifecycle
67 | public override func prepareForInterfaceBuilder() {
68 | super.prepareForInterfaceBuilder()
69 | configInspectableProperties()
70 | }
71 |
72 | public override func awakeFromNib() {
73 | super.awakeFromNib()
74 | configInspectableProperties()
75 | }
76 |
77 | public override func layoutSubviews() {
78 | super.layoutSubviews()
79 | autoRunAnimation()
80 | configAfterLayoutSubviews()
81 | }
82 |
83 | // MARK: - Private
84 | private func configInspectableProperties() {
85 | configAnimatableProperties()
86 | configOpacity()
87 |
88 | }
89 |
90 | private func configAfterLayoutSubviews() {
91 | configBorder()
92 | configGradient()
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/IBAnimatable/FadeAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/27/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class FadeAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType? = .Pan(fromDirection: .Horizontal)
14 |
15 | // MARK: - private
16 | private var direction: TransitionDirection
17 |
18 | public init(direction: TransitionDirection, transitionDuration: Duration) {
19 | self.direction = direction
20 | self.transitionDuration = transitionDuration
21 |
22 | switch direction {
23 | case .In:
24 | self.transitionAnimationType = .Fade(direction: .In)
25 | self.reverseAnimationType = .Fade(direction: .Out)
26 | case .Out:
27 | self.transitionAnimationType = .Fade(direction: .Out)
28 | self.reverseAnimationType = .Fade(direction: .In)
29 | default:
30 | self.transitionAnimationType = .Fade(direction: .Cross)
31 | self.reverseAnimationType = .Fade(direction: .Cross)
32 | }
33 |
34 | super.init()
35 | }
36 | }
37 |
38 | extension FadeAnimator: UIViewControllerAnimatedTransitioning {
39 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
40 | return retrieveTransitionDuration(transitionContext)
41 | }
42 |
43 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
44 | let (tempfromView, tempToView, tempContainerView) = retrieveViews(transitionContext)
45 | guard let fromView = tempfromView, toView = tempToView, containerView = tempContainerView else {
46 | transitionContext.completeTransition(true)
47 | return
48 | }
49 |
50 | switch direction {
51 | case .In:
52 | toView.alpha = 0
53 | containerView.addSubview(toView)
54 | case .Out:
55 | containerView.insertSubview(toView, belowSubview: fromView)
56 | default:
57 | toView.alpha = 0
58 | containerView.addSubview(toView)
59 | }
60 |
61 | UIView.animateWithDuration(transitionDuration(transitionContext),
62 | animations: {
63 | switch self.direction {
64 | case .In:
65 | toView.alpha = 1
66 | case .Out:
67 | fromView.alpha = 0
68 | default:
69 | fromView.alpha = 0
70 | toView.alpha = 1
71 | }
72 | },
73 | completion: { _ in
74 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
75 | })
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/20/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableLabel: UILabel, CornerDesignable, FillDesignable, Animatable, RotationDesignable, BorderDesignable {
9 |
10 | // MARK: - CornerDesignable
11 | @IBInspectable public var cornerRadius: CGFloat = CGFloat.NaN {
12 | didSet {
13 | configCornerRadius()
14 | }
15 | }
16 |
17 | // MARK: - FillDesignable
18 | @IBInspectable public var fillColor: UIColor? {
19 | didSet {
20 | configFillColor()
21 | }
22 | }
23 |
24 | @IBInspectable public var predefinedColor: String? {
25 | didSet {
26 | configFillColor()
27 | }
28 | }
29 |
30 | @IBInspectable public var opacity: CGFloat = CGFloat.NaN {
31 | didSet {
32 | configOpacity()
33 | }
34 | }
35 |
36 | // MARK: - BorderDesignable
37 | @IBInspectable public var borderColor: UIColor? {
38 | didSet {
39 | configBorder()
40 | }
41 | }
42 |
43 | @IBInspectable public var borderWidth: CGFloat = CGFloat.NaN {
44 | didSet {
45 | configBorder()
46 | }
47 | }
48 |
49 | @IBInspectable public var borderSide: String? {
50 | didSet {
51 | configBorder()
52 | }
53 | }
54 |
55 | // MARK: - Animatable
56 | @IBInspectable public var animationType: String?
57 | @IBInspectable public var autoRun: Bool = true
58 | @IBInspectable public var duration: Double = Double.NaN
59 | @IBInspectable public var delay: Double = Double.NaN
60 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
61 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
62 | @IBInspectable public var force: CGFloat = CGFloat.NaN
63 | @IBInspectable public var repeatCount: Float = Float.NaN
64 | @IBInspectable public var x: CGFloat = CGFloat.NaN
65 | @IBInspectable public var y: CGFloat = CGFloat.NaN
66 |
67 | // MARK: - RotationDesignable
68 | @IBInspectable public var rotate: CGFloat = CGFloat.NaN {
69 | didSet {
70 | configRotate()
71 | }
72 | }
73 |
74 | // MARK: - Lifecycle
75 | public override func prepareForInterfaceBuilder() {
76 | super.prepareForInterfaceBuilder()
77 | configInspectableProperties()
78 | }
79 |
80 | public override func awakeFromNib() {
81 | super.awakeFromNib()
82 | configInspectableProperties()
83 | }
84 |
85 | public override func layoutSubviews() {
86 | super.layoutSubviews()
87 | configAfterLayoutSubviews()
88 | autoRunAnimation()
89 | }
90 |
91 | // MARK: - Private
92 | private func configInspectableProperties() {
93 | configAnimatableProperties()
94 | configBorder()
95 | }
96 |
97 | private func configAfterLayoutSubviews() {
98 | configBorder()
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/16/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableTableViewCell: UITableViewCell, FillDesignable, BorderDesignable, TableViewCellDesignable, GradientDesignable, Animatable {
9 |
10 | // MARK: - FillDesignable
11 | @IBInspectable public var fillColor: UIColor? {
12 | didSet {
13 | configFillColor()
14 | }
15 | }
16 |
17 | @IBInspectable public var predefinedColor: String? {
18 | didSet {
19 | configFillColor()
20 | }
21 | }
22 |
23 | @IBInspectable public var opacity: CGFloat = CGFloat.NaN {
24 | didSet {
25 | configOpacity()
26 | }
27 | }
28 |
29 | // MARK: - BorderDesignable
30 | @IBInspectable public var borderColor: UIColor? {
31 | didSet {
32 | configBorder()
33 | }
34 | }
35 |
36 | @IBInspectable public var borderWidth: CGFloat = CGFloat.NaN {
37 | didSet {
38 | configBorder()
39 | }
40 | }
41 |
42 | @IBInspectable public var borderSide: String? {
43 | didSet {
44 | configBorder()
45 | }
46 | }
47 |
48 | // MARK: - TableViewCellDesignable
49 | @IBInspectable public var removeSeparatorMargins: Bool = false
50 |
51 | // MARK: - GradientDesignable
52 | @IBInspectable public var startColor: UIColor?
53 | @IBInspectable public var endColor: UIColor?
54 | @IBInspectable public var predefinedGradient: String?
55 | @IBInspectable public var startPoint: String?
56 |
57 | // MARK: - Animatable
58 | @IBInspectable public var animationType: String?
59 | @IBInspectable public var autoRun: Bool = true
60 | @IBInspectable public var duration: Double = Double.NaN
61 | @IBInspectable public var delay: Double = Double.NaN
62 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
63 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
64 | @IBInspectable public var force: CGFloat = CGFloat.NaN
65 | @IBInspectable public var repeatCount: Float = Float.NaN
66 | @IBInspectable public var x: CGFloat = CGFloat.NaN
67 | @IBInspectable public var y: CGFloat = CGFloat.NaN
68 |
69 | // MARK: - Lifecycle
70 | public override func prepareForInterfaceBuilder() {
71 | super.prepareForInterfaceBuilder()
72 | configInspectableProperties()
73 | }
74 |
75 | public override func awakeFromNib() {
76 | super.awakeFromNib()
77 | configInspectableProperties()
78 | }
79 |
80 | public override func layoutSubviews() {
81 | super.layoutSubviews()
82 | configAfterLayoutSubviews()
83 | autoRunAnimation()
84 | }
85 |
86 | // MARK: - Private
87 | private func configInspectableProperties() {
88 | configAnimatableProperties()
89 | configOpacity()
90 | configSeparatorMargins()
91 | }
92 |
93 | private func configAfterLayoutSubviews() {
94 | configBorder()
95 | configGradient()
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatedTransitioning.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/24/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | /**
8 | AnimatedTransitioning is the protocol of all Animator subclasses
9 | */
10 | public protocol AnimatedTransitioning: UIViewControllerAnimatedTransitioning {
11 |
12 | /**
13 | Value of `TransitionAnimationType` enum
14 | */
15 | var transitionAnimationType: TransitionAnimationType { get set }
16 |
17 | /**
18 | Transition duration
19 | */
20 | var transitionDuration: Duration { get set }
21 |
22 | /**
23 | Reverse animation type: used to specify the revers animation for pop or dismiss.
24 | */
25 | var reverseAnimationType: TransitionAnimationType? { get set }
26 |
27 | /**
28 | Interactive gesture type: used to specify the gesture type to pop or dismiss.
29 | */
30 | var interactiveGestureType: InteractiveGestureType? { get set }
31 | }
32 |
33 | public extension AnimatedTransitioning {
34 | public func retrieveViews(transitionContext: UIViewControllerContextTransitioning) -> (UIView?, UIView?, UIView?) {
35 | return (transitionContext.viewForKey(UITransitionContextFromViewKey), transitionContext.viewForKey(UITransitionContextToViewKey), transitionContext.containerView())
36 | }
37 |
38 | public func retrieveViewControllers(transitionContext: UIViewControllerContextTransitioning) -> (UIViewController?, UIViewController?, UIView?) {
39 | return (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey), transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey), transitionContext.containerView())
40 | }
41 |
42 | public func retrieveTransitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
43 | if let transitionContext = transitionContext {
44 | return transitionContext.isAnimated() ? transitionDuration : 0
45 | }
46 | return 0
47 | }
48 |
49 | public func animateWithCATransition(transitionContext: UIViewControllerContextTransitioning, type: SystemTransitionType, subtype: String?) {
50 | let (_, tempToView, tempContainerView) = retrieveViews(transitionContext)
51 | guard let toView = tempToView, containerView = tempContainerView else {
52 | transitionContext.completeTransition(true)
53 | return
54 | }
55 |
56 | containerView.addSubview(toView)
57 | CALayer.animate({
58 | let transition = CATransition()
59 | transition.type = type.rawValue
60 | if let subtype = subtype {
61 | transition.subtype = subtype
62 | }
63 | transition.duration = self.transitionDuration(transitionContext)
64 | // Use `EaseOutQubic` for system built-in transition animations. Thanks to @lexrus
65 | transition.timingFunction = CAMediaTimingFunction(controlPoints: 0.215, 0.61, 0.355, 1)
66 | containerView.layer.addAnimation(transition, forKey: kCATransition)
67 | },
68 | completion: {
69 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
70 | })
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/IBAnimatable/ScreenEdgePanInteractiveAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 4/5/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class ScreenEdgePanInteractiveAnimator: InteractiveAnimator {
9 |
10 | override func createGestureRecognizer() -> UIGestureRecognizer {
11 | let gestureRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleGesture(_:)))
12 | switch interactiveGestureType {
13 | case let .ScreenEdgePan(direction):
14 | switch direction {
15 | case .Left:
16 | gestureRecognizer.edges = .Left
17 | case .Right:
18 | gestureRecognizer.edges = .Right
19 | case .Horizontal:
20 | gestureRecognizer.edges = [.Left, .Right]
21 | case .Top:
22 | gestureRecognizer.edges = .Top
23 | case .Bottom:
24 | gestureRecognizer.edges = .Bottom
25 | case .Vertical:
26 | gestureRecognizer.edges = [.Top, .Bottom]
27 | default:
28 | break
29 | }
30 | default:
31 | break
32 | }
33 | return gestureRecognizer
34 | }
35 |
36 | override func calculateProgress(gestureRecognizer: UIGestureRecognizer) -> (progress: CGFloat, shouldFinishInteractiveTransition: Bool) {
37 | guard let gestureRecognizer = gestureRecognizer as? UIScreenEdgePanGestureRecognizer,
38 | superview = gestureRecognizer.view?.superview else {
39 | return (0, false)
40 | }
41 | let translation = gestureRecognizer.translationInView(superview)
42 | let velocity = gestureRecognizer.velocityInView(superview)
43 |
44 | var progress: CGFloat
45 | let distance: CGFloat
46 | let speed: CGFloat
47 | switch interactiveGestureType {
48 | case let .ScreenEdgePan(direction):
49 | switch direction {
50 | case .Horizontal:
51 | distance = superview.frame.width
52 | progress = abs(translation.x / distance)
53 | speed = abs(velocity.x)
54 | case .Left:
55 | distance = superview.frame.width
56 | progress = translation.x / distance
57 | speed = velocity.x
58 | case .Right:
59 | distance = superview.frame.width
60 | progress = -(translation.x / distance)
61 | speed = -velocity.x
62 | case .Vertical:
63 | distance = superview.frame.height
64 | progress = abs(translation.y / distance)
65 | speed = abs(velocity.y)
66 | case .Top:
67 | distance = superview.frame.height
68 | progress = translation.y / distance
69 | speed = velocity.y
70 | case .Bottom:
71 | distance = superview.frame.height
72 | progress = -translation.y / distance
73 | speed = -velocity.y
74 | default:
75 | return (0, false)
76 | }
77 | default:
78 | return (0, false)
79 | }
80 |
81 | progress = min(max(progress, 0), 0.99)
82 |
83 | // Finish the transition when pass the threathold
84 | let shouldFinishInteractiveTransition = progress > 0.5 || speed > 1000
85 |
86 | return (progress, shouldFinishInteractiveTransition)
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/IBAnimatableApp/ContainerTransitionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 07/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | import IBAnimatable
8 |
9 | class ContainerTransitionViewController: UIViewController, UITabBarDelegate {
10 |
11 | // MARK: Properties
12 |
13 | @IBOutlet var tabBar: UITabBar!
14 | @IBOutlet var containerView: UIView!
15 |
16 | private var viewControllers = [AnimatableViewController]()
17 | private var currentViewController: AnimatableViewController?
18 |
19 | // MARK: Life cycle
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 | createChildViewControllers()
24 | tabBar.selectedItem = tabBar.items?.first
25 | }
26 |
27 | }
28 |
29 | // MARK: - ChildViewController
30 |
31 | private extension ContainerTransitionViewController {
32 |
33 | func createChildViewControllers() {
34 | var viewController = AnimatableViewController()
35 | viewController.view.backgroundColor = UIColor.blueColor()
36 | viewController.transitionAnimationType = "Explode"
37 | viewControllers.append(viewController)
38 |
39 | viewController = AnimatableViewController()
40 | viewController.view.backgroundColor = UIColor.greenColor()
41 | viewController.transitionAnimationType = "Fold"
42 | viewControllers.append(viewController)
43 |
44 | viewController = AnimatableViewController()
45 | viewController.view.backgroundColor = UIColor.yellowColor()
46 | viewController.transitionAnimationType = "NatGeo"
47 | viewControllers.append(viewController)
48 |
49 | viewController = AnimatableViewController()
50 | viewController.view.backgroundColor = UIColor.redColor()
51 | viewController.transitionAnimationType = "Portal"
52 | viewControllers.append(viewController)
53 |
54 | cycleFromViewController(containerView, fromViewController: nil, toViewController: viewControllers[0])
55 |
56 | }
57 |
58 | func cycleFromViewController(containerView: UIView, fromViewController: AnimatableViewController?, toViewController: AnimatableViewController) {
59 | guard let animationType = TransitionAnimationType.fromString(toViewController.transitionAnimationType ?? "") else {
60 | return
61 | }
62 |
63 | let transitionContext = ContainerTransition(animationType: animationType,
64 | container: containerView,
65 | parentViewController: self,
66 | fromViewController: fromViewController,
67 | toViewController: toViewController) {
68 | self.currentViewController = toViewController
69 | }
70 | transitionContext.animate()
71 | }
72 |
73 | }
74 |
75 | // MARK: - UITabBarDelegate
76 |
77 | extension ContainerTransitionViewController {
78 |
79 | func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
80 | let toViewController = viewControllers[item.tag]
81 | cycleFromViewController(containerView, fromViewController: currentViewController, toViewController: toViewController)
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/IBAnimatable/Navigator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/24/16.
3 | // Copyright (c) 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | /**
9 | Navigator for `UINavigationController` to support custom transition animation for Push and Pop
10 | */
11 | public class Navigator: NSObject {
12 | var transitionAnimationType: TransitionAnimationType
13 | var transitionDuration: Duration = defaultTransitionDuration
14 |
15 | // animation controller
16 | private var animator: AnimatedTransitioning?
17 | // interaction controller
18 | private var interactiveAnimator: InteractiveAnimator?
19 |
20 | public init(transitionAnimationType: TransitionAnimationType, transitionDuration: Duration = defaultTransitionDuration, interactiveGestureType: InteractiveGestureType? = nil) {
21 | self.transitionAnimationType = transitionAnimationType
22 | self.transitionDuration = transitionDuration
23 | super.init()
24 |
25 | animator = AnimatorFactory.generateAnimator(transitionAnimationType, transitionDuration: transitionDuration)
26 |
27 | // If interactiveGestureType has been set
28 | if let interactiveGestureType = interactiveGestureType {
29 | // If configured as `.Default` then use the default interactive gesture type from the Animator
30 | switch interactiveGestureType {
31 | case .Default:
32 | if let interactiveGestureType = animator?.interactiveGestureType {
33 | interactiveAnimator = InteractiveAnimatorFactory.generateInteractiveAnimator(interactiveGestureType, transitionType: .NavigationTransition(.Pop))
34 | }
35 | default:
36 | interactiveAnimator = InteractiveAnimatorFactory.generateInteractiveAnimator(interactiveGestureType, transitionType: .NavigationTransition(.Pop))
37 | }
38 | }
39 | }
40 | }
41 |
42 | extension Navigator: UINavigationControllerDelegate {
43 | // MARK: - animation controller
44 | public func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
45 | interactiveAnimator?.connectGestureRecognizer(toVC)
46 |
47 | if operation == .Push {
48 | animator?.transitionDuration = transitionDuration
49 | return animator
50 | } else if operation == .Pop {
51 | // Use the reverse animation
52 | if let reverseTransitionAnimationType = animator?.reverseAnimationType {
53 | return AnimatorFactory.generateAnimator(reverseTransitionAnimationType, transitionDuration: transitionDuration)
54 | }
55 | }
56 | return nil
57 | }
58 |
59 | // MARK: - interaction controller
60 | public func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
61 | if let interactiveAnimator = interactiveAnimator where interactiveAnimator.interacting {
62 | return interactiveAnimator
63 | } else {
64 | return nil
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 11/04/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableCollectionViewCell: UICollectionViewCell, CornerDesignable, FillDesignable, BorderDesignable, TableViewCellDesignable, GradientDesignable, Animatable {
9 |
10 | // MARK: - CornerDesignable
11 | @IBInspectable public var cornerRadius: CGFloat = CGFloat.NaN {
12 | didSet {
13 | configCornerRadius()
14 | }
15 | }
16 |
17 | // MARK: - FillDesignable
18 | @IBInspectable public var fillColor: UIColor? {
19 | didSet {
20 | configFillColor()
21 | }
22 | }
23 |
24 | @IBInspectable public var predefinedColor: String? {
25 | didSet {
26 | configFillColor()
27 | }
28 | }
29 |
30 | @IBInspectable public var opacity: CGFloat = CGFloat.NaN {
31 | didSet {
32 | configOpacity()
33 | }
34 | }
35 |
36 | // MARK: - BorderDesignable
37 | @IBInspectable public var borderColor: UIColor? {
38 | didSet {
39 | configBorder()
40 | }
41 | }
42 |
43 | @IBInspectable public var borderWidth: CGFloat = CGFloat.NaN {
44 | didSet {
45 | configBorder()
46 | }
47 | }
48 |
49 | @IBInspectable public var borderSide: String? {
50 | didSet {
51 | configBorder()
52 | }
53 | }
54 |
55 | // MARK: - TableViewCellDesignable
56 | @IBInspectable public var removeSeparatorMargins: Bool = false
57 |
58 | // MARK: - GradientDesignable
59 | @IBInspectable public var startColor: UIColor?
60 | @IBInspectable public var endColor: UIColor?
61 | @IBInspectable public var predefinedGradient: String?
62 | @IBInspectable public var startPoint: String?
63 |
64 | // MARK: - Animatable
65 | @IBInspectable public var animationType: String?
66 | @IBInspectable public var autoRun: Bool = true
67 | @IBInspectable public var duration: Double = Double.NaN
68 | @IBInspectable public var delay: Double = Double.NaN
69 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
70 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
71 | @IBInspectable public var force: CGFloat = CGFloat.NaN
72 | @IBInspectable public var repeatCount: Float = Float.NaN
73 | @IBInspectable public var x: CGFloat = CGFloat.NaN
74 | @IBInspectable public var y: CGFloat = CGFloat.NaN
75 |
76 | // MARK: - Lifecycle
77 | public override func prepareForInterfaceBuilder() {
78 | super.prepareForInterfaceBuilder()
79 | configInspectableProperties()
80 | }
81 |
82 | public override func awakeFromNib() {
83 | super.awakeFromNib()
84 | configInspectableProperties()
85 | }
86 |
87 | public override func layoutSubviews() {
88 | super.layoutSubviews()
89 | configAfterLayoutSubviews()
90 | autoRunAnimation()
91 | }
92 |
93 | // MARK: - Private
94 | private func configInspectableProperties() {
95 | configAnimatableProperties()
96 | configOpacity()
97 | }
98 |
99 | private func configAfterLayoutSubviews() {
100 | configBorder()
101 | configGradient()
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatorFactory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/24/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 | /**
8 | Animator Factory
9 | */
10 | public struct AnimatorFactory {
11 | public static func generateAnimator(transitionAnimationType: TransitionAnimationType) -> AnimatedTransitioning {
12 | return generateAnimator(transitionAnimationType, transitionDuration: defaultTransitionDuration)
13 | }
14 |
15 | public static func generateAnimator(transitionAnimationType: TransitionAnimationType, transitionDuration: Duration) -> AnimatedTransitioning {
16 | switch transitionAnimationType {
17 | case .SystemRotate:
18 | return SystemRotateAnimator(transitionDuration: transitionDuration)
19 | case .SystemSuckEffect:
20 | return SystemSuckEffectAnimator(transitionDuration: transitionDuration)
21 | case .SystemRippleEffect:
22 | return SystemRippleEffectAnimator(transitionDuration: transitionDuration)
23 | case let .Explode(params):
24 | return ExplodeAnimator(params: params, transitionDuration: transitionDuration)
25 | case let .Fade(direction):
26 | return FadeAnimator(direction: direction, transitionDuration: transitionDuration)
27 | case let .Fold(direction, params):
28 | return FoldAnimator(fromDirection: direction, params: params, transitionDuration: transitionDuration)
29 | case let .Portal(direction, params):
30 | return PortalAnimator(fromDirection: direction, params: params, transitionDuration: transitionDuration)
31 | case let .NatGeo(direction):
32 | return NatGeoAnimator(fromDirection: direction, transitionDuration: transitionDuration)
33 | case let .Turn(direction):
34 | return TurnAnimator(fromDirection: direction, transitionDuration: transitionDuration)
35 | case let .Cards(direction):
36 | return CardsAnimator(fromDirection: direction, transitionDuration: transitionDuration)
37 | case let .Flip(direction):
38 | return FlipAnimator(fromDirection: direction, transitionDuration: transitionDuration)
39 | case let .Slide(direction, params):
40 | return SlideAnimator(fromDirection: direction, params: params, transitionDuration: transitionDuration)
41 | case let .SystemCube(direction):
42 | return SystemCubeAnimator(fromDirection: direction, transitionDuration: transitionDuration)
43 | case let .SystemFlip(direction):
44 | return SystemFlipAnimator(fromDirection: direction, transitionDuration: transitionDuration)
45 | case let .SystemMoveIn(direction):
46 | return SystemMoveInAnimator(fromDirection: direction, transitionDuration: transitionDuration)
47 | case let .SystemPush(direction):
48 | return SystemPushAnimator(fromDirection: direction, transitionDuration: transitionDuration)
49 | case let .SystemReveal(direction):
50 | return SystemRevealAnimator(fromDirection: direction, transitionDuration: transitionDuration)
51 | case let .SystemPage(type):
52 | return SystemPageAnimator(type: type, transitionDuration: transitionDuration)
53 | case let .SystemCameraIris(hollowState):
54 | return SystemCameraIrisAnimator(hollowState: hollowState, transitionDuration: transitionDuration)
55 | }
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/IBAnimatableApp.xcodeproj/xcshareddata/xcschemes/IBAnimatable.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/IBAnimatable/GradientType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 09/02/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import Foundation
7 |
8 | public enum GradientType: String {
9 | case SunnyDays
10 | case GreenBeach
11 | case IntuitivePurple
12 | case EmeraldWater
13 | case LemonTwist
14 | case Horizon
15 | case RoseWater
16 | case Frozen
17 | case MangoPulp
18 | case BloodyMary
19 | case Aubergine
20 | case AquaMarine
21 | case Sunrise
22 | case PurpleParadise
23 | case SeaWeed
24 | case Pinky
25 | case Cherry
26 | case Mojito
27 | case JuicyOrange
28 | case Mirage
29 | case SteelGray
30 | case Kashmir
31 | case ElectricViolet
32 | case VeniceBlue
33 | case BoraBora
34 | case Moss
35 | case ShroomHaze
36 | case Mystic
37 | case MidnightCity
38 | case SeaBlizz
39 | case Opa
40 | case Titanium
41 | case Mantle
42 | case Dracula
43 | case Peach
44 | case Moonrise
45 | case Clouds
46 | case Stellar
47 | case Bourbon
48 | case CalmDarya
49 | case Influenza
50 | case Shrimpy
51 | case Army
52 | case Miaka
53 | case PinotNoir
54 | case DayTripper
55 | case Namn
56 | case BlurryBeach
57 | case Vasily
58 | case ALostMemory
59 | case Petrichor
60 | case Jonquil
61 | case SiriusTamed
62 | case Kyoto
63 | case MistyMeadow
64 | case Aqualicious
65 | case Moor
66 | case Almost
67 | case ForeverLost
68 | case Winter
69 | case Autumn
70 | case Candy
71 | case Reef
72 | case TheStrain
73 | case DirtyFog
74 | case Earthly
75 | case Virgin
76 | case Ash
77 | case ShadowNight
78 | case Cherryblossoms
79 | case Parklife
80 | case DanceToForget
81 | case Starfall
82 | case RedMist
83 | case TealLove
84 | case NeonLife
85 | case ManofSteel
86 | case Amethyst
87 | case CheerUpEmoKid
88 | case Shore
89 | case FacebookMessenger
90 | case SoundCloud
91 | case Behongo
92 | case ServQuick
93 | case Friday
94 | case Martini
95 | case MetallicToad
96 | case BetweenTheClouds
97 | case CrazyOrangeI
98 | case Hersheys
99 | case TalkingToMiceElf
100 | case PurpleBliss
101 | case Predawn
102 | case EndlessRiver
103 | case PastelOrangeattheSun
104 | case Twitch
105 | case Instagram
106 | case Flickr
107 | case Vine
108 | case Turquoiseflow
109 | case Portrait
110 | case VirginAmerica
111 | case KokoCaramel
112 | case FreshTurboscent
113 | case Greentodark
114 | case Ukraine
115 | case Curiosityblue
116 | case DarkKnight
117 | case Piglet
118 | case Lizard
119 | case SagePersuasion
120 | case BetweenNightandDay
121 | case Timber
122 | case Passion
123 | case ClearSky
124 | case MasterCard
125 | case BackToEarth
126 | case DeepPurple
127 | case LittleLeaf
128 | case Netflix
129 | case LightOrange
130 | case GreenandBlue
131 | case Poncho
132 | case BacktotheFuture
133 | case Blush
134 | case Inbox
135 | case Purplin
136 | case PaleWood
137 | case Haikus
138 | case Pizelex
139 | case Joomla
140 | case Christmas
141 | case MinnesotaVikings
142 | case MiamiDolphins
143 | case Forest
144 | case Nighthawk
145 | case Superman
146 | case Suzy
147 | case DarkSkies
148 | }
149 |
--------------------------------------------------------------------------------
/IBAnimatable/SideImageDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/8/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol SideImageDesignable {
9 | /**
10 | * The left image
11 | */
12 | var leftImage: UIImage? { get set }
13 |
14 | /**
15 | * Left padding of the left image, default value is CGFloat.NaN
16 | */
17 | var leftImageLeftPadding: CGFloat { get set }
18 |
19 | /**
20 | * Right padding of the left image, default value is CGFloat.NaN
21 | */
22 | var leftImageRightPadding: CGFloat { get set }
23 |
24 | /**
25 | * Top padding of the left image, default value is CGFloat.NaN
26 | */
27 | var leftImageTopPadding: CGFloat { get set }
28 |
29 | /**
30 | * The right image
31 | */
32 | var rightImage: UIImage? { get set }
33 |
34 | /**
35 | * Left padding of the right image, default value is CGFloat.NaN
36 | */
37 | var rightImageLeftPadding: CGFloat { get set }
38 |
39 | /**
40 | * Right padding of the right image, default value is CGFloat.NaN
41 | */
42 | var rightImageRightPadding: CGFloat { get set }
43 |
44 | /**
45 | * Top padding of the right image, default value is CGFloat.NaN
46 | */
47 | var rightImageTopPadding: CGFloat { get set }
48 | }
49 |
50 | public extension SideImageDesignable where Self: UITextField {
51 |
52 | public func configImages() {
53 | configLeftImage()
54 | configRightImage()
55 | }
56 |
57 | private func configLeftImage() {
58 | guard let wrappedLeftImage = leftImage else {
59 | return
60 | }
61 |
62 | let sideView = generateSideViewWithImage(wrappedLeftImage, leftPadding: leftImageLeftPadding, rightPadding: leftImageRightPadding, topPadding: leftImageTopPadding)
63 | leftViewMode = .Always
64 | leftView = sideView
65 | }
66 |
67 | private func configRightImage() {
68 | guard let wrappedRightImage = rightImage else {
69 | return
70 | }
71 |
72 | let sideView = generateSideViewWithImage(wrappedRightImage, leftPadding: rightImageLeftPadding, rightPadding: rightImageRightPadding, topPadding: rightImageTopPadding)
73 | rightViewMode = .Always
74 | rightView = sideView
75 | }
76 |
77 | private func generateSideViewWithImage(image: UIImage, leftPadding: CGFloat, rightPadding: CGFloat, topPadding: CGFloat) -> UIView {
78 | let imageView = UIImageView(image: image)
79 |
80 | // If not set, use 0 as default value
81 | var leftPaddingValue: CGFloat = 0.0
82 | if !leftPadding.isNaN {
83 | leftPaddingValue = leftPadding
84 | }
85 |
86 | // If not set, use 0 as default value
87 | var rightPaddingValue: CGFloat = 0.0
88 | if !rightPadding.isNaN {
89 | rightPaddingValue = rightPadding
90 | }
91 |
92 | // If does not specify `topPadding`, then center it in the middle
93 | if topPadding.isNaN {
94 | imageView.frame.origin = CGPoint(x: leftPaddingValue, y: (bounds.height - imageView.bounds.height) / 2)
95 | } else {
96 | imageView.frame.origin = CGPoint(x: leftPaddingValue, y: topPadding)
97 | }
98 |
99 | let padding = rightPaddingValue + imageView.bounds.size.width + leftPaddingValue
100 | let sideView = UIView(frame: CGRect(x: 0, y: 0, width: padding, height: bounds.height))
101 | sideView.addSubview(imageView)
102 | return sideView
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/IBAnimatable/InteractiveAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 4/5/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | // Super abstract class for all interactive animator subclasses
9 | public class InteractiveAnimator: UIPercentDrivenInteractiveTransition {
10 | internal(set) public var interacting = false
11 |
12 | // transitionType: Used to deteminate pop or dismiss
13 | let transitionType: TransitionType
14 | // interactiveGestureType: Used to deteminate gesture type (direction)
15 | let interactiveGestureType: InteractiveGestureType
16 | // viewController: the viewController will connect to the gestureRecognizer
17 | weak var viewController: UIViewController?
18 | // gestureRecognizer: the gesture recognizer to handle gesture
19 | var gestureRecognizer: UIGestureRecognizer?
20 |
21 | init(interactiveGestureType: InteractiveGestureType, transitionType: TransitionType) {
22 | self.interactiveGestureType = interactiveGestureType
23 | self.transitionType = transitionType
24 | super.init()
25 | }
26 |
27 | deinit {
28 | if let gestureRecognizer = gestureRecognizer, view = viewController?.view {
29 | gestureRecognizer.removeTarget(self, action: #selector(handleGesture(_:)))
30 | view.removeGestureRecognizer(gestureRecognizer)
31 | }
32 | }
33 |
34 | func connectGestureRecognizer(viewController: UIViewController) {
35 | self.viewController = viewController
36 | let gestureRecognizerType = createGestureRecognizer()
37 | gestureRecognizer = gestureRecognizerType
38 | if let gestureRecognizer = gestureRecognizer {
39 | self.viewController?.view.addGestureRecognizer(gestureRecognizer)
40 | }
41 | }
42 |
43 | func handleGesture(gestureRecognizer: UIGestureRecognizer) {
44 | let (progress, shouldFinishInteractiveTransition) = calculateProgress(gestureRecognizer)
45 |
46 | switch gestureRecognizer.state {
47 | case .Began:
48 | guard shouldBeginProgress(gestureRecognizer) else {
49 | return
50 | }
51 |
52 | interacting = true
53 | switch transitionType {
54 | case .NavigationTransition(.Pop):
55 | viewController?.navigationController?.popViewControllerAnimated(true)
56 | case .PresentationTransition(.Dismissal):
57 | viewController?.dismissViewControllerAnimated(true, completion: nil)
58 | default:
59 | break
60 | }
61 | case .Changed:
62 | updateInteractiveTransition(progress)
63 | case .Cancelled, .Ended:
64 | interacting = false
65 | if shouldFinishInteractiveTransition {
66 | finishInteractiveTransition()
67 | } else {
68 | cancelInteractiveTransition()
69 | }
70 | default:
71 | // Something happened then cancel the transition.
72 | interacting = false
73 | cancelInteractiveTransition()
74 | break
75 | }
76 | }
77 |
78 | // Because Swift doesn't support pure virtual method, need to throw error
79 | func createGestureRecognizer() -> UIGestureRecognizer {
80 | preconditionFailure("This method must be overridden")
81 | }
82 |
83 | func shouldBeginProgress(gestureRecognizer: UIGestureRecognizer) -> Bool {
84 | // return true by default
85 | return true
86 | }
87 |
88 | func calculateProgress(gestureRecognizer: UIGestureRecognizer) -> (progress: CGFloat, shouldFinishInteractiveTransition: Bool) {
89 | preconditionFailure("This method must be overridden")
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/IBAnimatable/AnimatableButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 11/18/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | @IBDesignable public class AnimatableButton: UIButton, CornerDesignable, FillDesignable, BorderDesignable, ShadowDesignable, MaskDesignable, Animatable {
9 |
10 | // MARK: - CornerDesignable
11 | @IBInspectable public var cornerRadius: CGFloat = CGFloat.NaN {
12 | didSet {
13 | configCornerRadius()
14 | }
15 | }
16 |
17 | // MARK: - FillDesignable
18 | @IBInspectable public var fillColor: UIColor? {
19 | didSet {
20 | configFillColor()
21 | }
22 | }
23 |
24 | @IBInspectable public var predefinedColor: String? {
25 | didSet {
26 | configFillColor()
27 | }
28 | }
29 |
30 | @IBInspectable public var opacity: CGFloat = CGFloat.NaN {
31 | didSet {
32 | configOpacity()
33 | }
34 | }
35 |
36 | // MARK: - BorderDesignable
37 | @IBInspectable public var borderColor: UIColor? {
38 | didSet {
39 | configBorder()
40 | }
41 | }
42 |
43 | @IBInspectable public var borderWidth: CGFloat = CGFloat.NaN {
44 | didSet {
45 | configBorder()
46 | }
47 | }
48 |
49 | @IBInspectable public var borderSide: String? {
50 | didSet {
51 | configBorder()
52 | }
53 | }
54 |
55 | // MARK: - ShadowDesignable
56 | @IBInspectable public var shadowColor: UIColor? {
57 | didSet {
58 | configShadowColor()
59 | }
60 | }
61 |
62 | @IBInspectable public var shadowRadius: CGFloat = CGFloat.NaN {
63 | didSet {
64 | configShadowRadius()
65 | }
66 | }
67 |
68 | @IBInspectable public var shadowOpacity: CGFloat = CGFloat.NaN {
69 | didSet {
70 | configShadowOpacity()
71 | }
72 | }
73 |
74 | @IBInspectable public var shadowOffset: CGPoint = CGPoint(x: CGFloat.NaN, y: CGFloat.NaN) {
75 | didSet {
76 | configShadowOffset()
77 | }
78 | }
79 |
80 | // MARK: - MaskDesignable
81 | @IBInspectable public var maskType: String? {
82 | didSet {
83 | configMask()
84 | configBorder()
85 | }
86 | }
87 |
88 | // MARK: - Animatable
89 | @IBInspectable public var animationType: String?
90 | @IBInspectable public var autoRun: Bool = true
91 | @IBInspectable public var duration: Double = Double.NaN
92 | @IBInspectable public var delay: Double = Double.NaN
93 | @IBInspectable public var damping: CGFloat = CGFloat.NaN
94 | @IBInspectable public var velocity: CGFloat = CGFloat.NaN
95 | @IBInspectable public var force: CGFloat = CGFloat.NaN
96 | @IBInspectable public var repeatCount: Float = Float.NaN
97 | @IBInspectable public var x: CGFloat = CGFloat.NaN
98 | @IBInspectable public var y: CGFloat = CGFloat.NaN
99 |
100 | // MARK: - Lifecycle
101 | public override func prepareForInterfaceBuilder() {
102 | super.prepareForInterfaceBuilder()
103 | configInspectableProperties()
104 | }
105 |
106 | public override func awakeFromNib() {
107 | super.awakeFromNib()
108 | configInspectableProperties()
109 | }
110 |
111 | public override func layoutSubviews() {
112 | super.layoutSubviews()
113 | configAfterLayoutSubviews()
114 | autoRunAnimation()
115 | }
116 |
117 | // MARK: - Private
118 | private func configInspectableProperties() {
119 | configAnimatableProperties()
120 | }
121 |
122 | private func configAfterLayoutSubviews() {
123 | configMask()
124 | configBorder()
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/IBAnimatableApp/Animations.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/IBAnimatable/Presenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 2/24/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | /**
9 | Presenter for `UIViewController` to support custom transition animation for Present and Dismiss
10 | */
11 | public class Presenter: NSObject {
12 | private var transitionAnimationType: TransitionAnimationType
13 | var transitionDuration: Duration {
14 | didSet {
15 | if oldValue != transitionDuration {
16 | updateTransitionDuration()
17 | }
18 | }
19 | }
20 |
21 | var interactiveGestureType: InteractiveGestureType? {
22 | // Update `interactiveAnimator` if needed
23 | didSet {
24 | if oldValue?.stringValue != interactiveGestureType?.stringValue {
25 | updateInteractiveAnimator()
26 | }
27 | }
28 | }
29 |
30 | // animation controller
31 | private var animator: AnimatedTransitioning?
32 |
33 | // interaction controller
34 | private var interactiveAnimator: InteractiveAnimator?
35 |
36 | public init(transitionAnimationType: TransitionAnimationType, transitionDuration: Duration = defaultTransitionDuration, interactiveGestureType: InteractiveGestureType? = nil) {
37 | self.transitionAnimationType = transitionAnimationType
38 | self.transitionDuration = transitionDuration
39 | super.init()
40 |
41 | updateTransitionDuration()
42 |
43 | animator = AnimatorFactory.generateAnimator(transitionAnimationType, transitionDuration: transitionDuration)
44 |
45 | self.interactiveGestureType = interactiveGestureType
46 | updateInteractiveAnimator()
47 | }
48 |
49 | // MARK: - Private
50 | private func updateTransitionDuration() {
51 | if transitionDuration.isNaN {
52 | transitionDuration = defaultTransitionDuration
53 | }
54 | }
55 |
56 | private func updateInteractiveAnimator() {
57 | // If interactiveGestureType has been set
58 | if let interactiveGestureType = interactiveGestureType {
59 | // If configured as `.Default` then use the default interactive gesture type from the Animator
60 | switch interactiveGestureType {
61 | case .Default:
62 | if let interactiveGestureType = animator?.interactiveGestureType {
63 | interactiveAnimator = InteractiveAnimatorFactory.generateInteractiveAnimator(interactiveGestureType, transitionType: .PresentationTransition(.Dismissal))
64 | }
65 | default:
66 | interactiveAnimator = InteractiveAnimatorFactory.generateInteractiveAnimator(interactiveGestureType, transitionType: .PresentationTransition(.Dismissal))
67 | }
68 | } else {
69 | interactiveAnimator = nil
70 | }
71 | }
72 | }
73 |
74 | extension Presenter: UIViewControllerTransitioningDelegate {
75 | // MARK: - animation controller
76 | public func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
77 | animator?.transitionDuration = transitionDuration
78 | interactiveAnimator?.connectGestureRecognizer(presented)
79 | return animator
80 | }
81 |
82 | public func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
83 | // Use the reverse animation
84 | if let reverseTransitionAnimationType = animator?.reverseAnimationType {
85 | return AnimatorFactory.generateAnimator(reverseTransitionAnimationType, transitionDuration: transitionDuration)
86 | }
87 | return nil
88 | }
89 |
90 | // MARK: - interaction controller
91 | public func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
92 | if let interactiveAnimator = interactiveAnimator where interactiveAnimator.interacting {
93 | return interactiveAnimator
94 | } else {
95 | return nil
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/IBAnimatableApp/UserInterface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/swift,appcode,xcode,osx
3 |
4 | ### Swift ###
5 | # Xcode
6 | #
7 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
8 |
9 | ## Build generated
10 | build/
11 | DerivedData
12 |
13 | ## Various settings
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata
23 |
24 | ## Other
25 | *.xccheckout
26 | *.moved-aside
27 | *.xcuserstate
28 | *.xcscmblueprint
29 |
30 | ## Obj-C/Swift specific
31 | *.hmap
32 | *.ipa
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 |
53 | Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/screenshots
64 |
65 |
66 | ### AppCode ###
67 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
68 |
69 | *.iml
70 |
71 | ### Temporary files
72 | *.orig
73 |
74 | ## Directory-based project format:
75 | .idea/
76 | # if you remove the above rule, at least ignore the following:
77 |
78 | # User-specific stuff:
79 | # .idea/workspace.xml
80 | # .idea/tasks.xml
81 | # .idea/dictionaries
82 | # .idea/shelf
83 |
84 | # Sensitive or high-churn files:
85 | # .idea/dataSources.ids
86 | # .idea/dataSources.xml
87 | # .idea/sqlDataSources.xml
88 | # .idea/dynamic.xml
89 | # .idea/uiDesigner.xml
90 |
91 | # Gradle:
92 | # .idea/gradle.xml
93 | # .idea/libraries
94 |
95 | # Mongo Explorer plugin:
96 | # .idea/mongoSettings.xml
97 |
98 | ## File-based project format:
99 | *.ipr
100 | *.iws
101 |
102 | ## Plugin-specific files:
103 |
104 | # IntelliJ
105 | /out/
106 |
107 | # mpeltonen/sbt-idea plugin
108 | .idea_modules/
109 |
110 | # JIRA plugin
111 | atlassian-ide-plugin.xml
112 |
113 | # Crashlytics plugin (for Android Studio and IntelliJ)
114 | com_crashlytics_export_strings.xml
115 | crashlytics.properties
116 | crashlytics-build.properties
117 | fabric.properties
118 |
119 |
120 | ### Xcode ###
121 | # Xcode
122 | #
123 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
124 |
125 | ## Build generated
126 | build/
127 | DerivedData
128 |
129 | ## Various settings
130 | *.pbxuser
131 | !default.pbxuser
132 | *.mode1v3
133 | !default.mode1v3
134 | *.mode2v3
135 | !default.mode2v3
136 | *.perspectivev3
137 | !default.perspectivev3
138 | xcuserdata
139 |
140 | ## Other
141 | *.xccheckout
142 | *.moved-aside
143 | *.xcuserstate
144 |
145 |
146 | ### OSX ###
147 | .DS_Store
148 | .AppleDouble
149 | .LSOverride
150 |
151 | # Icon must end with two \r
152 | Icon
153 |
154 | # Thumbnails
155 | ._*
156 |
157 | # Files that might appear in the root of a volume
158 | .DocumentRevisions-V100
159 | .fseventsd
160 | .Spotlight-V100
161 | .TemporaryItems
162 | .Trashes
163 | .VolumeIcon.icns
164 |
165 | # Directories potentially created on remote AFP share
166 | .AppleDB
167 | .AppleDesktop
168 | Network Trash Folder
169 | Temporary Items
170 | .apdisk
171 |
172 |
--------------------------------------------------------------------------------
/IBAnimatable/FillDesignable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jake Lin on 12/5/15.
3 | // Copyright © 2015 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public protocol FillDesignable {
9 | var fillColor: UIColor? { get set }
10 | var predefinedColor: String? { get set }
11 | var opacity: CGFloat { get set }
12 | }
13 |
14 | public extension FillDesignable where Self: UIView {
15 | public func configFillColor() {
16 | if let unwrappedFillColor = fillColor {
17 | backgroundColor = unwrappedFillColor
18 | } else if let unwrappedPredefinedColor = predefinedColorFromString(predefinedColor) {
19 | backgroundColor = unwrappedPredefinedColor
20 | }
21 | }
22 |
23 | public func configOpacity() {
24 | if !opacity.isNaN && opacity >= 0 && opacity <= 1 {
25 | alpha = opacity
26 |
27 | // Make better performance
28 | if opacity == 1 {
29 | opaque = true
30 | }
31 | }
32 | }
33 | }
34 |
35 | public extension FillDesignable where Self: UITableViewCell {
36 | public func configFillColor() {
37 | if let unwrappedFillColor = fillColor {
38 | backgroundColor = unwrappedFillColor
39 | contentView.backgroundColor = unwrappedFillColor
40 | } else if let unwrappedPredefinedColor = predefinedColorFromString(predefinedColor) {
41 | backgroundColor = unwrappedPredefinedColor
42 | contentView.backgroundColor = unwrappedPredefinedColor
43 | }
44 | }
45 | }
46 |
47 | private extension FillDesignable {
48 |
49 | func predefinedColorFromString(predefinedColor: String?) -> UIColor? {
50 | guard let unwrappedColorTypeString = predefinedColor, colorType = ColorType(rawValue: unwrappedColorTypeString) else {
51 | return nil
52 | }
53 |
54 | switch colorType {
55 | case .FlatEmerland:
56 | return UIColor(red: 46 / 255, green: 204 / 255, blue: 113 / 255, alpha: 1.0)
57 | case .FlatPomegranate:
58 | return UIColor(red: 192 / 255, green: 57 / 255, blue: 43 / 255, alpha: 1.0)
59 | case .FlatWetAsphalt:
60 | return UIColor(red: 52 / 255, green: 73 / 255, blue: 94 / 255, alpha: 1.0)
61 | case .FlatTurquoise:
62 | return UIColor(red: 26 / 255, green: 188 / 255, blue: 156 / 255, alpha: 1.0)
63 | case .FlatConcrete:
64 | return UIColor(red: 149 / 255, green: 165 / 255, blue: 166 / 255, alpha: 1.0)
65 | case .FlatOrange:
66 | return UIColor(red: 243 / 255, green: 156 / 255, blue: 18 / 255, alpha: 1.0)
67 | case .FlatAsbestos:
68 | return UIColor(red: 127 / 255, green: 140 / 255, blue: 141 / 255, alpha: 1.0)
69 | case .FlatPeterRiver:
70 | return UIColor(red: 52 / 255, green: 152 / 255, blue: 219 / 255, alpha: 1.0)
71 | case .FlatSilver:
72 | return UIColor(red: 189 / 255, green: 195 / 255, blue: 199 / 255, alpha: 1.0)
73 | case .FlatSunFlower:
74 | return UIColor(red: 241 / 255, green: 196 / 255, blue: 15 / 255, alpha: 1.0)
75 | case .FlatAmethyst:
76 | return UIColor(red: 155 / 255, green: 89 / 255, blue: 182 / 255, alpha: 1.0)
77 | case .FlatAlizarin:
78 | return UIColor(red: 231 / 255, green: 76 / 255, blue: 60 / 255, alpha: 1.0)
79 | case .FlatGreenSea:
80 | return UIColor(red: 22 / 255, green: 160 / 255, blue: 133 / 255, alpha: 1.0)
81 | case .FlatBelizeHole:
82 | return UIColor(red: 41 / 255, green: 128 / 255, blue: 185 / 255, alpha: 1.0)
83 | case .FlatNephritis:
84 | return UIColor(red: 39 / 255, green: 174 / 255, blue: 96 / 255, alpha: 1.0)
85 | case .FlatMidnightBlue:
86 | return UIColor(red: 44 / 255, green: 62 / 255, blue: 80 / 255, alpha: 1.0)
87 | case .FlatClouds:
88 | return UIColor(red: 236 / 255, green: 240 / 255, blue: 241 / 255, alpha: 1.0)
89 | case .FlatWisteria:
90 | return UIColor(red: 142 / 255, green: 68 / 255, blue: 173 / 255, alpha: 1.0)
91 | case .FlatCarrot:
92 | return UIColor(red: 230 / 255, green: 126 / 255, blue: 34 / 255, alpha: 1.0)
93 | case .FlatPumpkin:
94 | return UIColor(red: 211 / 255, green: 84 / 255, blue: 0 / 255, alpha: 1.0)
95 | }
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/IBAnimatable/SlideAnimator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Tom Baranes on 08/05/16.
3 | // Copyright © 2016 Jake Lin. All rights reserved.
4 | //
5 |
6 | import UIKit
7 |
8 | public class SlideAnimator: NSObject, AnimatedTransitioning {
9 | // MARK: - AnimatorProtocol
10 | public var transitionAnimationType: TransitionAnimationType
11 | public var transitionDuration: Duration = defaultTransitionDuration
12 | public var reverseAnimationType: TransitionAnimationType?
13 | public var interactiveGestureType: InteractiveGestureType?
14 |
15 | // MARK: - private
16 | private var fromDirection: TransitionDirection
17 | private var horizontal = false
18 | private var reverse = false
19 | private var fade = false
20 |
21 | public init(fromDirection: TransitionDirection, params: [String], transitionDuration: Duration) {
22 | self.fromDirection = fromDirection
23 | self.transitionDuration = transitionDuration
24 | fade = params.contains("fade")
25 | horizontal = fromDirection.isHorizontal
26 |
27 | switch fromDirection {
28 | case .Right:
29 | self.transitionAnimationType = .Slide(toDirection: .Right, params: params)
30 | self.reverseAnimationType = .Slide(toDirection: .Left, params: params)
31 | self.interactiveGestureType = .Pan(fromDirection: .Right)
32 | reverse = true
33 | case .Top:
34 | self.transitionAnimationType = .Slide(toDirection: .Top, params: params)
35 | self.reverseAnimationType = .Slide(toDirection: .Bottom, params: params)
36 | self.interactiveGestureType = .Pan(fromDirection: .Top)
37 | reverse = false
38 | case .Bottom:
39 | self.transitionAnimationType = .Slide(toDirection: .Bottom, params: params)
40 | self.reverseAnimationType = .Slide(toDirection: .Top, params: params)
41 | self.interactiveGestureType = .Pan(fromDirection: .Bottom)
42 | reverse = true
43 | default:
44 | self.transitionAnimationType = .Slide(toDirection: .Left, params: params)
45 | self.reverseAnimationType = .Slide(toDirection: .Right, params: params)
46 | self.interactiveGestureType = .Pan(fromDirection: .Left)
47 | reverse = false
48 | }
49 | super.init()
50 | }
51 | }
52 |
53 | extension SlideAnimator: UIViewControllerAnimatedTransitioning {
54 | public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
55 | return retrieveTransitionDuration(transitionContext)
56 | }
57 |
58 | public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
59 | let (tempfromView, tempToView, tempContainerView) = retrieveViews(transitionContext)
60 | guard let fromView = tempfromView, toView = tempToView, containerView = tempContainerView else {
61 | transitionContext.completeTransition(true)
62 | return
63 | }
64 |
65 |
66 | let travelDistance = horizontal ? containerView.bounds.width : containerView.bounds.height
67 | let travel = CGAffineTransformMakeTranslation(horizontal ? (reverse ? travelDistance : -travelDistance) : 0, horizontal ? 0 : (reverse ? travelDistance : -travelDistance))
68 | containerView.addSubview(toView)
69 | if fade {
70 | toView.alpha = 0
71 | }
72 | toView.transform = CGAffineTransformInvert(travel)
73 | animateSlideTransition(toView: toView, fromView: fromView, travel: travel) {
74 | fromView.transform = CGAffineTransformIdentity
75 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
76 | }
77 | }
78 |
79 | }
80 |
81 | // MARK: - Animation
82 |
83 | private extension SlideAnimator {
84 |
85 | func animateSlideTransition(toView toView: UIView, fromView: UIView, travel: CGAffineTransform, completion: AnimatableCompletion) {
86 | UIView.animateWithDuration(transitionDuration, animations: {
87 | fromView.transform = travel
88 | toView.transform = CGAffineTransformIdentity
89 | if self.fade {
90 | fromView.alpha = 0
91 | toView.alpha = 1
92 | }
93 | },
94 | completion: { _ in
95 | completion()
96 | })
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------