├── XWTransitionDemo
├── p1.JPG
├── p2.JPG
├── zrx1.jpg
├── zrx2.jpg
├── zrx3.jpg
├── zrx4.jpg
├── zrx5.jpg
├── zrx6.jpg
├── zrx7.jpg
├── zrx8.jpg
├── zrx9.jpg
├── PageFlipTransiton
│ ├── XWCoolTypeListController.h
│ ├── XWCoolToController.h
│ ├── XWCoolFromController.h
│ ├── XWCoolTypeListController.m
│ ├── XWCoolToController.m
│ └── XWCoolFromController.m
├── XWTransitionTypeListController.h
├── MagicMoveTransiton
│ ├── XWMagicMoveFromTwoController.h
│ ├── XWMagicMoveListController.h
│ ├── XWMagicMoveToController.h
│ ├── XWMagicMoveFromController.h
│ ├── XWMagicMoveToImageController.h
│ ├── XWMagicMoveToController.m
│ ├── XWMagicMoveListController.m
│ ├── XWMagicMoveFromController.m
│ ├── XWMagicMoveFromTwoController.m
│ └── XWMagicMoveToImageController.m
├── DrawerTransition
│ ├── XWDrawerTypeListController.h
│ ├── XWDrawerToController.h
│ ├── XWDrawerFromController.h
│ ├── XWDrawerTypeListController.m
│ ├── XWDrawerToController.m
│ └── XWDrawerFromController.m
├── CircleSpreadTransition
│ ├── XWCircleSpreadToController.h
│ ├── XWCircleSpreadFromController.h
│ ├── XWCircleSpreadToController.m
│ └── XWCircleSpreadFromController.m
├── AppDelegate.h
├── FilterTransition
│ ├── XWFilterListControllerController.h
│ ├── XWFilterToController.h
│ ├── XWFilterFromController.h
│ ├── XWFilterListControllerController.m
│ ├── XWFilterToController.m
│ └── XWFilterFromController.m
├── main.m
├── AppDelegate.m
├── XWBasicToController.h
├── XWBasicFromController.h
├── XWBasicListController.h
├── XWTransitionTypeListController.m
├── XWBasicFromController.m
├── XWBasicToController.m
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
└── XWBasicListController.m
├── XWTransition
├── Resoures
│ ├── line.png
│ ├── mask.jpg
│ └── restrictedshine.tiff
├── Category
│ ├── UIView+Snapshot.h
│ ├── UINavigationController+XWTransition.h
│ ├── UIView+Snapshot.m
│ ├── UIViewController+XWTransition.h
│ ├── UIViewController+XWTransition.m
│ └── UINavigationController+XWTransition.m
├── XWFilterAnimator
│ ├── XWFilterAnimator+XWMask.h
│ ├── XWFilterAnimator+XWFlash.h
│ ├── XWFilterAnimator+XWBoxBlur.h
│ ├── XWFilterAnimator+XWRipple.h
│ ├── XWFilterAnimator+XWMod.h
│ ├── XWFilterAnimator+XWSwipe.h
│ ├── XWFilterAnimator+XWPageCurl.h
│ ├── XWFilterAnimator+XWBarSwipe.h
│ ├── XWFilterAnimator+XWCopyMachine.h
│ ├── XWFilterTransitionView.h
│ ├── XWFilterAnimator+XWBoxBlur.m
│ ├── XWFilterAnimator+XWBarSwipe.m
│ ├── XWFilterAnimator+XWPageCurl.m
│ ├── XWFilterAnimator+XWRipple.m
│ ├── XWFilterAnimator+XWSwipe.m
│ ├── XWFilterAnimator+XWFlash.m
│ ├── XWFilterAnimator+XWCopyMachine.m
│ ├── XWFilterAnimator+XWMod.m
│ ├── XWFilterAnimator+XWMask.m
│ ├── XWFilterAnimator.h
│ ├── XWFilterTransitionView.m
│ └── XWFilterAnimator.m
├── XWCoolAnimator
│ ├── XWCoolAnimator+XWExplode.h
│ ├── XWCoolAnimator+XWPageFlip.h
│ ├── XWCoolAnimator+XWPortal.h
│ ├── XWCoolAnimator+XWFold.h
│ ├── XWCoolAnimator+XWLines.h
│ ├── XWCoolAnimator+XWScanning.h
│ ├── XWCoolAnimator+XWMiddlePageFlip.h
│ ├── XWCoolAnimator.h
│ ├── XWCoolAnimator+XWExplode.m
│ ├── XWCoolAnimator+XWScanning.m
│ ├── XWCoolAnimator+XWPageFlip.m
│ ├── XWCoolAnimator+XWLines.m
│ ├── XWCoolAnimator+XWPortal.m
│ ├── XWCoolAnimator.m
│ ├── XWCoolAnimator+XWFold.m
│ └── XWCoolAnimator+XWMiddlePageFlip.m
├── XWCircleSpreadAnimator
│ ├── XWCircleSpreadAnimator.h
│ └── XWCircleSpreadAnimator.m
├── XWMagicMoveAnimator
│ ├── XWMagicMoveAnimator.h
│ └── XWMagicMoveAnimator.m
├── Main
│ ├── XWTransitionAnimator.h
│ ├── XWInteractiveTransition.h
│ ├── XWTransitionAnimator.m
│ └── XWInteractiveTransition.m
└── XWDrawerAnimator
│ └── XWDrawerAnimator.h
├── XWTransitionDemo.xcodeproj
└── project.xcworkspace
│ └── contents.xcworkspacedata
├── .gitignore
├── README.md
└── LICENSE.md
/XWTransitionDemo/p1.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/p1.JPG
--------------------------------------------------------------------------------
/XWTransitionDemo/p2.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/p2.JPG
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx1.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx2.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx3.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx4.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx5.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx6.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx7.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx8.jpg
--------------------------------------------------------------------------------
/XWTransitionDemo/zrx9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransitionDemo/zrx9.jpg
--------------------------------------------------------------------------------
/XWTransition/Resoures/line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransition/Resoures/line.png
--------------------------------------------------------------------------------
/XWTransition/Resoures/mask.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransition/Resoures/mask.jpg
--------------------------------------------------------------------------------
/XWTransition/Resoures/restrictedshine.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wazrx/XWTransition/HEAD/XWTransition/Resoures/restrictedshine.tiff
--------------------------------------------------------------------------------
/XWTransitionDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/XWTransitionDemo/PageFlipTransiton/XWCoolTypeListController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolTypeListController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicListController.h"
10 |
11 | @interface XWCoolTypeListController : XWBasicListController
12 | @end
13 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWTransitionTypeListController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/9.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicListController.h"
10 |
11 | @interface XWTransitionTypeListController : XWBasicListController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveFromTwoController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveToTwoController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface XWMagicMoveFromTwoController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransitionDemo/DrawerTransition/XWDrawerTypeListController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerTypeListController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicListController.h"
10 |
11 | @interface XWDrawerTypeListController : XWBasicListController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveListController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveListController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicListController.h"
10 |
11 | @interface XWMagicMoveListController : XWBasicListController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | .DS_Store
3 | .svn
4 | */build/*
5 | *.pbxuser
6 | !default.pbxuser
7 | *.mode1v3
8 | !default.mode1v3
9 | *.mode2v3
10 | !default.mode2v3
11 | *.perspectivev3
12 | !default.perspectivev3
13 | #*.xcworkspace
14 | xcuserdata
15 | *.moved-aside
16 | DerivedData
17 | .idea/
18 | *.hmap
19 | *.xccheckout
20 |
21 | #CocoaPods
22 | #Pods
23 |
24 |
25 |
--------------------------------------------------------------------------------
/XWTransitionDemo/CircleSpreadTransition/XWCircleSpreadToController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCircleSpreadToController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicToController.h"
10 |
11 | @interface XWCircleSpreadToController : XWBasicToController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransitionDemo/CircleSpreadTransition/XWCircleSpreadFromController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCircleSpreadController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicFromController.h"
10 |
11 | @interface XWCircleSpreadFromController : XWBasicFromController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransitionDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/9.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/XWTransitionDemo/FilterTransition/XWFilterListControllerController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterListControllerViewController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicListController.h"
10 |
11 | @interface XWFilterListControllerController : XWBasicListController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransitionDemo/FilterTransition/XWFilterToController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterToController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicToController.h"
10 |
11 | @interface XWFilterToController : XWBasicToController
12 | @property (nonatomic, assign) NSUInteger type;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransitionDemo/PageFlipTransiton/XWCoolToController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWPageFlipToController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicToController.h"
10 |
11 | @interface XWCoolToController : XWBasicToController
12 | @property (nonatomic, assign) NSUInteger type;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransitionDemo/DrawerTransition/XWDrawerToController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerToController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicToController.h"
10 |
11 | @interface XWDrawerToController : XWBasicToController
12 |
13 | @property (nonatomic, assign) NSInteger type;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/XWTransitionDemo/FilterTransition/XWFilterFromController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterFromController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicFromController.h"
10 |
11 | @interface XWFilterFromController : XWBasicFromController
12 | @property (nonatomic, assign) NSUInteger type;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveToController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveToController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicToController.h"
10 |
11 | @interface XWMagicMoveToController : XWBasicToController
12 |
13 | - (void)xw_setImage:(UIImage *)img;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/XWTransitionDemo/PageFlipTransiton/XWCoolFromController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWPageFlipFromController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicFromController.h"
10 |
11 | @interface XWCoolFromController : XWBasicFromController
12 | @property (nonatomic, assign) NSUInteger type;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/Category/UIView+Snapshot.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Snapshot.h
3 | // XWTransitionDemo
4 | //
5 | // Created by 肖文 on 2016/12/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIView (Snapshot)
12 |
13 | @property (nonatomic, readonly) UIImage *snapshotImage;
14 | @property (nonatomic, strong) UIImage *contentImage;
15 |
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/XWTransitionDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/9.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/XWTransitionDemo/DrawerTransition/XWDrawerFromController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerFromController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicFromController.h"
10 |
11 | @interface XWDrawerFromController : XWBasicFromController
12 |
13 | @property (nonatomic, assign) NSInteger type;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveFromController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveFromController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicFromController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface XWMagicMoveFromController : XWBasicFromController
14 |
15 | - (void)xw_setImage:(UIImage *)img;
16 |
17 | @end
18 |
19 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransitionDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/9.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | return YES;
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveToImageController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveToImageController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface XWMagicMoveToImageController : UIViewController
12 |
13 | @property (nonatomic, assign) NSUInteger idx;
14 |
15 | @property (nonatomic, copy) void(^dismissConfig)(NSInteger currentIndex);
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWMask.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWMask.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWMask)
12 |
13 | - (void)xw_maskAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration;
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWBasicToController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWBasicToController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "UINavigationController+XWTransition.h"
11 | #import "UIViewController+XWTransition.h"
12 |
13 | @interface XWBasicToController : UIViewController
14 | @property (nonatomic, weak, readonly) UIButton *button;
15 |
16 | - (void)xw_transiton;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWFlash.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWFlash.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWFlash)
12 |
13 | - (void)xw_flashAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration;
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWBoxBlur.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWBoxBlur.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWBoxBlur)
12 | - (void)xw_boxBlurAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration;
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWRipple.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWRipple.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWRipple)
12 |
13 | - (void)xw_rippleAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration;
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWMod.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWMod.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWMod)
12 |
13 | - (void)xw_modAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag;
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWExplode.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWExplode.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/14.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | @interface XWCoolAnimator (XWExplode)
12 |
13 | - (void)xw_setExplodeToAnimation:(id)transitionContext;
14 |
15 | - (void)xw_setExplodeBackAnimation:(id)transitionContext;
16 | @end
17 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWPageFlip.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWPageFlip.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | @interface XWCoolAnimator (XWPageFlip)
12 | - (void)xw_setPageFlipToAnimation:(id)transitionContext;
13 |
14 | - (void)xw_setPageFlipBackAnimation:(id)transitionContext;
15 | @end
16 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWSwipe.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWSwipe.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWSwipe)
12 |
13 | - (void)xw_swipeAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag;
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWPortal.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWPortal.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | @interface XWCoolAnimator (XWPortal)
12 |
13 | - (void)xw_setPortalToAnimation:(id)transitionContext;
14 |
15 | - (void)xw_setPortalBackAnimation:(id)transitionContext;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWPageCurl.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWPageCurl.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 | @interface XWFilterAnimator (XWPageCurl)
11 |
12 | - (void)xw_pageCurlAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag;
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWBarSwipe.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWBarSwipe.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWBarSwipe)
12 |
13 | - (void)xw_barSwipeAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag;
14 | @end
15 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWCopyMachine.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWCopyMachine.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 |
11 | @interface XWFilterAnimator (XWCopyMachine)
12 | - (void)xw_copyMachineAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag;
13 | @end
14 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWFold.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWFold.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | @interface XWCoolAnimator (XWFold)
12 |
13 | - (void)xw_setFoldToAnimation:(id)transitionContext leftFlag:(BOOL)left;
14 |
15 | - (void)xw_setFoldBackAnimation:(id)transitionContext leftFlag:(BOOL)left;
16 | @end
17 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWBasicFromController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWBasicFromController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "UINavigationController+XWTransition.h"
11 | #import "UIViewController+XWTransition.h"
12 |
13 | @interface XWBasicFromController : UIViewController
14 | @property (nonatomic, weak,readonly) UISwitch *pushOrPresntSwitch;
15 | @property (nonatomic, weak, readonly) UIButton *button;
16 |
17 | - (void)xw_transition;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWLines.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWVerticalLines.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/14.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | @interface XWCoolAnimator (XWLines)
12 |
13 |
14 | - (void)xw_setLinesToAnimation:(id)transitionContext vertical:(BOOL)vertical;
15 |
16 | - (void)xw_setLinesBackAnimation:(id)transitionContext vertical:(BOOL)vertical;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWBasicListController.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWBasicListController.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface XWBasicListController : UIViewController
12 | @property (nonatomic, copy) NSArray *titleData;
13 | @property (nonatomic, weak,readonly) UITableView *mainView;
14 |
15 | - (void)xw_configCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath;
16 |
17 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWScanning.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWScanning.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/14.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | @interface XWCoolAnimator (XWScanning)
12 |
13 |
14 | - (void)xw_setScanningToAnimation:(id)transitionContext direction:(NSUInteger)direction;
15 |
16 | - (void)xw_setScanningBackAnimation:(id)transitionContext direction:(NSUInteger)direction;
17 | @end
18 |
--------------------------------------------------------------------------------
/XWTransition/Category/UINavigationController+XWTransition.h:
--------------------------------------------------------------------------------
1 | //
2 | // UINavigationController+XWTransition.h
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 | @class XWTransitionAnimator;
11 |
12 | @interface UINavigationController (XWTransition)
13 |
14 | /**
15 | * 通过指定的转场animator来push控制器,达到不同的转场效果
16 | *
17 | * @param viewController 被push的控制器
18 | * @param animator 转场Animator
19 | */
20 | - (void)xw_pushViewController:(UIViewController *)viewController withAnimator:(XWTransitionAnimator *)animator;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/XWTransition/XWCircleSpreadAnimator/XWCircleSpreadAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCircleSpreadAnimator.h
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWTransitionAnimator.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface XWCircleSpreadAnimator : XWTransitionAnimator
14 |
15 | /**
16 | * 返回一个小圆点扩散转场效果器
17 | *
18 | * @param point 扩散开始中心
19 | * @param radius 扩散开始的半径
20 | *
21 | * @return 小圆点扩散转场效果器
22 | */
23 | + (instancetype)xw_animatorWithStartCenter:(CGPoint)point radius:(CGFloat)radius;
24 |
25 | @end
26 |
27 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransitionDemo/CircleSpreadTransition/XWCircleSpreadToController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCircleSpreadToController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCircleSpreadToController.h"
10 |
11 | @implementation XWCircleSpreadToController
12 |
13 | - (void)viewDidLoad {
14 | [super viewDidLoad];
15 | [self.button setTitle:@"点我或向下滑动" forState:UIControlStateNormal];
16 | __weak typeof(self)weakSelf = self;
17 | [self xw_registerBackInteractiveTransitionWithDirection:XWInteractiveTransitionGestureDirectionDown transitonBlock:^(CGPoint startPoint){
18 | [weakSelf xw_transiton];
19 | } edgeSpacing:0];
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/XWTransitionDemo/DrawerTransition/XWDrawerTypeListController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerTypeListController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWDrawerTypeListController.h"
10 | #import "XWDrawerFromController.h"
11 |
12 | @implementation XWDrawerTypeListController
13 |
14 | - (void)viewDidLoad {
15 | [super viewDidLoad];
16 | self.navigationItem.title = @"DrawertypeList";
17 | self.titleData = @[@"drawerLeft(仿QQ)",@"drawerBottom(仿淘宝)"];
18 | }
19 |
20 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath{
21 | XWDrawerFromController *fVC = [XWDrawerFromController new];
22 | fVC.type = indexPath.row;
23 | [self.navigationController pushViewController:fVC animated:YES];
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/XWTransition/Category/UIView+Snapshot.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Snapshot.m
3 | // XWTransitionDemo
4 | //
5 | // Created by 肖文 on 2016/12/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "UIView+Snapshot.h"
10 |
11 | @implementation UIView (Snapshot)
12 |
13 | - (UIImage *)snapshotImage {
14 | UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0);
15 | [self.layer renderInContext:UIGraphicsGetCurrentContext()];
16 | UIImage *snap = UIGraphicsGetImageFromCurrentImageContext();
17 | UIGraphicsEndImageContext();
18 | return snap;
19 | }
20 |
21 | - (UIImage *)contentImage{
22 | return [UIImage imageWithCGImage:(__bridge CGImageRef)self.layer.contents];
23 | }
24 |
25 | - (void)setContentImage:(UIImage *)contentImage{
26 | self.layer.contents = (__bridge id)contentImage.CGImage;;
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWMiddlePageFlip.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWMiddlePageFlip.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 |
11 | typedef NS_ENUM(NSUInteger, XWMiddlePageFlipDirection) {
12 | XWMiddlePageFlipDirectionLeft,
13 | XWMiddlePageFlipDirectionRight,
14 | XWMiddlePageFlipDirectionTop,
15 | XWMiddlePageFlipDirectionBottom
16 | };
17 |
18 | @interface XWCoolAnimator (XWMiddlePageFlip)
19 |
20 |
21 | - (void)xw_setMiddlePageFlipToAnimation:(id)transitionContext direction:(XWMiddlePageFlipDirection)direction;
22 |
23 | - (void)xw_setMiddlePageFlipBackAnimation:(id)transitionContext direction:(XWMiddlePageFlipDirection)direction;
24 | @end
25 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterTransitionView.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWBlurView.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface XWFilterTransitionView : GLKView
14 |
15 | @property (nonatomic, assign) BOOL blurType;
16 | @property (nonatomic, strong) CIFilter *filter;
17 |
18 | - (instancetype)initWithFrame:(CGRect)frame
19 | fromImage:(UIImage *)fromImage
20 | toImage:(UIImage *)toImage;
21 |
22 | - (CAAnimation *)xw_getInnerAnimation;
23 |
24 | - (CIVector *)xw_getInnerVector;
25 |
26 | + (void)xw_animationWith:(XWFilterTransitionView *)filterView duration:(NSTimeInterval)duration completion:(void (^ __nullable)(BOOL finished))completion;
27 |
28 | @end
29 |
30 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWBoxBlur.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWBoxBlur.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWBoxBlur.h"
10 |
11 | @implementation XWFilterAnimator (XWBoxBlur)
12 |
13 | - (void)xw_boxBlurAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration {
14 | CIFilter *filter = [CIFilter filterWithName: @"CIBoxBlur"];
15 | filterView.filter = filter;
16 | filterView.blurType = YES;
17 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
18 | [filterView removeFromSuperview];
19 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
20 |
21 | }];
22 | }
23 | @end
24 |
--------------------------------------------------------------------------------
/XWTransitionDemo/DrawerTransition/XWDrawerToController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerToController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWDrawerToController.h"
10 | #import "XWCoolAnimator.h"
11 |
12 | @implementation XWDrawerToController
13 |
14 | - (void)viewDidLoad {
15 | [super viewDidLoad];
16 | NSString *title = _type ? @"点我或向下滑动" : @"点我或向左滑动";
17 | [self.button setTitle:title forState:UIControlStateNormal];
18 | self.button.hidden = YES;
19 | XWInteractiveTransitionGestureDirection direction = _type ? XWInteractiveTransitionGestureDirectionDown : XWInteractiveTransitionGestureDirectionLeft;
20 | __weak typeof(self)weakSelf = self;
21 | [self xw_registerBackInteractiveTransitionWithDirection:direction transitonBlock:^(CGPoint startPoint){
22 | [weakSelf xw_transiton];
23 | } edgeSpacing:0];
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/XWTransitionDemo/FilterTransition/XWFilterListControllerController.m:
--------------------------------------------------------------------------------
1 |
2 |
3 | //
4 | // XWFilterListControllerViewController.m
5 | // XWTransitionDemo
6 | //
7 | // Created by wazrx on 16/6/17.
8 | // Copyright © 2016年 wazrx. All rights reserved.
9 | //
10 |
11 | #import "XWFilterListControllerController.h"
12 | #import "XWFilterFromController.h"
13 |
14 | @interface XWFilterListControllerController ()
15 |
16 | @end
17 |
18 | @implementation XWFilterListControllerController
19 |
20 | - (void)viewDidLoad {
21 | [super viewDidLoad];
22 | self.navigationItem.title = @"FilterTransition";
23 | self.titleData = @[@"BoxBlur", @"Swipe", @"BarsSwipe", @"Mask", @"Flash", @"Mod", @"PageCurl", @"Ripple", @"CopyMachine"];
24 | }
25 |
26 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath{
27 | XWFilterFromController *fVC = [XWFilterFromController new];
28 | fVC.type = indexPath.row;
29 | [self.navigationController pushViewController:fVC animated:YES];
30 | }
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWTransitionTypeListController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/9.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWTransitionTypeListController.h"
10 |
11 | @implementation XWTransitionTypeListController
12 |
13 | - (void)viewDidLoad {
14 | [super viewDidLoad];
15 | self.navigationItem.title = @"transitionList";
16 | self.titleData = @[@"CircleSpreadTransition", @"MagicMoveTransition", @"CoolTransition", @"DrawerTransition", @"FilterTransition"];
17 | }
18 |
19 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath{
20 | NSArray *controllerNames = @[@"XWCircleSpreadFromController", @"XWMagicMoveListController", @"XWCoolTypeListController", @"XWDrawerTypeListController", @"XWFilterListControllerController"];
21 | UIViewController *pushVC = [NSClassFromString(controllerNames[indexPath.row]) new];
22 | pushVC.hidesBottomBarWhenPushed = YES;
23 | [self.navigationController pushViewController:pushVC animated:YES];
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/XWTransitionDemo/PageFlipTransiton/XWCoolTypeListController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolTypeListController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolTypeListController.h"
10 | #import "XWCoolFromController.h"
11 | #import "XWCoolAnimator.h"
12 |
13 | @implementation XWCoolTypeListController
14 |
15 | - (void)viewDidLoad {
16 | [super viewDidLoad];
17 | self.navigationItem.title = @"CooltypeList";
18 | self.titleData = @[@"PageFlip",@"MiddleFlipFromLeft",@"MiddleFlipFromRight",@"MiddleFlipFromTop",@"MiddleFlipFromBottom",@"Portal",@"FoldFromLeft",@"FoldFromRight", @"Explode", @"HorizontalLines", @"VerticalLines",@"ScanningFromLeft",@"ScanningFromRight",@"ScanningFromTop",@"ScanningFromBottom"];
19 | }
20 |
21 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath{
22 | XWCoolFromController *fVC = [XWCoolFromController new];
23 | fVC.type = indexPath.row;
24 | [self.navigationController pushViewController:fVC animated:YES];
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/XWTransition/XWMagicMoveAnimator/XWMagicMoveAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveAnimator.h
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/8.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | // 神奇移动效果请配合UIViewController+XWTransition中的相关API使用,如果神奇移动的终止视图为cell,需要参考一下demo中的九宫格例子
8 |
9 | #import "XWTransitionAnimator.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface UIView (XWTransition)
14 |
15 | //神奇移动的时候,如果对设置view的该属性为YES,则移动视图不会按照截图的方式生成,而且尝试直接取得其image(暂时支持imageView、button等),解决神奇移动从下到大会产生模糊的情况
16 | @property (nonatomic, assign) BOOL magicMoveImageMode;
17 |
18 | @end
19 |
20 |
21 | @interface XWMagicMoveAnimator : XWTransitionAnimator
22 |
23 | //是否开启弹簧效果
24 | @property (nonatomic, assign) BOOL dampingEnable;
25 | //设为YES后,对于做神奇移动数组中的所有View会直接取其图片而不会截图,可解决神奇移动从小变得较大的时候,截图不清晰的问题,如果想要对单个view最该设置,请参考上面的UIView分类的magicMoveImageMode属性
26 | @property (nonatomic, assign) BOOL imageMode;
27 |
28 | @end
29 |
30 | UIKIT_EXTERN NSString *const kXWMagicMoveAnimatorStartViewVCKey;
31 | UIKIT_EXTERN NSString *const kXWMagicMoveAnimatorEndViewVCKey;
32 |
33 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWBarSwipe.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWBarSwipe.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWBarSwipe.h"
10 |
11 | @implementation XWFilterAnimator (XWBarSwipe)
12 |
13 | - (void)xw_barSwipeAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag {
14 | CGFloat angle = self.revers && !flag ? self.startAngle + M_PI : self.startAngle;
15 | CIFilter *filter = [CIFilter filterWithName:@"CIBarsSwipeTransition"
16 | keysAndValues:
17 | kCIInputAngleKey, @(angle),
18 | nil];
19 | filterView.filter = filter;
20 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
21 | [filterView removeFromSuperview];
22 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
23 | }];
24 | }
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/XWTransitionDemo/PageFlipTransiton/XWCoolToController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWPageFlipToController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolToController.h"
10 |
11 | @implementation XWCoolToController
12 |
13 | - (void)viewDidLoad {
14 | [super viewDidLoad];
15 | NSArray *directionNames = @[@"右",@"左",@"右",@"上",@"下",@"上",@"左",@"右",@"上",@"右", @"上", @"左", @"右", @"上", @"下"];
16 | [self.button setTitle:[NSString stringWithFormat:@"点我或向%@滑动", directionNames[_type]] forState:UIControlStateNormal];
17 | [self.button addTarget:self action:@selector(xw_transiton) forControlEvents:UIControlEventTouchUpInside];
18 | __weak typeof(self)weakSelf = self;
19 | [self xw_registerBackInteractiveTransitionWithDirection:[self xw_getDirectionWithName:directionNames[_type]] transitonBlock:^(CGPoint startPoint){
20 | [weakSelf xw_transiton];
21 | } edgeSpacing:0];
22 | }
23 |
24 | - (NSInteger)xw_getDirectionWithName:(NSString *)name{
25 | NSArray *temp = @[@"左", @"右", @"上", @"下"];
26 | return [temp indexOfObject:name];
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWPageCurl.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // XWFilterAnimator+XWPageCurl.m
4 | // XWTransitionDemo
5 | //
6 | // Created by wazrx on 16/6/19.
7 | // Copyright © 2016年 wazrx. All rights reserved.
8 | //
9 |
10 | #import "XWFilterAnimator+XWPageCurl.h"
11 |
12 | @implementation XWFilterAnimator (XWPageCurl)
13 |
14 | - (void)xw_pageCurlAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag{
15 | CGFloat angle = self.revers && !flag ? self.startAngle + M_PI : self.startAngle;
16 | CIFilter *filter = [CIFilter filterWithName: @"CIPageCurlWithShadowTransition"
17 | keysAndValues:
18 | kCIInputAngleKey, @(angle),
19 | nil];
20 | filterView.filter = filter;
21 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
22 | [filterView removeFromSuperview];
23 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
24 | }];
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/XWTransition/Main/XWTransitionAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWTransitionAnimator.h
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | // 所有转场效果器的基类,若要自定义请继承与该基类
8 |
9 | #import
10 | #import "XWInteractiveTransition.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface XWTransitionAnimator : NSObject
15 |
16 | //to转场时间 默认0.5
17 | @property (nonatomic, assign) NSTimeInterval toDuration;
18 | //back转场时间 默认0.5
19 | @property (nonatomic, assign) NSTimeInterval backDuration;
20 | //是否需要开启手势timer,某些转场如果在转成过程中所开手指,不会有动画过渡,显得很生硬,开启timer后,松开手指,会用timer不断的刷新转场百分比,消除生硬的缺点
21 | @property (nonatomic, assign) BOOL needInteractiveTimer;
22 |
23 | /**
24 | * 配置To过程动画(push, present),自定义转场动画应该复写该方法
25 | */
26 | - (void)xw_setToAnimation:(id)transitionContext;
27 | /**
28 | * 配置back过程动画(pop, dismiss),自定义转场动画应该复写该方法
29 | */
30 | - (void)xw_setBackAnimation:(id)transitionContext;
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransitionDemo/FilterTransition/XWFilterToController.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // XWFilterToController.m
4 | // XWTransitionDemo
5 | //
6 | // Created by wazrx on 16/6/17.
7 | // Copyright © 2016年 wazrx. All rights reserved.
8 | //
9 |
10 | #import "XWFilterToController.h"
11 |
12 | @interface XWFilterToController ()
13 |
14 | @end
15 |
16 | @implementation XWFilterToController
17 |
18 | - (void)viewDidLoad {
19 | [super viewDidLoad];
20 | NSArray *directionNames = @[@"上",@"左",@"左", @"上", @"上", @"上", @"左", @"左", @"左"];
21 | [self.button setTitle:[NSString stringWithFormat:@"点我或向%@滑动", directionNames[_type]] forState:UIControlStateNormal];
22 | [self.button addTarget:self action:@selector(xw_transiton) forControlEvents:UIControlEventTouchUpInside];
23 | __weak typeof(self)weakSelf = self;
24 | [self xw_registerBackInteractiveTransitionWithDirection:[self xw_getDirectionWithName:directionNames[_type]] transitonBlock:^(CGPoint startPoint){
25 | [weakSelf xw_transiton];
26 | } edgeSpacing:0];
27 | }
28 |
29 | - (NSInteger)xw_getDirectionWithName:(NSString *)name{
30 | NSArray *temp = @[@"左", @"右", @"上", @"下"];
31 | return [temp indexOfObject:name];
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWBasicFromController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWBasicFromController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicFromController.h"
10 |
11 | @implementation XWBasicFromController
12 |
13 | - (void)viewDidLoad {
14 | [super viewDidLoad];
15 | self.view.backgroundColor = [UIColor whiteColor];
16 | self.view.layer.contents = (__bridge id)[UIImage imageNamed:@"p1.JPG"].CGImage;
17 | UISwitch *pushOrPresntSwitch = [UISwitch new];
18 | _pushOrPresntSwitch = pushOrPresntSwitch;
19 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:pushOrPresntSwitch];
20 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
21 | _button = button;
22 | button.titleLabel.font = [UIFont systemFontOfSize:13];
23 | button.titleLabel.textAlignment = 1;
24 | [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
25 | button.center = CGPointMake(self.view.center.x, self.view.center.y + 30);
26 | button.bounds = CGRectMake(0, 0, 150, 30);
27 | [button addTarget:self action:@selector(xw_transition) forControlEvents:UIControlEventTouchUpInside];
28 | [self.view addSubview:button];
29 | }
30 |
31 | - (void)xw_transition {
32 |
33 | }
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWBasicToController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWBasicToController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicToController.h"
10 |
11 | @interface XWBasicToController ()
12 |
13 | @end
14 |
15 | @implementation XWBasicToController
16 |
17 | - (void)dealloc{
18 | NSLog(@"toVC销毁了");
19 | }
20 |
21 | - (void)viewDidLoad {
22 | [super viewDidLoad];
23 | self.view.backgroundColor = [UIColor whiteColor];
24 | self.view.layer.contents = (__bridge id)[UIImage imageNamed:@"p2.JPG"].CGImage;
25 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
26 | _button = button;
27 | button.titleLabel.font = [UIFont systemFontOfSize:13];
28 | [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
29 | button.center = CGPointMake(self.view.center.x, self.view.center.y + 30);
30 | button.bounds = CGRectMake(0, 0, 100, 30);
31 | [button addTarget:self action:@selector(xw_transiton) forControlEvents:UIControlEventTouchUpInside];
32 | [self.view addSubview:button];
33 | }
34 |
35 | - (void)xw_transiton{
36 | if (self.navigationController) {
37 | [self.navigationController popViewControllerAnimated:YES];
38 | }else{
39 | [self dismissViewControllerAnimated:YES completion:nil];
40 | }
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWRipple.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWRipple.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWRipple.h"
10 |
11 | @implementation XWFilterAnimator (XWRipple)
12 |
13 | - (void)xw_rippleAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration{
14 | CIImage *img = [CIImage imageWithCGImage:[UIImage imageNamed:@"restrictedshine.tiff"].CGImage];
15 | CIVector *vector = [filterView xw_getInnerVector];
16 | CIFilter *filter = [CIFilter filterWithName: @"CIRippleTransition"
17 | keysAndValues:
18 | kCIInputShadingImageKey, img,
19 | kCIInputCenterKey, [CIVector vectorWithX:0.5 * vector.CGRectValue.size.width
20 | Y:0.5 * vector.CGRectValue.size.height],
21 | nil];
22 | filterView.filter = filter;
23 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
24 | [filterView removeFromSuperview];
25 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
26 | }];
27 | }
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/XWTransition/XWDrawerAnimator/XWDrawerAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerAnimator.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWTransitionAnimator.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | typedef NS_ENUM(NSUInteger, XWDrawerAnimatorDirection) {
14 | XWDrawerAnimatorDirectionLeft,
15 | XWDrawerAnimatorDirectionRight,
16 | XWDrawerAnimatorDirectionTop,
17 | XWDrawerAnimatorDirectionBottom
18 | };
19 |
20 | @interface XWDrawerAnimator : XWTransitionAnimator
21 |
22 | /**fromVC的缩放比例, 如果Flip效果,比例默认为0.8, 否者为1.0不缩放*/
23 | @property (nonatomic, assign) CGFloat scaleRatio;
24 | /**视差效果,类似于QQ的设置界面弹出效果, 和flipEnable只能选择其一,如果都设置为YES,后设置的生效*/
25 | @property (nonatomic, assign) BOOL parallaxEnable;
26 | /**翻转效果,类似于淘宝选择规格时,后面视图的动画效果*/
27 | @property (nonatomic, assign) BOOL flipEnable;
28 |
29 | /**
30 | * 初始化一个转场抽屉效果器
31 | *
32 | * @param direction 抽屉效果触发方向
33 | * @param distance 显示在屏幕中的宽度或者高度,如果传0,默认就是当前屏幕的高度或者宽度
34 | *
35 | * @return animator
36 | */
37 | + (instancetype)xw_animatorWithDirection:(XWDrawerAnimatorDirection)direction moveDistance:(CGFloat)distance;
38 |
39 | /**
40 | * 开启边缘(就是屏幕除开toView所占用的部分)back手势和边缘点击返回效果,类似于QQ设置界面的返回效果
41 | *
42 | * @param backConfig 返回操作,您的dismiss或者pop操作
43 | */
44 | - (void)xw_enableEdgeGestureAndBackTapWithConfig:(dispatch_block_t)backConfig;
45 |
46 | @end
47 |
48 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWSwipe.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWSwipe.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWSwipe.h"
10 |
11 | @implementation XWFilterAnimator (XWSwipe)
12 |
13 | - (void)xw_swipeAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag {
14 | CGFloat angle = self.revers && !flag ? self.startAngle + M_PI : self.startAngle;
15 | CIVector *vector = [filterView xw_getInnerVector];
16 | CIFilter *filter = [CIFilter filterWithName:@"CISwipeTransition"
17 | keysAndValues:
18 | kCIInputExtentKey, vector,
19 | kCIInputColorKey, [CIColor colorWithRed:0 green:0 blue:0 alpha:0],
20 | kCIInputAngleKey, @(angle),
21 | kCIInputWidthKey, @80.0,
22 | @"inputOpacity", @0.0,
23 | nil];
24 | filterView.filter = filter;
25 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
26 | [filterView removeFromSuperview];
27 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
28 | }];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWFlash.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWFlash.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWFlash.h"
10 |
11 | @implementation XWFilterAnimator (XWFlash)
12 |
13 | - (void)xw_flashAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration{
14 | CGSize size = filterView.frame.size;
15 | CIFilter *filter = [CIFilter filterWithName:@"CIFlashTransition"
16 | keysAndValues:
17 | kCIInputCenterKey, [CIVector vectorWithCGPoint:CGPointMake(size.width, size.height)],
18 | kCIInputColorKey, [CIColor colorWithRed:1.0 green:0.8 blue:0.6 alpha:1],
19 | @"inputMaxStriationRadius", @2.5,
20 | @"inputStriationStrength", @0.5,
21 | @"inputStriationContrast", @1.37,
22 | @"inputFadeThreshold", @0.5,
23 | nil];
24 | filterView.filter = filter;
25 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
26 | [filterView removeFromSuperview];
27 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
28 | }];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWCopyMachine.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWCopyMachine.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWCopyMachine.h"
10 |
11 | @implementation XWFilterAnimator (XWCopyMachine)
12 |
13 | - (void)xw_copyMachineAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag{
14 | CGFloat angle = self.revers && !flag ? self.startAngle + M_PI : self.startAngle;
15 | CIVector *vector = [filterView xw_getInnerVector];
16 | CIFilter *filter = [CIFilter filterWithName:@"CICopyMachineTransition"
17 | keysAndValues:
18 | kCIInputExtentKey, vector,
19 | kCIInputColorKey, [CIColor colorWithRed:.6 green:1 blue:.8 alpha:1],
20 | kCIInputAngleKey, @(angle),
21 | kCIInputWidthKey, @50.0,
22 | @"inputOpacity", @1.0,
23 | nil];
24 | filterView.filter = filter;
25 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
26 | [filterView removeFromSuperview];
27 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
28 | }];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWMod.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWMod.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWMod.h"
10 |
11 | @implementation XWFilterAnimator (XWMod)
12 |
13 | - (void)xw_modAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration toFlag:(BOOL)flag{
14 | CGFloat angle = self.revers && !flag ? self.startAngle + M_PI : self.startAngle;
15 | CIVector *vector = [filterView xw_getInnerVector];
16 | CIFilter *filter = [CIFilter filterWithName: @"CIModTransition"
17 | keysAndValues:
18 | kCIInputCenterKey,[CIVector vectorWithX:0.5 * vector.CGRectValue.size.width
19 | Y:0.5 * vector.CGRectValue.size.height],
20 | kCIInputAngleKey, @(angle),
21 | kCIInputRadiusKey, @30.0,
22 | @"inputCompression", @10.0,
23 | nil];
24 | filterView.filter = filter;
25 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
26 | [filterView removeFromSuperview];
27 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
28 | }];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/XWTransitionDemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "83.5x83.5",
66 | "scale" : "2x"
67 | }
68 | ],
69 | "info" : {
70 | "version" : 1,
71 | "author" : "xcode"
72 | }
73 | }
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator+XWMask.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator+XWMask.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator+XWMask.h"
10 |
11 | @implementation XWFilterAnimator (XWMask)
12 |
13 | - (void)xw_maskAnimationFor:(XWFilterTransitionView *)filterView transitionContext:(id)transitionContext duration:(NSTimeInterval)duration {
14 | CGFloat height = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view.frame.size.height;
15 | CIImage *maskImg = self.maskImg ? [CIImage imageWithCGImage:self.maskImg.CGImage] : [CIImage imageWithCGImage:[UIImage imageNamed:@"mask.jpg"].CGImage];
16 | CIFilter *filter = [CIFilter filterWithName: @"CIDisintegrateWithMaskTransition"
17 | keysAndValues:
18 | kCIInputMaskImageKey, maskImg,
19 | @"inputShadowRadius", @10.0,
20 | @"inputShadowDensity", @0.7,
21 | @"inputShadowOffset", [CIVector vectorWithX:0.0 Y:-0.05 * height],
22 | nil];
23 | filterView.filter = filter;
24 | [XWFilterTransitionView xw_animationWith:filterView duration:duration completion:^(BOOL finished) {
25 | [filterView removeFromSuperview];
26 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
27 | }];
28 | }
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/XWTransitionDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveToController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveToController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWMagicMoveToController.h"
10 |
11 | @interface XWMagicMoveToController ()
12 | @property (nonatomic, weak) UIImageView *imgView;
13 | @property (nonatomic, strong) UIImage *img;
14 | @end
15 |
16 | @implementation XWMagicMoveToController
17 |
18 | - (void)viewDidLoad {
19 | [super viewDidLoad];
20 | self.view.layer.contents = nil;
21 | UIImageView *imgView = [UIImageView new];
22 | imgView.frame = CGRectMake(10, 100, 150, 150);
23 | imgView.image = _img;
24 | [self.view addSubview:imgView];
25 | UIView *view1 = [UIView new];
26 | view1.backgroundColor = [UIColor blueColor];
27 | [self.view addSubview:view1];
28 | view1.frame = CGRectMake(50, 400, 80, 80);
29 | view1.layer.cornerRadius = 40;
30 | UIView *view2 = [UIView new];
31 | view2.backgroundColor = [UIColor purpleColor];
32 | view2.frame = CGRectMake(200, 400, 75, 75);
33 | [self.view addSubview:view2];
34 | [self.button setTitle:@"点我或向上滑动" forState:UIControlStateNormal];
35 | [self xw_addMagicMoveEndViewGroup:@[imgView, view1, view2]];
36 | __weak typeof(self)weakSelf = self;
37 | [self xw_registerBackInteractiveTransitionWithDirection:XWInteractiveTransitionGestureDirectionUp transitonBlock:^(CGPoint startPoint){
38 | [weakSelf xw_transiton];
39 | } edgeSpacing:0];
40 | }
41 |
42 | - (void)xw_setImage:(UIImage *)img {
43 | _img = img;
44 | }
45 | @end
46 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | // XWFilterAnimator 全都是基于不同的CIFilter产生的一些滤镜效果,貌似在模拟器无法运行这些效果,请在真机上测试
8 |
9 | #import "XWTransitionAnimator.h"
10 | #import "XWFilterTransitionView.h"
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | typedef NS_ENUM(NSUInteger, XWFilterAnimatorType) {
15 | XWFilterAnimatorTypeBoxBlur,//模糊转场,对应CIBoxBlur
16 | XWFilterAnimatorTypeSwipe,//滑动过渡转场,对应CISwipeTranstion
17 | XWFilterAnimatorTypeBarSwipe,//对应CIBarSwipeTranstion
18 | XWFilterAnimatorTypeMask,//按指定遮罩图片转场,对应CIDisintegrateWithMaskTransition
19 | XWFilterAnimatorTypeFlash,//闪烁转场,对应CIFlashTransition
20 | XWFilterAnimatorTypeMod,//条纹转场 对应CIModTransition
21 | XWFilterAnimatorTypePageCurl,//翻页转场 对应CIPageCurlWithShadowTransition
22 | XWFilterAnimatorTypeRipple,//波纹转场,对应CIRippleTransition
23 | XWFilterAnimatorTypeCopyMachine, //效果和XWCoolAnimator中的Scanning效果类似,对应CICopyMachineTransition
24 | };
25 |
26 | @interface XWFilterAnimator : XWTransitionAnimator
27 |
28 | /**for XWFilterAnimatorTypeMask,如果为空,则为默认的maskImg*/
29 | @property (nonatomic, strong) UIImage *maskImg;
30 | /**是否翻转,对于有转场有方向之分的此属性可用,如果为YES,如果to转场为左,那么back转场为右,默认为YES*/
31 | @property (nonatomic, assign) BOOL revers;
32 | /**开始角度,对于有转场方向的转场此属性可用,0为左,M_PI_2 为下 M_PI 为右 M_PI_2 * 3为上,也可指定任意开始角度*/
33 | @property (nonatomic, assign) CGFloat startAngle;
34 |
35 | /**
36 | * 初始化一个filter转场效果器
37 | *
38 | * @param type 效果枚举值
39 | *
40 | * @return 效果器
41 | */
42 | + (instancetype)xw_animatorWithType:(XWFilterAnimatorType)type;
43 |
44 | @end
45 |
46 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransitionDemo/FilterTransition/XWFilterFromController.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // XWFilterFromController.m
4 | // XWTransitionDemo
5 | //
6 | // Created by wazrx on 16/6/17.
7 | // Copyright © 2016年 wazrx. All rights reserved.
8 | //
9 |
10 | #import "XWFilterFromController.h"
11 | #import "XWFilterToController.h"
12 | #import "XWFilterAnimator.h"
13 |
14 | @interface XWFilterFromController ()
15 |
16 | @end
17 |
18 | @implementation XWFilterFromController
19 |
20 | - (void)viewDidLoad {
21 | [super viewDidLoad];
22 | NSArray *directionNames = @[@"下",@"右", @"右", @"下", @"下", @"下", @"右", @"右", @"右"];
23 | [self.button setTitle:[NSString stringWithFormat:@"点我或向%@滑动", directionNames[_type]] forState:UIControlStateNormal];
24 | [self.button addTarget:self action:@selector(xw_transition) forControlEvents:UIControlEventTouchUpInside];
25 | __weak typeof(self)weakSelf = self;
26 | [self xw_registerToInteractiveTransitionWithDirection:[self xw_getDirectionWithName:directionNames[_type]] transitonBlock:^(CGPoint startPoint){
27 | [weakSelf xw_transition];
28 | } edgeSpacing:0];
29 | }
30 |
31 | - (void)xw_transition{
32 | XWFilterAnimator *animator = [XWFilterAnimator xw_animatorWithType:_type];
33 | XWFilterToController *toVC = [XWFilterToController new];
34 | toVC.type = _type;
35 | if (self.pushOrPresntSwitch.on) {
36 | [self.navigationController xw_pushViewController:toVC withAnimator:animator];
37 | }else{
38 | [self xw_presentViewController:toVC withAnimator:animator];
39 | }
40 | }
41 |
42 | - (NSInteger)xw_getDirectionWithName:(NSString *)name{
43 | NSArray *temp = @[@"左", @"右", @"上", @"下"];
44 | return [temp indexOfObject:name];
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/XWTransitionDemo/PageFlipTransiton/XWCoolFromController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWPageFlipFromController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolFromController.h"
10 | #import "XWCoolToController.h"
11 | #import "XWCoolAnimator.h"
12 |
13 |
14 | @implementation XWCoolFromController
15 |
16 | - (void)viewDidLoad {
17 | [super viewDidLoad];
18 | NSArray *directionNames = @[@"左",@"右", @"左", @"下", @"上", @"下",@"右",@"左",@"下",@"左",@"下",@"右",@"左",@"下",@"上"];
19 | [self.button setTitle:[NSString stringWithFormat:@"点我或向%@滑动", directionNames[_type]] forState:UIControlStateNormal];
20 | [self.button addTarget:self action:@selector(xw_transition) forControlEvents:UIControlEventTouchUpInside];
21 | __weak typeof(self)weakSelf = self;
22 | [self xw_registerToInteractiveTransitionWithDirection:[self xw_getDirectionWithName:directionNames[_type]] transitonBlock:^(CGPoint startPoint){
23 | [weakSelf xw_transition];
24 | } edgeSpacing:0];
25 | }
26 |
27 | - (void)xw_transition{
28 | XWCoolAnimator *animator = [XWCoolAnimator xw_animatorWithType:_type];
29 | animator.toDuration = 1.0f;
30 | animator.backDuration = 1.0f;
31 | XWCoolToController *toVC = [XWCoolToController new];
32 | toVC.type = _type;
33 | if (self.pushOrPresntSwitch.on) {
34 | [self.navigationController xw_pushViewController:toVC withAnimator:animator];
35 | }else{
36 | [self xw_presentViewController:toVC withAnimator:animator];
37 | }
38 | }
39 |
40 | - (NSInteger)xw_getDirectionWithName:(NSString *)name{
41 | NSArray *temp = @[@"左", @"右", @"上", @"下"];
42 | return [temp indexOfObject:name];
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/XWTransitionDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/XWTransitionDemo/XWBasicListController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWBasicListController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWBasicListController.h"
10 |
11 | @interface XWBasicListController ()
12 |
13 | @end
14 |
15 | @implementation XWBasicListController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | self.view.backgroundColor = [UIColor whiteColor];
20 | UITableView *mainView = [UITableView new];
21 | mainView.delegate = self;
22 | mainView.dataSource = self;
23 | mainView.frame = self.view.bounds;
24 | mainView.backgroundColor = [UIColor whiteColor];
25 | _mainView = mainView;
26 | [self.view addSubview:mainView];
27 | }
28 |
29 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
30 | return self.titleData.count;
31 | }
32 |
33 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
34 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"xwtransition"];
35 | if (!cell) {
36 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"xwtransition"];
37 | }
38 | cell.textLabel.text = _titleData[indexPath.row];
39 | [self xw_configCell:cell indexPath:indexPath];
40 | return cell;
41 | }
42 |
43 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
44 | [self xw_selectCellAtIndexPath:indexPath];
45 | }
46 |
47 | - (void)xw_configCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
48 |
49 | }
50 |
51 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath {
52 |
53 | }
54 |
55 |
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveListController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveListController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWMagicMoveListController.h"
10 | #import "XWMagicMoveFromController.h"
11 | #import "XWMagicMoveFromTwoController.h"
12 | #import "XWMagicMoveAnimator.h"
13 |
14 | @implementation XWMagicMoveListController
15 |
16 | - (void)viewDidLoad {
17 | [super viewDidLoad];
18 | self.navigationItem.title = @"magicTypeList";
19 | self.titleData = @[@"test1",@"test2"];
20 | self.mainView.rowHeight = 65;
21 | }
22 |
23 | - (void)xw_configCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath{
24 | NSArray *imgs = @[@"zrx1.jpg", @"zrx2.jpg"];
25 | cell.imageView.image = [UIImage imageNamed:imgs[indexPath.row]];
26 | }
27 |
28 | - (void)xw_selectCellAtIndexPath:(NSIndexPath *)indexPath{
29 | UIImageView *imgView = [self.mainView cellForRowAtIndexPath:indexPath].imageView;
30 | [self xw_addMagicMoveStartViewGroup:@[imgView]];
31 | XWMagicMoveAnimator *animator = [XWMagicMoveAnimator new];
32 | animator.dampingEnable = YES;
33 | animator.imageMode = YES;
34 | animator.toDuration = 0.5f;
35 | animator.backDuration = 0.5f;
36 | if (indexPath.row == 0) {
37 | XWMagicMoveFromController *fromVC = [XWMagicMoveFromController new];
38 | [fromVC xw_setImage:imgView.image];
39 | [self.navigationController xw_pushViewController:fromVC withAnimator:animator];
40 | return;
41 | }
42 | if (indexPath.row == 1) {
43 | XWMagicMoveFromTwoController *fromTwoVC = [XWMagicMoveFromTwoController new];
44 | [self.navigationController xw_pushViewController:fromTwoVC withAnimator:animator];
45 | }
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWTransitionAnimator.h"
10 |
11 | /**
12 | cool转场效果中的Portal、Fold、Explode效果的部分代码逻辑来源于ColinEberhardt/VCTransitionsLibrary,地址:https://github.com/ColinEberhardt/VCTransitionsLibrary 非常感谢作者,我只是将其进行了部分改动,以便对手势的支持更加完善,里面还有许多其他效果,本人经历有限就没有再集成进来了,大家可以自行查看;
13 | cool转场效果的Lines的想法来自于cinkster/HUAnimator,地址:https://github.com/cinkster/HUAnimator, 非常感谢作者,但是由于作者在对toVC截图采用了延迟的方式来处理,导致了闪烁和一些手势上的bug,对此我采用了另一种方式来解决截图的问题,使用了layer的contentRect属性,解决了闪烁问题和延迟截图的bug问题,相关代码请自行查看
14 |
15 | */
16 |
17 | NS_ASSUME_NONNULL_BEGIN
18 |
19 | typedef NS_ENUM(NSUInteger, XWCoolTransitionAnimatorType){
20 | //全屏翻页
21 | XWCoolTransitionAnimatorTypePageFlip,
22 | //中间翻页
23 | XWCoolTransitionAnimatorTypePageMiddleFlipFromLeft,
24 | XWCoolTransitionAnimatorTypePageMiddleFlipFromRight,
25 | XWCoolTransitionAnimatorTypePageMiddleFlipFromTop,
26 | XWCoolTransitionAnimatorTypePageMiddleFlipFromBottom,
27 | //开窗
28 | XWCoolTransitionAnimatorTypePortal,
29 | //折叠
30 | XWCoolTransitionAnimatorTypeFoldFromLeft,
31 | XWCoolTransitionAnimatorTypeFoldFromRight,
32 | //爆炸
33 | XWCoolTransitionAnimatorTypeExplode,
34 | //酷炫线条效果
35 | XWCoolTransitionAnimatorTypeHorizontalLines,
36 | XWCoolTransitionAnimatorTypeVerticalLines,
37 | //扫描效果
38 | XWCoolTransitionAnimatorTypeScanningFromLeft,
39 | XWCoolTransitionAnimatorTypeScanningFromRight,
40 | XWCoolTransitionAnimatorTypeScanningFromTop,
41 | XWCoolTransitionAnimatorTypeScanningFromBottom,
42 |
43 |
44 | };
45 |
46 | @interface XWCoolAnimator : XWTransitionAnimator
47 |
48 | //flod效果的折叠数量, for XWCoolTransitionAnimatorTypeFoldFromLeft 和 XWCoolTransitionAnimatorTypeFoldFromRight
49 | @property (nonatomic) NSUInteger foldCount;
50 |
51 | + (instancetype)xw_animatorWithType:(XWCoolTransitionAnimatorType)type;
52 |
53 | @end
54 |
55 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransitionDemo/CircleSpreadTransition/XWCircleSpreadFromController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCircleSpreadController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCircleSpreadFromController.h"
10 | #import "XWCircleSpreadToController.h"
11 | #import "XWCircleSpreadAnimator.h"
12 |
13 | @implementation XWCircleSpreadFromController
14 |
15 | - (void)viewDidLoad {
16 | [super viewDidLoad];
17 | [self.button addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(xw_drag:)]];
18 | [self.button setTitle:@"点我\n拖我" forState:UIControlStateNormal];
19 | self.button.backgroundColor = [UIColor lightGrayColor];
20 | self.button.titleLabel.numberOfLines = 0;
21 | self.button.titleLabel.font = [UIFont systemFontOfSize:12];
22 | self.button.bounds = CGRectMake(0, 0, 40, 40);
23 | self.button.center = CGPointMake(self.view.center.x, self.view.center.y - 100);
24 | self.button.layer.cornerRadius = 20;
25 |
26 | }
27 |
28 | - (void)xw_transition{
29 | XWCircleSpreadAnimator *animator = [XWCircleSpreadAnimator xw_animatorWithStartCenter:self.button.center radius:20];
30 | animator.toDuration = 0.5f;
31 | animator.backDuration = 0.5f;
32 | XWCircleSpreadToController *toVC = [XWCircleSpreadToController new];
33 | if (self.pushOrPresntSwitch.on) {
34 | [self.navigationController xw_pushViewController:toVC withAnimator:animator];
35 | }else{
36 | [self xw_presentViewController:toVC withAnimator:animator];
37 | }
38 | }
39 |
40 | - (void)xw_drag:(UIPanGestureRecognizer *)panGesture{
41 | CGPoint transitionP = [panGesture translationInView:panGesture.view];
42 | CGFloat transitionX = fmax(20, fmin(self.button.center.x + transitionP.x, self.view.bounds.size.width - 20));
43 | CGFloat transitionY = fmax(64 + 20, fmin(self.button.center.y + transitionP.y, self.view.bounds.size.height - 20));
44 | self.button.center = CGPointMake(transitionX, transitionY);
45 | [panGesture setTranslation:CGPointZero inView:panGesture.view];
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/XWTransition/Main/XWInteractiveTransition.h:
--------------------------------------------------------------------------------
1 | //
2 | // XWInteractiveTransition.h
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/10.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | // 手势转场管理者
8 | // 注意:使用UIViewController+XWTransition相关API配合animator,通常情况下无需自己创建手势过渡管理者
9 |
10 | #import
11 | @class XWInteractiveTransition;
12 |
13 | NS_ASSUME_NONNULL_BEGIN
14 |
15 | /**手势转场时的代理事件,animator默认为为其手势的代理,复写对应的代理事件可处理一些手势失败闪烁的情况*/
16 | @protocol XWInteractiveTransitionDelegate
17 |
18 | @optional
19 | /**手势转场即将开始时调用*/
20 | - (void)xw_interactiveTransitionWillBegin:(XWInteractiveTransition *)interactiveTransition;
21 | /**手势转场中调用*/
22 | - (void)xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition isUpdating:(CGFloat)percent;
23 | /**如果开始了转场手势timer,会在松开手指,timer开始的时候调用*/
24 | - (void)xw_interactiveTransitionWillBeginTimerAnimation:(XWInteractiveTransition *)interactiveTransition;
25 | /**手势转场结束的时候调用*/
26 | - (void)xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition willEndWithSuccessFlag:(BOOL)flag percent:(CGFloat)percent;
27 |
28 | @end
29 |
30 | /**手势转场方向*/
31 | typedef NS_ENUM(NSUInteger, XWInteractiveTransitionGestureDirection) {
32 | XWInteractiveTransitionGestureDirectionLeft = 0,
33 | XWInteractiveTransitionGestureDirectionRight,
34 | XWInteractiveTransitionGestureDirectionUp,
35 | XWInteractiveTransitionGestureDirectionDown
36 | };
37 |
38 | @interface XWInteractiveTransition : UIPercentDrivenInteractiveTransition
39 |
40 | @property (nonatomic, assign, readonly) BOOL interation;
41 | @property (nonatomic, assign) BOOL timerEable;
42 | @property (nonatomic, weak) id delegate;
43 |
44 | /**设置该值可改变计算手势百分比的基准,手势基准的原理:百分比 = 拖动距离 / panRatioBaseValue, 默认情况下水平方向panRatioBaseValue为手势所在view的宽度,垂直方向为手势所在view的高度,通常无需更改该值,在某些特殊情况下,如果想要调整手势的速率可以更改该值,比如让手势速率加倍,可以调整该值为view宽度高度的一半*/
45 | @property (nonatomic, assign) CGFloat panRatioBaseValue;
46 |
47 | + (instancetype)xw_interactiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction config:(void(^)(CGPoint startPoint))config edgeSpacing:(CGFloat)edgeSpacing;
48 |
49 | - (void)xw_addPanGestureForView:(UIView *)view to:(BOOL)flag;
50 |
51 | @end
52 |
53 | NS_ASSUME_NONNULL_END
--------------------------------------------------------------------------------
/XWTransition/Category/UIViewController+XWTransition.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+XWTransition.h
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "XWTransitionAnimator.h"
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface UIViewController (XWTransition)
14 |
15 |
16 | /**
17 | * 通过指定的转场animator来present控制器
18 | *
19 | * @param viewController 被modal出的控制器
20 | * @param animator 转场animator
21 | */
22 | - (void)xw_presentViewController:(UIViewController *)viewController withAnimator:(XWTransitionAnimator *)animator;
23 |
24 |
25 | #pragma mark - 神奇移动相关
26 |
27 | /**
28 | * 注册神奇移动起始视图
29 | *
30 | * @param group 神奇移动起始视图数组
31 | */
32 | - (void)xw_addMagicMoveStartViewGroup:(NSArray *)group;
33 |
34 | /**
35 | * 注册神奇移动终止视图
36 | *
37 | * @param group 神奇移动终止视图数组,注意起始视图数组和终止视图数组的视图需要一一对应才能有正确的效果
38 | */
39 | - (void)xw_addMagicMoveEndViewGroup:(NSArray *)group;
40 |
41 | /**
42 | * 改变神奇移动起始视图,因为在back的时候,有可能不需要再回到原来起始的位置,需要去一个新的视图位置,所以在back前需要调用该方法改变起始视图数组
43 | *
44 | * @param group 新的起始视图数组
45 | */
46 | - (void)xw_changeMagicMoveStartViewGroup:(NSArray *)group;
47 |
48 | #pragma mark - 手势相关
49 |
50 | /**
51 | * 注册to手势(push或者Present手势),block中的startPoint为手势开始时手指所在的点,在有些特殊需求的时候,你可能需要它
52 | *
53 | * @param direction 手势方向
54 | * @param tansitionConfig 手势触发的block,block中需要包含你的push或者Present的逻辑代码,注意避免循环引用问题
55 | * @param edgeSpacing 手势触发的边缘距离,该值为0,表示在整个控制器视图上都有效,否者这在边缘的edgeSpacing之类有效
56 | */
57 |
58 | - (void)xw_registerToInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(void(^)(CGPoint startPoint))tansitionConfig edgeSpacing:(CGFloat)edgeSpacing;
59 |
60 | /**
61 | * 注册back手势(pop或者dismiss手势)
62 | *
63 | * @param direction 手势方向
64 | * @param tansitionConfig 手势触发的block,block中需要包含你的pop或者dismiss的逻辑代码,注意避免循环引用问题
65 | * @param edgeSpacing 手势触发的边缘距离,该值为0,表示在整个控制器视图上都有效,否者这在边缘的edgeSpacing之类有效
66 | */
67 | - (void)xw_registerBackInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(void(^)(CGPoint startPoint))tansitionConfig edgeSpacing:(CGFloat)edgeSpacing;
68 |
69 | @end
70 |
71 | UIKIT_EXTERN NSString *const kXWToInteractiveKey;
72 | UIKIT_EXTERN NSString *const kXWAnimatorKey;
73 |
74 | NS_ASSUME_NONNULL_END
75 |
76 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveFromController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveFromController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/12.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWMagicMoveFromController.h"
10 | #import "XWMagicMoveToController.h"
11 | #import "XWMagicMoveAnimator.h"
12 | #import "UIViewController+XWTransition.h"
13 | #import "UINavigationController+XWTransition.h"
14 |
15 | @interface XWMagicMoveFromController ()
16 |
17 | @property (nonatomic, strong) UIImage *img;
18 |
19 | @end
20 |
21 | @implementation XWMagicMoveFromController
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | self.view.layer.contents = nil;
26 | UIImageView *imgView = [UIImageView new];
27 | imgView.center = CGPointMake(self.view.center.x, 170);
28 | imgView.bounds = CGRectMake(0, 0, 200, 200);
29 | imgView.image = _img;
30 | [self.view addSubview:imgView];
31 | UIView *view1 = [UIView new];
32 | view1.backgroundColor = [UIColor blueColor];
33 | [self.view addSubview:view1];
34 | view1.frame = CGRectMake(50, 300, 50, 50);
35 | view1.layer.cornerRadius = 25;
36 | UIView *view2 = [UIView new];
37 | view2.backgroundColor = [UIColor purpleColor];
38 | view2.frame = CGRectMake(250, 300, 75, 75);
39 | [self.view addSubview:view2];
40 |
41 | [self.button setTitle:@"点我或向下滑动" forState:UIControlStateNormal];
42 | //注册神奇移动前视图
43 | [self xw_addMagicMoveEndViewGroup:@[imgView]];
44 | [self xw_addMagicMoveStartViewGroup:@[imgView, view1, view2]];
45 | __weak typeof(self)weakSelf = self;
46 | [self xw_registerToInteractiveTransitionWithDirection:XWInteractiveTransitionGestureDirectionDown transitonBlock:^(CGPoint startPoint){
47 | [weakSelf xw_transition];
48 | } edgeSpacing:0];
49 | }
50 |
51 | - (void)xw_setImage:(UIImage *)img {
52 | _img = img;
53 | }
54 |
55 | - (void)xw_transition{
56 | XWMagicMoveToController *toVC = [XWMagicMoveToController new];
57 | [toVC xw_setImage:_img];
58 | XWMagicMoveAnimator *animator = [XWMagicMoveAnimator new];
59 | animator.toDuration = animator.backDuration = 0.5;
60 | if (self.pushOrPresntSwitch.on) {
61 | [self.navigationController xw_pushViewController:toVC withAnimator:animator];
62 | }else{
63 | [self xw_presentViewController:toVC withAnimator:animator];
64 | }
65 | }
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveFromTwoController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveToTwoController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWMagicMoveFromTwoController.h"
10 | #import "XWMagicMoveToImageController.h"
11 | #import "UIViewController+XWTransition.h"
12 | #import "UINavigationController+XWTransition.h"
13 | #import "XWMagicMoveAnimator.h"
14 |
15 | @interface XWMagicMoveFromTwoController ()
16 |
17 | @end
18 |
19 | @implementation XWMagicMoveFromTwoController
20 |
21 | - (void)dealloc{
22 | NSLog(@"toVC销毁了");
23 | }
24 |
25 | - (void)viewDidLoad {
26 | [super viewDidLoad];
27 | self.view.backgroundColor = [UIColor whiteColor];
28 | for (int i = 0; i < 9; i ++) {
29 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
30 | // [button setImage:[UIImage imageNamed:[NSString stringWithFormat:@"zrx%zd.jpg", i + 1]] forState:UIControlStateNormal];
31 | button.layer.contents = (__bridge id)[UIImage imageNamed:[NSString stringWithFormat:@"zrx%zd.jpg", i + 1]].CGImage;
32 |
33 | [button addTarget:self action:@selector(xw_clicked:) forControlEvents:UIControlEventTouchUpInside];
34 | CGFloat spacing = 5;
35 | CGFloat edgeSpacing = 15;
36 | CGFloat width = (self.view.frame.size.width - (5 + 15) * 2) / 3.0f;
37 | CGFloat height = width;
38 | CGFloat x = edgeSpacing + (width + spacing) * (i % 3);
39 | CGFloat y = 100 + (height + spacing) * (i / 3);
40 | button.frame = CGRectMake(x, y, width, height);
41 | [self.view addSubview:button];
42 | }
43 | //注册神奇移动转场终止视图
44 | [self xw_addMagicMoveEndViewGroup:@[self.view.subviews[1]]];
45 |
46 | }
47 |
48 | - (void)xw_clicked:(UIButton *)sender{
49 | XWMagicMoveToImageController *imgVC = [XWMagicMoveToImageController new];
50 | imgVC.idx = [self.view.subviews indexOfObject:sender];
51 | __weak typeof(self)weakSelf = self;
52 | imgVC.dismissConfig = ^(NSInteger idx){
53 | [weakSelf xw_dismiss:idx];
54 | };
55 | //将点击的按钮注册为神奇移动转场开始视图
56 | [self xw_addMagicMoveStartViewGroup:@[sender]];
57 | XWMagicMoveAnimator *animator = [XWMagicMoveAnimator new];
58 | // animator.dampingEnable = YES;
59 | // animator.imageMode = YES;
60 | sender.magicMoveImageMode = YES;
61 | [self xw_presentViewController:imgVC withAnimator: animator];
62 | }
63 |
64 | - (void)xw_dismiss:(NSInteger)idx{
65 | //更改转场视图为collectionView滑动的视图
66 | [self xw_changeMagicMoveStartViewGroup:@[self.view.subviews[idx]]];
67 | //dismiss
68 | [self dismissViewControllerAnimated:YES completion:nil];
69 | }
70 |
71 | @end
72 |
--------------------------------------------------------------------------------
/XWTransitionDemo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/XWTransition/Category/UIViewController+XWTransition.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+XWTransition.m
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "UIViewController+XWTransition.h"
10 | #import "XWMagicMoveAnimator.h"
11 | #import
12 |
13 | @implementation UIViewController (XWTransition)
14 |
15 | - (void)xw_registerToInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(void(^)(CGPoint startPoint))tansitionConfig edgeSpacing:(CGFloat)edgeSpacing{
16 | if (!tansitionConfig) return;
17 | XWInteractiveTransition *interactive = [XWInteractiveTransition xw_interactiveTransitionWithDirection:direction config:tansitionConfig edgeSpacing:edgeSpacing];
18 | [interactive xw_addPanGestureForView:self.view to:YES];
19 | objc_setAssociatedObject(self, &kXWToInteractiveKey, interactive, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
20 |
21 | }
22 |
23 | - (void)xw_registerBackInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(void(^)(CGPoint startPoint))tansitionConfig edgeSpacing:(CGFloat)edgeSpacing{
24 | if (!tansitionConfig) return;
25 | XWInteractiveTransition *interactive = [XWInteractiveTransition xw_interactiveTransitionWithDirection:direction config:tansitionConfig edgeSpacing:edgeSpacing];
26 | [interactive xw_addPanGestureForView:self.view to:NO];
27 | XWTransitionAnimator *animator = objc_getAssociatedObject(self, &kXWAnimatorKey);if (animator) {
28 | [animator setValue:interactive forKey:@"backInteractive"];
29 | }
30 | }
31 |
32 | - (void)xw_presentViewController:(UIViewController *)viewController withAnimator:(XWTransitionAnimator *)animator {
33 | if (!viewController) return;
34 | if (!animator) animator = [XWTransitionAnimator new];
35 | viewController.transitioningDelegate = animator;
36 | XWInteractiveTransition *toInteractive = objc_getAssociatedObject(self, &kXWToInteractiveKey);
37 | if (toInteractive) {
38 | [animator setValue:toInteractive forKey:@"toInteractive"];
39 | }
40 | objc_setAssociatedObject(viewController, &kXWAnimatorKey, animator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
41 | [self presentViewController:viewController animated:YES completion:nil];
42 | }
43 |
44 | - (void)xw_addMagicMoveStartViewGroup:(NSArray *)group {
45 | if (!group.count) return;
46 | objc_setAssociatedObject(self, &kXWMagicMoveAnimatorStartViewVCKey, group, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
47 | }
48 |
49 | - (void)xw_addMagicMoveEndViewGroup:(NSArray *)group {
50 | if (!group.count) return;
51 | objc_setAssociatedObject(self, &kXWMagicMoveAnimatorEndViewVCKey, group, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
52 |
53 | }
54 |
55 | - (void)xw_changeMagicMoveStartViewGroup:(NSArray *)group {
56 | [self xw_addMagicMoveStartViewGroup:group];
57 | }
58 |
59 | @end
60 |
61 | NSString *const kXWToInteractiveKey = @"kXWToInteractiveKey";
62 | NSString *const kXWAnimatorKey = @"kXWAnimatorKey";
63 |
--------------------------------------------------------------------------------
/XWTransitionDemo/DrawerTransition/XWDrawerFromController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWDrawerFromController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/15.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWDrawerFromController.h"
10 | #import "XWDrawerToController.h"
11 | #import "XWDrawerAnimator.h"
12 |
13 | @implementation XWDrawerFromController
14 |
15 | - (void)viewDidLoad {
16 | [super viewDidLoad];
17 | NSString *title = _type ? @"点我或向上滑动" : @"点我或从边缘向右滑动";
18 | [self.button setTitle:title forState:UIControlStateNormal];
19 | __weak typeof(self)weakSelf = self;
20 | XWInteractiveTransitionGestureDirection direction = _type ? XWInteractiveTransitionGestureDirectionUp : XWInteractiveTransitionGestureDirectionRight;
21 | [self xw_registerToInteractiveTransitionWithDirection:direction transitonBlock:^(CGPoint startPoint){
22 | [weakSelf xw_transition];
23 | } edgeSpacing:_type ? 0 : 80];
24 | }
25 |
26 | - (void)viewDidAppear:(BOOL)animated{
27 | [super viewDidAppear:animated];
28 | self.navigationController.interactivePopGestureRecognizer.enabled = NO;
29 | }
30 |
31 | - (void)viewDidDisappear:(BOOL)animated{
32 | [super viewDidDisappear:animated];
33 | self.navigationController.interactivePopGestureRecognizer.enabled = YES;
34 | }
35 |
36 | - (void)xw_transition{
37 | XWDrawerAnimatorDirection direction = _type ? XWDrawerAnimatorDirectionBottom : XWDrawerAnimatorDirectionLeft;
38 | CGFloat distance = _type ? 450 : 250;
39 | XWDrawerAnimator *animator = [XWDrawerAnimator xw_animatorWithDirection:direction moveDistance:distance];
40 | animator.toDuration = 0.5;
41 | animator.backDuration = 0.5;
42 | if (_type) {
43 | animator.flipEnable = YES;
44 | }else{
45 | animator.parallaxEnable = YES;
46 | }
47 | XWDrawerToController *toVC = [XWDrawerToController new];
48 | toVC.type = _type;
49 | if (self.pushOrPresntSwitch.on) {
50 | [self.navigationController xw_pushViewController:toVC withAnimator:animator];
51 | }else{
52 | [self xw_presentViewController:toVC withAnimator:animator];
53 | }
54 | __weak typeof(self)weakSelf = self;
55 | [animator xw_enableEdgeGestureAndBackTapWithConfig:^{
56 | [weakSelf _xw_back];
57 | }];
58 | }
59 |
60 | - (void)_xw_back{
61 | if (self.presentedViewController) {
62 | [self dismissViewControllerAnimated:YES completion:nil];
63 | }else{
64 | [self.navigationController popViewControllerAnimated:YES];
65 | }
66 | }
67 |
68 |
69 |
70 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
71 | return 20;
72 | }
73 |
74 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
75 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"test"];
76 | if (!cell) {
77 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"test"];
78 | cell.textLabel.text = @"测试";
79 | }
80 | return cell;
81 | }
82 |
83 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
84 | NSLog(@"选中了%zd", indexPath.row);
85 | [self xw_transition];
86 | }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWExplode.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWExplode.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/14.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWExplode.h"
10 | #import "UIView+Snapshot.h"
11 |
12 | @implementation XWCoolAnimator (XWExplode)
13 |
14 | - (void)xw_setExplodeToAnimation:(id)transitionContext {
15 | [self _xw_animation:transitionContext duration:self.toDuration];
16 |
17 | }
18 |
19 | - (void)xw_setExplodeBackAnimation:(id)transitionContext {
20 | [self _xw_animation:transitionContext duration:self.backDuration];
21 |
22 | }
23 |
24 | - (void)_xw_animation:(id)transitionContext duration:(NSTimeInterval)duration{
25 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
26 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
27 | UIView *toView = toVC.view;
28 | UIView *fromView = fromVC.view;
29 | UIView *containerView = [transitionContext containerView];
30 | [containerView insertSubview:toView atIndex:0];
31 | CGSize size = toView.frame.size;
32 | NSMutableArray *snapshots = [NSMutableArray new];
33 | CGFloat xNum = 10.0f;
34 | CGFloat yNum = xNum * size.height / size.width;
35 | UIView *fromViewSnapshot = [UIView new];
36 | UIImage *fromImage = fromVC.view.snapshotImage;
37 | fromViewSnapshot.contentImage = fromImage;
38 | CGFloat fromWidth = fromVC.view.bounds.size.width;
39 | CGFloat fromHeight = fromVC.view.bounds.size.height;
40 | for (CGFloat x=0; x < size.width; x+= size.width / xNum) {
41 | for (CGFloat y=0; y < size.height; y+= size.height / yNum) {
42 | CGRect snapshotRegion = CGRectMake(x, y, size.width / xNum, size.height / yNum);
43 | UIView *snapshot = [UIView new];
44 | snapshot.contentImage = fromImage;
45 | CGRect contentRect = CGRectMake(x / fromWidth, y / fromHeight, size.width / xNum / fromWidth, size.height / yNum / fromHeight);
46 | snapshot.layer.contentsRect = contentRect;
47 | snapshot.frame = snapshotRegion;
48 | [containerView addSubview:snapshot];
49 | [snapshots addObject:snapshot];
50 | }
51 | }
52 | fromView.hidden = YES;
53 | [UIView animateWithDuration:duration animations:^{
54 | for (UIView *view in snapshots) {
55 | CGFloat xOffset = [self _xw_randomFloatBetween:-100.0 and:100.0];
56 | CGFloat yOffset = [self _xw_randomFloatBetween:-100.0 and:100.0];
57 | view.frame = CGRectOffset(view.frame, xOffset, yOffset);
58 | view.alpha = 0.0;
59 | view.transform = CGAffineTransformScale(CGAffineTransformMakeRotation([self _xw_randomFloatBetween:-10.0 and:10.0]), 0.01, 0.01);
60 | }
61 | } completion:^(BOOL finished) {
62 | for (UIView *view in snapshots) {
63 | [view removeFromSuperview];
64 | }
65 | fromView.hidden = NO;
66 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
67 | }];
68 | }
69 |
70 | - (float)_xw_randomFloatBetween:(float)smallNumber and:(float)bigNumber {
71 | float diff = bigNumber - smallNumber;
72 | return (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + smallNumber;
73 | }
74 |
75 | @end
76 |
--------------------------------------------------------------------------------
/XWTransition/Category/UINavigationController+XWTransition.m:
--------------------------------------------------------------------------------
1 | //
2 | // UINavigationController+XWTransition.m
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "UINavigationController+XWTransition.h"
10 | #import "UIViewController+XWTransition.h"
11 | #import "XWTransitionAnimator.h"
12 | #import
13 | #import
14 |
15 | @implementation UINavigationController (XWTransition)
16 |
17 | + (void)load{
18 | method_exchangeImplementations(class_getInstanceMethod([self class], @selector(pushViewController:animated:)), class_getInstanceMethod([self class], @selector(_xw_pushViewController:animated:)));
19 | }
20 |
21 | - (void)xw_pushViewController:(UIViewController *)viewController withAnimator:(XWTransitionAnimator *)animator {
22 | if (!viewController) return;
23 | XWInteractiveTransition *toInteractive = objc_getAssociatedObject(self.topViewController, &kXWToInteractiveKey);
24 | if (toInteractive) {
25 | [animator setValue:toInteractive forKey:@"toInteractive"];
26 | }
27 | if (animator) {
28 | objc_setAssociatedObject(viewController, &kXWAnimatorKey, animator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
29 | }
30 | [self pushViewController:viewController animated:YES];
31 | static dispatch_once_t onceToken;
32 | dispatch_once(&onceToken, ^{
33 | [self _xw_swizzeViewControlelrDealloc];
34 | });
35 | }
36 |
37 | - (void)_xw_swizzeViewControlelrDealloc{
38 | Class swizzleClass = [UIViewController class];
39 | @synchronized(swizzleClass) {
40 | SEL deallocSelector = sel_registerName("dealloc");
41 | __block void (*originalDealloc)(__unsafe_unretained id, SEL) = NULL;
42 | __weak typeof(self)weakSelf = self;
43 | id newDealloc = ^(__unsafe_unretained UIViewController *objSelf){
44 | [weakSelf _xw_checkDelegate];
45 | if (originalDealloc == NULL) {
46 | struct objc_super superInfo = {
47 | .receiver = objSelf,
48 | .super_class = class_getSuperclass(swizzleClass)
49 | };
50 | void (*msgSend)(struct objc_super *, SEL) = (__typeof__(msgSend))objc_msgSendSuper;
51 | msgSend(&superInfo, deallocSelector);
52 | }else{
53 | originalDealloc(objSelf, deallocSelector);
54 | }
55 | };
56 | IMP newDeallocIMP = imp_implementationWithBlock(newDealloc);
57 | if (!class_addMethod(swizzleClass, deallocSelector, newDeallocIMP, "v@:")) {
58 | Method deallocMethod = class_getInstanceMethod(swizzleClass, deallocSelector);
59 | originalDealloc = (void(*)(__unsafe_unretained id, SEL))method_getImplementation(deallocMethod);
60 | originalDealloc = (void(*)(__unsafe_unretained id, SEL))method_setImplementation(deallocMethod, newDeallocIMP);
61 | }
62 | }
63 | }
64 |
65 | - (void)_xw_checkDelegate{
66 | XWTransitionAnimator *animator = objc_getAssociatedObject(self.topViewController, &kXWAnimatorKey);
67 | if (animator) {
68 | self.delegate = animator;
69 | }else{
70 | self.delegate = nil;
71 | }
72 | }
73 |
74 | - (void)_xw_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
75 | XWTransitionAnimator *animator = objc_getAssociatedObject(viewController, &kXWAnimatorKey);
76 | if (animator) {
77 | self.delegate = animator;
78 | }else if([self.delegate isKindOfClass:[XWTransitionAnimator class]]){
79 | self.delegate = nil;
80 | }
81 | [self _xw_pushViewController:viewController animated:animated];
82 | }
83 |
84 | @end
85 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWScanning.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWScanning.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/14.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWScanning.h"
10 |
11 | @implementation XWCoolAnimator (XWScanning)
12 |
13 | - (void)xw_setScanningToAnimation:(id)transitionContext direction:(NSUInteger)direction {
14 | [self _xw_animateTransition:transitionContext duration:self.toDuration direction:direction];
15 |
16 | }
17 |
18 | - (void)xw_setScanningBackAnimation:(id)transitionContext direction:(NSUInteger)direction {
19 | [self _xw_animateTransition:transitionContext duration:self.toDuration direction:direction];
20 |
21 | }
22 |
23 | - (void)_xw_animateTransition:(id )transitionContext duration:(NSTimeInterval)duration direction:(NSInteger)direction{
24 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
25 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
26 | UIView *containerView = [transitionContext containerView];
27 | [containerView insertSubview:toVC.view atIndex:0];
28 | UIView *maskView = [UIView new];
29 | maskView.backgroundColor = [UIColor whiteColor];
30 | maskView.frame = containerView.bounds;
31 | fromVC.view.maskView = maskView;
32 | UIView *scanView = [UIView new];
33 | scanView.layer.contents = (__bridge id)[UIImage imageNamed:@"line"].CGImage;
34 | [containerView addSubview:scanView];
35 | CGFloat width = containerView.frame.size.width;
36 | CGFloat height = containerView.frame.size.height;
37 | CGAffineTransform transfrom = CGAffineTransformIdentity;
38 | if (direction == 0){
39 | scanView.bounds = CGRectMake(0, 0, 18, height * 1.5);
40 | scanView.center = CGPointMake(-4, containerView.center.y);
41 | transfrom = CGAffineTransformMakeTranslation(width, 0);
42 | }
43 | if (direction == 1){
44 | scanView.bounds = CGRectMake(0, 0, 18, height * 1.5);
45 | scanView.center = CGPointMake(width + 4, containerView.center.y);
46 | transfrom = CGAffineTransformMakeTranslation(-width, 0);
47 | }
48 | if (direction == 2){
49 | scanView.bounds = CGRectMake(0, 0,width * 1.5, 18);
50 | scanView.center = CGPointMake(containerView.center.x, -4);
51 | transfrom = CGAffineTransformMakeTranslation(0, height);
52 | }
53 | if (direction == 3){
54 | scanView.bounds = CGRectMake(0, 0, width * 1.5, 18);
55 | scanView.center = CGPointMake(containerView.center.x, height + 4);
56 | transfrom = CGAffineTransformMakeTranslation(0, -height);
57 | }
58 | [UIView animateKeyframesWithDuration:duration delay:0.0 options:0
59 | animations:^{
60 | [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.7 animations:^{
61 | maskView.transform = transfrom;
62 | scanView.transform = transfrom;
63 | }];
64 | [UIView addKeyframeWithRelativeStartTime:0.7 relativeDuration:0.3 animations:^{
65 | scanView.transform = CGAffineTransformIdentity;
66 | }];
67 |
68 | } completion:^(BOOL finished) {
69 | fromVC.view.maskView = nil;
70 | [scanView removeFromSuperview];
71 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
72 | }];
73 |
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/XWTransitionDemo/MagicMoveTransiton/XWMagicMoveToImageController.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWMagicMoveToImageController.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/19.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWMagicMoveToImageController.h"
10 | #import "UIViewController+XWTransition.h"
11 |
12 | @interface XWMagicMoveToImageController ()
13 | @property (nonatomic, weak) UICollectionView *mainView;
14 | @property (nonatomic, weak) UIView *tempView;
15 | @end
16 |
17 | @implementation XWMagicMoveToImageController
18 |
19 | - (void)dealloc{
20 | NSLog(@"toVC销毁了");
21 | }
22 |
23 | - (void)viewDidLoad {
24 | [super viewDidLoad];
25 | [self xw_initailizeUI];
26 | //根据点击的idx设置collectionView的滚动位置
27 | [_mainView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:_idx inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
28 | //注意:由于在转场过程中cell还没有加载,所以无法注册cell为神奇移动视图,这种情况需要生产一个零时视图注册为转场视图来使用
29 | //下面创建一个零时的转场视图
30 | UIView *tempView = [UIView new];
31 | tempView.layer.contents = (__bridge id)[UIImage imageNamed:[NSString stringWithFormat:@"zrx%zd.jpg", _idx + 1]].CGImage;
32 | [self.view addSubview:tempView];
33 | _tempView = tempView;
34 | //配置tempView的图片和位置和cell完全重合
35 | tempView.center = self.view.center;
36 | tempView.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width);
37 | //将该零时视图注册为神奇移动结束视图
38 | [self xw_addMagicMoveEndViewGroup:@[tempView]];
39 | //隐藏collectionView
40 | _mainView.hidden = YES;
41 | __weak typeof(self)weakSelf = self;
42 | //注册back手势,左滑动黑色部分可以back
43 | [self xw_registerBackInteractiveTransitionWithDirection:XWInteractiveTransitionGestureDirectionLeft transitonBlock:^(CGPoint startPoint){
44 | [weakSelf collectionView:weakSelf.mainView didSelectItemAtIndexPath:[weakSelf.mainView indexPathsForVisibleItems].firstObject];
45 | } edgeSpacing:0];
46 | }
47 |
48 | #pragma mark - initialize methods
49 |
50 | - (void)xw_initailizeUI{
51 | self.view.backgroundColor = [UIColor blackColor];
52 | UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
53 | layout.itemSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.width);
54 | layout.minimumLineSpacing = 0;
55 | layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
56 | UICollectionView *mainView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
57 | mainView.backgroundColor = [UIColor blackColor];
58 | _mainView = mainView;
59 | mainView.pagingEnabled = YES;
60 | mainView.delegate = self;
61 | mainView.dataSource = self;
62 | [mainView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"xw_XWMagicMoveToImageController_cell"];
63 | [self.view addSubview:mainView];
64 | mainView.center = self.view.center;
65 | mainView.bounds = CGRectMake(0, 0, layout.itemSize.width, layout.itemSize.height);
66 | }
67 |
68 | - (void)viewDidAppear:(BOOL)animated{
69 | [super viewDidAppear:animated];
70 | //转场结束后,我们需要隐藏零时视图,同时显示collectionView,转场完成
71 | _mainView.hidden = NO;
72 | _tempView.hidden = YES;
73 | }
74 |
75 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
76 | return 9;
77 | }
78 |
79 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
80 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"xw_XWMagicMoveToImageController_cell" forIndexPath:indexPath];
81 | cell.layer.contents = (__bridge id)[UIImage imageNamed:[NSString stringWithFormat:@"zrx%zd.jpg", indexPath.item + 1]].CGImage;
82 | return cell;
83 | }
84 |
85 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
86 | //back的时候,我们继续调出临时视图来转场,同时设置临时视图的图片为当前图片
87 | _tempView.hidden = NO;
88 | _mainView.hidden = YES;
89 | _tempView.layer.contents = (__bridge id)[UIImage imageNamed:[NSString stringWithFormat:@"zrx%zd.jpg", indexPath.item + 1]].CGImage;
90 | //将dismiss操作传递给presentingController,因为此时转场回去的视图已经改变,而且本来dismiss操作最好也应该有presentingController来完成
91 | if (_dismissConfig) {
92 | _dismissConfig(indexPath.item);
93 | }
94 | }
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWPageFlip.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWPageFlip.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWPageFlip.h"
10 | #import "UIView+Snapshot.h"
11 | #import
12 |
13 | static NSString *const kPageFlipTempViewKey = @"kPageFlipTempViewKey";
14 |
15 | @implementation XWCoolAnimator (XWPageFlip)
16 |
17 | - (void)xw_setPageFlipToAnimation:(id)transitionContext {
18 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
19 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
20 | UIView *tempView = [UIView new];
21 | tempView.contentImage = fromVC.view.snapshotImage;
22 | tempView.frame = fromVC.view.frame;
23 | UIView *containerView = [transitionContext containerView];
24 | [containerView addSubview:toVC.view];
25 | [containerView addSubview:tempView];
26 | fromVC.view.hidden = YES;
27 | [containerView insertSubview:toVC.view atIndex:0];
28 | [self _xw_setAnchorPoint:CGPointMake(0, 0.5) forView:tempView];
29 | CATransform3D transfrom3d = CATransform3DIdentity;
30 | transfrom3d.m34 = -0.002;
31 | containerView.layer.sublayerTransform = transfrom3d;
32 | CAGradientLayer *fromGradient = [CAGradientLayer layer];
33 | fromGradient.frame = fromVC.view.bounds;
34 | fromGradient.colors = @[(id)[UIColor blackColor].CGColor,
35 | (id)[UIColor blackColor].CGColor];
36 | fromGradient.startPoint = CGPointMake(0.0, 0.5);
37 | fromGradient.endPoint = CGPointMake(0.8, 0.5);
38 | UIView *fromShadow = [[UIView alloc]initWithFrame:fromVC.view.bounds];
39 | fromShadow.backgroundColor = [UIColor clearColor];
40 | [fromShadow.layer insertSublayer:fromGradient atIndex:1];
41 | fromShadow.alpha = 0.0;
42 | [tempView addSubview:fromShadow];
43 | CAGradientLayer *toGradient = [CAGradientLayer layer];
44 | toGradient.frame = fromVC.view.bounds;
45 | toGradient.colors = @[(id)[UIColor blackColor].CGColor,
46 | (id)[UIColor blackColor].CGColor];
47 | toGradient.startPoint = CGPointMake(0.0, 0.5);
48 | toGradient.endPoint = CGPointMake(0.8, 0.5);
49 | UIView *toShadow = [[UIView alloc]initWithFrame:fromVC.view.bounds];
50 | toShadow.backgroundColor = [UIColor clearColor];
51 | [toShadow.layer insertSublayer:toGradient atIndex:1];
52 | toShadow.alpha = 1.0;
53 | [toVC.view addSubview:toShadow];
54 | objc_setAssociatedObject(self, &kPageFlipTempViewKey, tempView, OBJC_ASSOCIATION_ASSIGN);
55 | [UIView animateWithDuration:self.toDuration animations:^{
56 | tempView.layer.transform = CATransform3DMakeRotation(-M_PI_2, 0, 1, 0);
57 | fromShadow.alpha = 1.0;
58 | toShadow.alpha = 0.0;
59 | } completion:^(BOOL finished) {
60 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
61 | if ([transitionContext transitionWasCancelled]) {
62 | [tempView removeFromSuperview];
63 | fromVC.view.hidden = NO;
64 | }
65 | }];
66 |
67 | }
68 |
69 | - (void)xw_setPageFlipBackAnimation:(id)transitionContext {
70 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
71 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
72 | UIView *containerView = [transitionContext containerView];
73 | UIView *tempView = objc_getAssociatedObject(self, &kPageFlipTempViewKey);
74 | [containerView addSubview:toVC.view];
75 | [UIView animateWithDuration:self.backDuration animations:^{
76 | tempView.layer.transform = CATransform3DIdentity;
77 | fromVC.view.subviews.lastObject.alpha = 1.0;
78 | tempView.subviews.lastObject.alpha = 0.0;
79 | } completion:^(BOOL finished) {
80 | if ([transitionContext transitionWasCancelled]) {
81 | [transitionContext completeTransition:NO];
82 | }else{
83 | [transitionContext completeTransition:YES];
84 | [tempView removeFromSuperview];
85 | toVC.view.hidden = NO;
86 | }
87 | }];
88 | }
89 |
90 | - (void)_xw_setAnchorPoint:(CGPoint)point forView:(UIView *)view{
91 | view.frame = CGRectOffset(view.frame, (point.x - view.layer.anchorPoint.x) * view.frame.size.width, (point.y - view.layer.anchorPoint.y) * view.frame.size.height);
92 | view.layer.anchorPoint = point;
93 | }
94 | @end
95 |
--------------------------------------------------------------------------------
/XWTransition/XWCircleSpreadAnimator/XWCircleSpreadAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCircleSpreadAnimator.m
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCircleSpreadAnimator.h"
10 |
11 | @interface XWCircleSpreadAnimator ()
12 | @property (nonatomic, assign) CGPoint startPoint;
13 | @property (nonatomic, assign) CGFloat startRadius;
14 | @property (nonatomic, strong) UIBezierPath *startPath;
15 | @property (nonatomic, strong) UIView *containerView;
16 | @property (nonatomic, strong) CAShapeLayer *maskLayer;
17 |
18 | @end
19 |
20 | @implementation XWCircleSpreadAnimator
21 |
22 | + (instancetype)xw_animatorWithStartCenter:(CGPoint)point radius:(CGFloat)radius {
23 | return [[self alloc] _initWithStartCenter:point radius:radius];
24 | }
25 |
26 | - (instancetype)_initWithStartCenter:(CGPoint)point radius:(CGFloat)radius
27 | {
28 | self = [super init];
29 | if (self) {
30 | _startPoint = point;
31 | _startRadius = radius == 0 ? 0.01 : radius;
32 | self.needInteractiveTimer = YES;
33 | }
34 | return self;
35 | }
36 |
37 | - (void)xw_setToAnimation:(id)transitionContext{
38 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
39 | UIView *containerView = [transitionContext containerView];
40 | [containerView addSubview:toVC.view];
41 | UIBezierPath *startCycle = [UIBezierPath bezierPathWithArcCenter:self.startPoint radius:self.startRadius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
42 | CGFloat x = self.startPoint.x;
43 | CGFloat y = self.startPoint.y;
44 | CGFloat endX = MAX(x, containerView.frame.size.width - x);
45 | CGFloat endY = MAX(y, containerView.frame.size.height - y);
46 | CGFloat radius = sqrtf(pow(endX, 2) + pow(endY, 2));
47 | UIBezierPath *endCycle = [UIBezierPath bezierPathWithArcCenter:self.startPoint radius:radius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
48 | CAShapeLayer *maskLayer = [CAShapeLayer layer];
49 | maskLayer.path = endCycle.CGPath;
50 | toVC.view.layer.mask = maskLayer;
51 | self.startPath = startCycle;
52 | self.maskLayer = maskLayer;
53 | self.containerView = containerView;
54 | CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
55 | maskLayerAnimation.fromValue = (__bridge id)(startCycle.CGPath);
56 | maskLayerAnimation.toValue = (__bridge id)((endCycle.CGPath));
57 | maskLayerAnimation.duration = self.toDuration;
58 | maskLayerAnimation.delegate = self;
59 | [maskLayerAnimation setValue:transitionContext forKey:@"transitionContext"];
60 | [maskLayer addAnimation:maskLayerAnimation forKey:@"xw_path"];
61 | }
62 |
63 | - (void)xw_setBackAnimation:(id)transitionContext{
64 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
65 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
66 | UIView *containerView = [transitionContext containerView];
67 | [containerView insertSubview:toVC.view atIndex:0];
68 | UIBezierPath *endCycle = [UIBezierPath bezierPathWithArcCenter:self.startPoint radius:self.startRadius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
69 | CAShapeLayer *maskLayer = (CAShapeLayer *)fromVC.view.layer.mask;
70 | CGPathRef startPath = maskLayer.path;
71 | maskLayer.path = endCycle.CGPath;
72 | self.maskLayer = maskLayer;
73 | self.startPath = [UIBezierPath bezierPathWithCGPath:startPath];
74 | self.containerView = containerView;
75 | CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
76 | maskLayerAnimation.fromValue = (__bridge id)(startPath);
77 | maskLayerAnimation.toValue = (__bridge id)(endCycle.CGPath);
78 | maskLayerAnimation.duration = self.backDuration;
79 | maskLayerAnimation.delegate = self;
80 | [maskLayerAnimation setValue:transitionContext forKey:@"transitionContext"];
81 | [maskLayer addAnimation:maskLayerAnimation forKey:@"xw_path"];
82 | }
83 |
84 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
85 | id transitionContext = [anim valueForKey:@"transitionContext"];
86 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
87 | }
88 |
89 | - (void)xw_interactiveTransitionWillBeginTimerAnimation:(XWInteractiveTransition *)interactiveTransition{
90 | _containerView.userInteractionEnabled = NO;
91 | }
92 |
93 | - (void)xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition willEndWithSuccessFlag:(BOOL)flag percent:(CGFloat)percent{
94 | if (!flag) {
95 | //防止失败后的闪烁
96 | _maskLayer.path = _startPath.CGPath;
97 | }
98 | _containerView.userInteractionEnabled = YES;
99 | }
100 |
101 | @end
102 |
--------------------------------------------------------------------------------
/XWTransition/Main/XWTransitionAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWTransitionAnimator.m
3 | // XWTADemo
4 | //
5 | // Created by wazrx on 16/6/7.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWTransitionAnimator.h"
10 | #import
11 | #import
12 |
13 | #pragma mark - 私有转场动画管理者
14 |
15 | typedef void(^XWTransitionAnimationConfig)(id transitionContext);
16 |
17 | @interface _XWTransitionObject : NSObject
18 |
19 |
20 | - (instancetype)_initObjectWithDuration:(NSTimeInterval)duration animationBlock:(void(^)(id transitionContext)) config;
21 |
22 | @end
23 |
24 | @implementation _XWTransitionObject{
25 | NSTimeInterval _duration;
26 | XWTransitionAnimationConfig _config;
27 | }
28 |
29 | - (instancetype)_initObjectWithDuration:(NSTimeInterval)duration animationBlock:(XWTransitionAnimationConfig)config{
30 | self = [super init];
31 | if (self) {
32 | _duration = duration;
33 | _config = config;
34 | }
35 | return self;
36 | }
37 |
38 | #pragma mark -
39 |
40 | - (NSTimeInterval)transitionDuration:(id)transitionContext{
41 | return _duration;
42 | }
43 |
44 | - (void)animateTransition:(id)transitionContext{
45 | if (_config) {
46 | _config(transitionContext);
47 | }
48 |
49 | }
50 |
51 | @end
52 |
53 | @interface XWTransitionAnimator ()
54 | @property (nonatomic, strong) _XWTransitionObject *toTransition;
55 | @property (nonatomic, strong) _XWTransitionObject *backTranstion;
56 | @property (nonatomic, strong) XWInteractiveTransition *toInteractive;
57 | @property (nonatomic, strong) XWInteractiveTransition *backInteractive;
58 | @property (nonatomic, assign) UINavigationControllerOperation operation;
59 | @property (nonatomic, assign) BOOL toType;
60 |
61 | @end
62 |
63 | @implementation XWTransitionAnimator
64 |
65 |
66 | - (instancetype)init
67 | {
68 | self = [super init];
69 | if (self) {
70 | _toDuration = _backDuration = 0.5f;
71 | }
72 | return self;
73 | }
74 |
75 | - (_XWTransitionObject *)toTransition{
76 | if (!_toTransition) {
77 | __weak typeof(self)weakSelf = self;
78 | _toTransition = [[_XWTransitionObject alloc] _initObjectWithDuration:_toDuration animationBlock:^(id transitionContext) {
79 | [weakSelf xw_setToAnimation:transitionContext];
80 | }];
81 | }
82 | return _toTransition;
83 | }
84 |
85 | - (_XWTransitionObject *)backTranstion{
86 | if (!_backTranstion) {
87 | __weak typeof(self)weakSelf = self;
88 | _backTranstion = [[_XWTransitionObject alloc] _initObjectWithDuration:_backDuration animationBlock:^(id transitionContext) {
89 | [weakSelf xw_setBackAnimation:transitionContext];
90 | }];
91 | }
92 | return _backTranstion;
93 | }
94 |
95 | - (void)setToInteractive:(XWInteractiveTransition *)toInteractive{
96 | _toInteractive = toInteractive;
97 | toInteractive.delegate = self;
98 | toInteractive.timerEable = _needInteractiveTimer;
99 |
100 | }
101 |
102 | - (void)setBackInteractive:(XWInteractiveTransition *)backInteractive{
103 | _backInteractive = backInteractive;
104 | backInteractive.delegate = self;
105 | backInteractive.timerEable = _needInteractiveTimer;
106 |
107 | }
108 |
109 | - (void)xw_setToAnimation:(id)transitionContext{
110 | //交给子类实现
111 | }
112 |
113 | - (void)xw_setBackAnimation:(id)transitionContext{
114 | //交给子类实现
115 | }
116 |
117 | #pragma mark -
118 |
119 | - (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{
120 | return self.toTransition;
121 | }
122 |
123 | - (id)animationControllerForDismissedController:(UIViewController *)dismissed{
124 | return self.backTranstion;
125 | }
126 |
127 | - (id)interactionControllerForDismissal:(id)animator{
128 | return self.backInteractive.interation ? self.backInteractive : nil;
129 | }
130 |
131 | - (id)interactionControllerForPresentation:(id)animator{
132 | return self.toInteractive.interation ? self.toInteractive : nil;
133 | }
134 |
135 | #pragma mark -
136 |
137 | - (id)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
138 | _operation = operation;
139 | return operation == UINavigationControllerOperationPush ? self.toTransition : self.backTranstion;
140 | }
141 |
142 | - (id)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id)animationController{
143 | XWInteractiveTransition *inter = _operation == UINavigationControllerOperationPush ? self.toInteractive : self.backInteractive;
144 | return inter.interation ? inter : nil;
145 | }
146 |
147 | @end
148 |
149 |
150 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterTransitionView.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWBlurView.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterTransitionView.h"
10 |
11 | @interface _XWDisplayRatioLayer : CALayer
12 |
13 | @property (nonatomic, assign) CGFloat ratio;
14 | @property (nonatomic, copy) void(^ratioUpdating)(CGFloat ratio);
15 |
16 | @end
17 |
18 | @implementation _XWDisplayRatioLayer
19 |
20 | @dynamic ratio;
21 |
22 | + (BOOL)needsDisplayForKey:(NSString *)key{
23 | if ([key isEqualToString:@"ratio"]) {
24 | return YES;
25 | }
26 | return [super needsDisplayForKey:key];
27 | }
28 |
29 | - (void)display{
30 | if (_ratioUpdating) {
31 | _ratioUpdating([[self presentationLayer] ratio]);
32 | }
33 | }
34 |
35 | @end
36 |
37 | @interface XWFilterTransitionView ()
38 | @property (nonatomic, weak) _XWDisplayRatioLayer *ratioLayer;
39 | @property (nonatomic, assign) CGFloat ratio;
40 | @property (nonatomic, copy) CIImage *(^animationConfig)(CGFloat ratio, CIImage *fromImg, CIImage * toImg, CIFilter * filter);
41 | @property (nonatomic, copy) void(^completion)(BOOL finish);
42 | @property (nonatomic, assign) CGFloat lastRatio;
43 |
44 | @end
45 |
46 | @implementation XWFilterTransitionView{
47 | CIImage *_fromImg;
48 | CIImage *_toImg;
49 | CIContext *_saveContext;
50 | CGRect _imgRect;
51 | CIVector *_vector;
52 | }
53 |
54 | - (instancetype)initWithFrame:(CGRect)frame
55 | fromImage:(UIImage *)fromImage
56 | toImage:(UIImage *)toImage{
57 | self = [super initWithFrame:frame];
58 | if (!self) return nil;
59 | _fromImg = [CIImage imageWithCGImage:fromImage.CGImage];
60 | _toImg = [CIImage imageWithCGImage:toImage.CGImage];
61 | _vector = [CIVector vectorWithX:0 Y:0 Z:fromImage.size.width * fromImage.scale W:fromImage.size.height * fromImage.scale];
62 | CGFloat width = fromImage.size.width * fromImage.scale;
63 | CGFloat height = fromImage.size.height * fromImage.scale;
64 | _imgRect = CGRectMake(0, 0, width, height);
65 | self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
66 | _saveContext = [CIContext contextWithEAGLContext:self.context];
67 | _XWDisplayRatioLayer *layer = [_XWDisplayRatioLayer new];
68 | _ratioLayer = layer;
69 | _ratioLayer.frame = CGRectMake(0, 0, 100, 100);
70 | __weak typeof(self)weakSelf = self;
71 | _ratioLayer.ratioUpdating = ^(CGFloat ratio){
72 | weakSelf.ratio = ratio;
73 | [weakSelf setNeedsDisplay];
74 | };
75 | [self.layer insertSublayer:_ratioLayer atIndex:0];
76 | self.delegate = self;
77 | return self;
78 | }
79 |
80 | - (CAAnimation *)_xw_filterBasicAnimation{
81 | CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"ratio"];
82 | animation.fromValue = @0;
83 | animation.toValue = @1;
84 | return animation;
85 | }
86 |
87 | - (CIImage *)_xw_filterBasicImageForTransition
88 | {
89 | [_filter setValue:_fromImg forKey:kCIInputImageKey];
90 | [_filter setValue:_toImg forKey:kCIInputTargetImageKey];
91 | [_filter setValue:@(_ratio) forKey:kCIInputTimeKey];
92 | CIImage *transitionImage = [_filter valueForKey:kCIOutputImageKey];
93 | return transitionImage;
94 | }
95 |
96 | - (CIImage *)_xw_filterBlurImageForTransition{
97 | CGFloat radius = 0;
98 | if (_ratio < 0.5) {
99 | [_filter setValue:_fromImg forKey:kCIInputImageKey];
100 | radius = _ratio * 0.5 * 200;
101 | }
102 | else {
103 | [_filter setValue:_toImg forKey:kCIInputImageKey];
104 | radius = (1.0 - _ratio) * 200;
105 | }
106 | [_filter setValue:@(radius) forKey:kCIInputRadiusKey];
107 | CIImage *transitionImage = [_filter valueForKey:kCIOutputImageKey];
108 | return transitionImage;
109 | }
110 | - (void)_xw_filterViewDoAnimation:(NSTimeInterval)duration completion:(void (^ __nullable)(BOOL finished))completion{
111 | _completion = completion;
112 | CAAnimation *animation = [self _xw_filterBasicAnimation];
113 | animation.duration = duration;
114 | animation.delegate = self;
115 | [_ratioLayer addAnimation:animation forKey:@"xw_filterAnimation"];
116 | }
117 |
118 | #pragma mark -
119 |
120 | - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
121 | if (_ratio >= 1 || _ratio <= 0) {
122 | _ratio = _lastRatio > 0.5 ? 1 : 0;
123 | }
124 | if (!_filter) return;
125 | CIImage *image = _blurType ? [self _xw_filterBlurImageForTransition] : [self _xw_filterBasicImageForTransition];
126 | if (!image) return;
127 | CGFloat scale = [[UIScreen mainScreen] scale];
128 | CGRect nativeBounds = [[UIScreen mainScreen] nativeBounds];
129 | CGRect destRect = CGRectMake(0, self.bounds.size.height * scale - _imgRect.size.height,
130 | nativeBounds.size.width,
131 | nativeBounds.size.height);
132 | [_saveContext drawImage:image
133 | inRect:destRect
134 | fromRect:_imgRect];
135 | _lastRatio = _ratio;
136 | }
137 |
138 |
139 | #pragma mark -
140 |
141 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
142 | if (_completion) {
143 | _completion(flag);
144 | }
145 | _completion = nil;
146 | }
147 |
148 | + (void)xw_animationWith:(XWFilterTransitionView *)filterView duration:(NSTimeInterval)duration completion:(void (^ __nullable)(BOOL finished))completion {
149 | [filterView _xw_filterViewDoAnimation:duration completion:completion];
150 | }
151 |
152 | - (CAAnimation *)xw_getInnerAnimation {
153 | return [self _xw_filterBasicAnimation];
154 | }
155 |
156 | - (CIVector *)xw_getInnerVector {
157 | return _vector;
158 | }
159 | @end
160 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWLines.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWVerticalLines.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/14.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWLines.h"
10 |
11 | @implementation XWCoolAnimator (XWLines)
12 |
13 | static inline float XWRandomFloat(float max, float min){
14 | return ((float)arc4random() / 0x100000000) * (max - min) + min;
15 | }
16 |
17 | - (void)xw_setLinesToAnimation:(id)transitionContext vertical:(BOOL)vertical {
18 | [self _xw_animateTransition:transitionContext duration:self.toDuration to:YES vertical:vertical];
19 |
20 | }
21 |
22 | - (void)xw_setLinesBackAnimation:(id)transitionContext vertical:(BOOL)vertical {
23 | [self _xw_animateTransition:transitionContext duration:self.toDuration to:NO vertical:vertical];
24 |
25 | }
26 |
27 |
28 | #define HLINEHEIGHT 4.0
29 | - (void)_xw_animateTransition:(id )transitionContext duration:(NSTimeInterval)duration to:(BOOL)flag vertical:(BOOL)vertical{
30 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
31 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
32 | UIView *toView = toVC.view;
33 | UIView *containerView = [transitionContext containerView];
34 | [containerView insertSubview:toView atIndex:0];
35 | NSArray *outgoingLineViews = [self _xw_lineViews:fromVC.view intoSlicesOfDis:HLINEHEIGHT Offset:fromVC.view.frame.origin.y containerView:containerView vertical:vertical];
36 | NSArray *incomingLineViews = [self _xw_lineViews:toView intoSlicesOfDis:HLINEHEIGHT Offset:toView.frame.origin.y containerView:containerView vertical:vertical];
37 | CGFloat toViewStart = vertical ? toView.frame.origin.y : toView.frame.origin.x;
38 | BOOL presenting = flag;
39 | vertical ? [self _xw_repositionViewSlices:incomingLineViews moveFirstFrameUp:NO]:[self _xw_repositionViewSlices:incomingLineViews moveLeft:!presenting];
40 | fromVC.view.hidden = YES;
41 | toView.hidden = YES;
42 | [UIView animateWithDuration:duration - 0.01 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
43 | vertical ? [self _xw_repositionViewSlices:outgoingLineViews moveFirstFrameUp:YES] : [self _xw_repositionViewSlices:outgoingLineViews moveLeft:presenting];
44 | [self _xw_resetViewSlices:incomingLineViews toOrigin:toViewStart vertical:vertical];
45 | } completion:^(BOOL finished) {
46 | fromVC.view.hidden = NO;
47 | toView.hidden = NO;
48 | [toView setNeedsUpdateConstraints];
49 | for (UIView *v in incomingLineViews) {
50 | [v removeFromSuperview];
51 | }
52 | for (UIView *v in outgoingLineViews) {
53 | [v removeFromSuperview];
54 | }
55 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
56 | }];
57 | }
58 |
59 | - (UIImage *)_xw_ImageFromsnapshotView:(UIView *)view{
60 | CALayer *layer = view.layer;
61 | UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.opaque, 0);
62 | CGContextRef context = UIGraphicsGetCurrentContext();
63 | [layer renderInContext:context];
64 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
65 | UIGraphicsEndImageContext();
66 | return image;
67 | }
68 |
69 | //弃用了原作者的截取若干小图的方法,由于toView刚开始无法截图,原作者采用延迟0.001秒后来截图,但是这种方式不是对手势和转场失败的效果有很大的干扰,所以我转换思路换了一种方式实现了小图,采用的是contentsRect
70 | - (NSArray *)_xw_lineViews:(UIView *)view intoSlicesOfDis:(float)dis Offset:(float)yOffset containerView:(UIView *)containerView vertical:(BOOL)vertical{
71 | CGFloat width = vertical ? CGRectGetHeight(view.frame) : CGRectGetWidth(view.frame);
72 | CGFloat height = !vertical ? CGRectGetHeight(view.frame) : CGRectGetWidth(view.frame);
73 | UIImage *img = [self _xw_ImageFromsnapshotView:view];
74 | NSMutableArray *lineViews = [NSMutableArray array];
75 | for (int i = 0; i < height; i += dis) {
76 | CGRect subrect = vertical ? CGRectMake(i, 0, dis, width) : CGRectMake(0, i, width, dis);
77 | UIView *subsnapshot = [UIView new];
78 | subsnapshot.layer.contents= (__bridge id)img.CGImage;
79 | subsnapshot.layer.contentsRect = vertical ? CGRectMake((float)i / view.frame.size.width, 0.0, dis / view.frame.size.width, 1.0) : CGRectMake(0, (float)i / view.frame.size.height, 1.0, dis / view.frame.size.height);
80 | subrect.origin.x += yOffset;
81 | subsnapshot.frame = subrect;
82 | [lineViews addObject:subsnapshot];
83 | [containerView addSubview:subsnapshot];
84 | }
85 | return lineViews;
86 | }
87 |
88 |
89 | -(void)_xw_repositionViewSlices:(NSArray *)views moveLeft:(BOOL)left{
90 | CGRect frame;
91 | float width;
92 | for (UIView *line in views) {
93 | frame = line.frame;
94 | width = CGRectGetWidth(frame) * XWRandomFloat(1.0, 8.0);
95 | frame.origin.x += (left)?-width:width;
96 | line.frame = frame;
97 | }
98 | }
99 |
100 | -(void)_xw_repositionViewSlices:(NSArray *)views moveFirstFrameUp:(BOOL)startUp{
101 |
102 | BOOL up = startUp;
103 | CGRect frame;
104 | float height;
105 | for (UIView *line in views) {
106 | frame = line.frame;
107 | height = CGRectGetHeight(frame) * XWRandomFloat(1.0, 4.0);
108 | frame.origin.y += (up)?-height:height;
109 | line.frame = frame;
110 |
111 | up = !up;
112 | }
113 | }
114 |
115 | -(void)_xw_resetViewSlices:(NSArray *)views toOrigin:(CGFloat)o vertical:(BOOL)vertical{
116 | CGRect frame;
117 | for (UIView *line in views) {
118 | frame = line.frame;
119 | if (vertical) {
120 | frame.origin.y = o;
121 | }else{
122 | frame.origin.x = o;
123 | }
124 | line.frame = frame;
125 | }
126 | }
127 |
128 | @end
129 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWPortal.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWPortal.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/16.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWPortal.h"
10 | #import "UIView+Snapshot.h"
11 |
12 | @implementation XWCoolAnimator (XWPortal)
13 |
14 |
15 | - (void)xw_setPortalToAnimation:(id)transitionContext {
16 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
17 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
18 | UIView *toView = toVC.view;
19 | UIView *fromView = fromVC.view;
20 | UIView *containerView = [transitionContext containerView];
21 | UIView *toViewSnapshot = [UIView new];
22 | toViewSnapshot.contentImage = toView.snapshotImage;
23 | toViewSnapshot.frame = containerView.bounds;
24 | CATransform3D scale = CATransform3DIdentity;
25 | toViewSnapshot.layer.transform = CATransform3DScale(scale, 0.8, 0.8, 1);
26 | [containerView addSubview:toViewSnapshot];
27 | [containerView sendSubviewToBack:toViewSnapshot];
28 | CGRect leftSnapshotRegion = CGRectMake(0, 0, fromView.frame.size.width / 2, fromView.frame.size.height);
29 | UIView *leftHandView = [UIView new];
30 | leftHandView.contentImage = fromView.snapshotImage;
31 | leftHandView.layer.contentsRect = CGRectMake(0, 0, 0.5, 1.0);
32 | leftHandView.frame = leftSnapshotRegion;
33 | [containerView addSubview:leftHandView];
34 | CGRect rightSnapshotRegion = CGRectMake(fromView.frame.size.width / 2, 0, fromView.frame.size.width / 2, fromView.frame.size.height);
35 | UIView *rightHandView = [UIView new];
36 | rightHandView.contentImage = leftHandView.contentImage;
37 | rightHandView.layer.contentsRect = CGRectMake(0.5, 0, 0.5, 1.0);
38 | rightHandView.frame = rightSnapshotRegion;
39 | [containerView addSubview:rightHandView];
40 | fromView.hidden = YES;
41 | [UIView animateWithDuration:self.toDuration
42 | delay:0.0
43 | options:UIViewAnimationOptionCurveEaseOut
44 | animations:^{
45 | leftHandView.frame = CGRectOffset(leftHandView.frame, - leftHandView.frame.size.width, 0);
46 | rightHandView.frame = CGRectOffset(rightHandView.frame, rightHandView.frame.size.width, 0);
47 | toViewSnapshot.center = toView.center;
48 | toViewSnapshot.frame = toView.frame;
49 | } completion:^(BOOL finished) {
50 | fromView.hidden = NO;
51 | if ([transitionContext transitionWasCancelled]) {
52 | [containerView addSubview:fromView];
53 | [self _xw_removeOtherViews:fromView];
54 | } else {
55 | [containerView addSubview:toView];
56 | [self _xw_removeOtherViews:toView];
57 | }
58 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
59 | }];
60 | }
61 |
62 | - (void)xw_setPortalBackAnimation:(id)transitionContext {
63 |
64 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
65 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
66 | UIView *toView = toVC.view;
67 | UIView *fromView = fromVC.view;
68 | UIView *containerView = [transitionContext containerView];
69 | [containerView addSubview:fromView];
70 | toView.frame = [transitionContext finalFrameForViewController:toVC];
71 | toView.frame = CGRectOffset(toView.frame, toView.frame.size.width, 0);
72 | [containerView addSubview:toView];
73 | CGRect leftSnapshotRegion = CGRectMake(0, 0, toView.frame.size.width / 2, toView.frame.size.height);
74 | UIView *leftHandView = [UIView new];
75 | leftHandView.contentImage = toView.snapshotImage;
76 | leftHandView.layer.contentsRect = CGRectMake(0, 0, 0.5, 1.0);
77 | leftHandView.frame = leftSnapshotRegion;
78 | leftHandView.frame = CGRectOffset(leftHandView.frame, - leftHandView.frame.size.width, 0);
79 | [containerView addSubview:leftHandView];
80 | CGRect rightSnapshotRegion = CGRectMake(toView.frame.size.width / 2, 0, toView.frame.size.width / 2, toView.frame.size.height);
81 | UIView *rightHandView = [UIView new];
82 | rightHandView.contentImage = leftHandView.contentImage;
83 | rightHandView.layer.contentsRect = CGRectMake(0.5, 0, 0.5, 1.0);
84 | rightHandView.frame = rightSnapshotRegion;
85 | rightHandView.frame = CGRectOffset(rightHandView.frame, rightHandView.frame.size.width, 0);
86 | [containerView addSubview:rightHandView];
87 | [UIView animateWithDuration:self.backDuration
88 | delay:0.0
89 | options:UIViewAnimationOptionCurveEaseOut
90 | animations:^{
91 | leftHandView.frame = CGRectOffset(leftHandView.frame, leftHandView.frame.size.width, 0);
92 | rightHandView.frame = CGRectOffset(rightHandView.frame, - rightHandView.frame.size.width, 0);
93 | CATransform3D scale = CATransform3DIdentity;
94 | fromView.layer.transform = CATransform3DScale(scale, 0.8, 0.8, 1);
95 | } completion:^(BOOL finished) {
96 | if ([transitionContext transitionWasCancelled]) {
97 | [self _xw_removeOtherViews:fromView];
98 | } else {
99 | [self _xw_removeOtherViews:toView];
100 | toView.frame = containerView.bounds;
101 | }
102 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
103 | }];
104 | }
105 |
106 | - (void)_xw_removeOtherViews:(UIView*)viewToKeep {
107 | UIView *containerView = viewToKeep.superview;
108 | for (UIView *view in containerView.subviews) {
109 | if (view != viewToKeep) {
110 | [view removeFromSuperview];
111 | }
112 | }
113 | }
114 | @end
115 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XWTransition
2 |
3 | ###是什么
4 | XWTransition是用来帮助你快速集成自定义转场的工具,使用它你无需关注转场的逻辑和长长的delegate方法,只需要选择相应效果的转场效果器,然后几乎就像以前的push和present操作一样进行转场工作,当然你也可以很简单自定义自己的效果器完成你独特的转场创意而无需关注转场逻辑,你只需要专心关注你的动画逻辑即可,其它的东西都已经为你处理好了
5 |
6 | ###效果图(可下载demo真机运行效果更好)
7 | 截图中,左上角的开关代表push和present,所有效果都支持手势,我就不一一演示了
8 |
9 | 1、CircleSpreadTransition 小圆点扩散
10 |
11 | 
12 |
13 | 2、MagicMoveTransition 神奇移动
14 |
15 |
16 | 
17 | 
18 |
19 | 3、XWDrawerAnimator 抽屉效果,仿照QQ和淘宝
20 |
21 | 
22 | 
23 |
24 | 4、XWCoolAnimator 自定义一些效果
25 |
26 | 
27 | 
28 | 
29 | 
30 | 
31 | 
32 | 
33 |
34 | 5、XWFilterAnimator 通过CIFilter滤镜自定义一些效果,请在真机上运行
35 |
36 | 
37 | 
38 | 
39 | 
40 | 
41 | 
42 | 
43 | 
44 |
45 | ###基本使用
46 |
47 | 1、clone后将XWTranstion文件夹导入工程
48 |
49 | 2、导入`UINavigationController+XWTransition.h`或者`UIViewController+XWTransition.h`两个分类
50 |
51 | 3、选择你需要的效果器进行根据初始化方法进行初始化,比如下面的小圆点扩散,初始化指定开始圆心和半径
52 |
53 | ```
54 | XWCircleSpreadAnimator *animator = [XWCircleSpreadAnimator xw_animatorWithStartCenter:self.button.center radius:20];
55 |
56 | ```
57 |
58 | 4、通过初始化的效果器转场,根据分类提供两个方法进行push或者present,就完成了!
59 |
60 | ```
61 | /**
62 | * 通过指定的转场animator来push控制器,达到不同的转场效果
63 | *
64 | * @param viewController 被push的控制器
65 | * @param animator 转场Animator
66 | */
67 | - (void)xw_pushViewController:(UIViewController *)viewController withAnimator:(XWTransitionAnimator *)animator;
68 |
69 | /**
70 | * 通过指定的转场animator来present控制器
71 | *
72 | * @param viewController 被modal出的控制器
73 | * @param animator 转场animator
74 | */
75 | - (void)xw_presentViewController:(UIViewController *)viewController withAnimator:(XWTransitionAnimator *)animator;
76 |
77 | //事例代码如下
78 | [self.navigationController xw_pushViewController:toVC withAnimator:animator];
79 | 或者
80 | [self xw_presentViewController:toVC withAnimator:animator];
81 |
82 | ```
83 |
84 | ###手势驱动(所有的效果都支持手势驱动)
85 | 1、在`UIViewController+XWTransition.h`分类中提供了两个方法,用来注册手势驱动,在viewDidLoad的时候调用注册手势就可以了,详见demo,注意避免循环引用,手势支持边缘属性
86 |
87 | ```
88 | /**
89 | * 注册to手势(push或者Present手势)
90 | *
91 | * @param direction 手势方向
92 | * @param tansitionConfig 手势触发的block,block中需要包含你的push或者Present的逻辑代码,注意避免循环引用问题
93 | * @param edgeSpacing 手势触发的边缘距离,该值为0,表示在整个控制器视图上都有效,否者这在边缘的edgeSpacing之类有效
94 | */
95 |
96 | - (void)xw_registerToInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(dispatch_block_t)tansitionConfig edgeSpacing:(CGFloat)edgeSpacing;
97 |
98 | /**
99 | * 注册back手势(pop或者dismiss手势)
100 | *
101 | * @param direction 手势方向
102 | * @param tansitionConfig 手势触发的block,block中需要包含你的pop或者dismiss的逻辑代码,注意避免循环引用问题
103 | * @param edgeSpacing 手势触发的边缘距离,该值为0,表示在整个控制器视图上都有效,否者这在边缘的edgeSpacing之类有效
104 | */
105 |
106 | - (void)xw_registerBackInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction transitonBlock:(dispatch_block_t)tansitionConfig edgeSpacing:(CGFloat)edgeSpacing;
107 |
108 | ```
109 |
110 | 2、事例代码
111 |
112 | ```
113 | __weak typeof(self)weakSelf = self;
114 | //注册一个全屏的back转场
115 | [self xw_registerBackInteractiveTransitionWithDirection:XWInteractiveTransitionGestureDirectionDown transitonBlock:^{
116 | //pop或者dismiss操作
117 | [weakSelf xw_transiton];
118 | } edgeSpacing:0];
119 |
120 | ```
121 |
122 |
123 | ###关于自定义转场效果
124 | 你只需要继承于`XWTransitionAnimator`,就像内置实现的所有效果器一样,然后复写需要的属性和两个必须的方法即可,然后你就可以使用你自定义的效果器转场,`XWTransitionAnimator`头文件如下:
125 |
126 | ```
127 | @interface XWTransitionAnimator : NSObject
128 |
129 | //to转场时间 默认0.5
130 | @property (nonatomic, assign) NSTimeInterval toDuration;
131 | //back转场时间 默认0.5
132 | @property (nonatomic, assign) NSTimeInterval backDuration;
133 | //是否需要开启手势timer,某些转场如果在转成过程中所开手指,不会有动画过渡,显得很生硬,开启timer后,松开手指,会用timer不断的刷新转场百分比,消除生硬的缺点
134 | @property (nonatomic, assign) BOOL needInteractiveTimer;
135 |
136 | /**
137 | * 配置To过程动画(push, present),自定义转场动画应该复写该方法
138 | */
139 | - (void)xw_setToAnimation:(id)transitionContext;
140 | /**
141 | * 配置back过程动画(pop, dismiss),自定义转场动画应该复写该方法
142 | */
143 | - (void)xw_setBackAnimation:(id)transitionContext;
144 |
145 | @end
146 | ```
147 |
148 | ####更多原理和使用细节请前往我的简书博客:[几句代码快速集成自定义转场效果+ 全手势驱动](http://www.jianshu.com/p/e498b956491c)
149 |
150 |
151 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator.h"
10 | #import "XWCoolAnimator+XWPortal.h"
11 | #import "XWCoolAnimator+XWPageFlip.h"
12 | #import "XWCoolAnimator+XWFold.h"
13 | #import "XWCoolAnimator+XWMiddlePageFlip.h"
14 | #import "XWCoolAnimator+XWExplode.h"
15 | #import "XWCoolAnimator+XWLines.h"
16 | #import "XWCoolAnimator+XWScanning.h"
17 |
18 | @interface XWCoolAnimator ()
19 | @property (nonatomic, weak) UIView *pageFlipTempView;
20 | @end
21 |
22 | @implementation XWCoolAnimator{
23 | XWCoolTransitionAnimatorType _type;
24 | }
25 |
26 | - (void)dealloc{
27 | NSLog(@"coolAnimator销毁了");
28 | }
29 |
30 |
31 | + (instancetype)xw_animatorWithType:(XWCoolTransitionAnimatorType)type {
32 | return [[self alloc] _initWithTransitionType:type];
33 | }
34 |
35 | - (instancetype)_initWithTransitionType:(XWCoolTransitionAnimatorType)type{
36 | self = [super init];
37 | if (self) {
38 | _type = type;
39 | _foldCount = 4;
40 | }
41 | return self;
42 | }
43 |
44 |
45 |
46 | - (void)xw_setToAnimation:(id)transitionContext{
47 | switch (_type) {
48 | case XWCoolTransitionAnimatorTypePageFlip: {
49 | [self xw_setPageFlipToAnimation:transitionContext];
50 | break;
51 | }
52 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromLeft: {
53 | [self xw_setMiddlePageFlipToAnimation:transitionContext direction:XWMiddlePageFlipDirectionLeft];
54 | break;
55 | }
56 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromRight: {
57 | [self xw_setMiddlePageFlipToAnimation:transitionContext direction:XWMiddlePageFlipDirectionRight];
58 | break;
59 | }
60 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromTop: {
61 | [self xw_setMiddlePageFlipToAnimation:transitionContext direction:XWMiddlePageFlipDirectionTop];
62 | break;
63 | }
64 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromBottom: {
65 | [self xw_setMiddlePageFlipToAnimation:transitionContext direction:XWMiddlePageFlipDirectionBottom];
66 | break;
67 | }
68 | case XWCoolTransitionAnimatorTypePortal: {
69 | [self xw_setPortalToAnimation:transitionContext];
70 | break;
71 | }
72 | case XWCoolTransitionAnimatorTypeFoldFromLeft: {
73 | [self xw_setFoldToAnimation:transitionContext leftFlag:YES];
74 | break;
75 | }
76 | case XWCoolTransitionAnimatorTypeFoldFromRight: {
77 | [self xw_setFoldToAnimation:transitionContext leftFlag:NO];
78 | break;
79 | }
80 | case XWCoolTransitionAnimatorTypeExplode: {
81 | [self xw_setExplodeToAnimation:transitionContext];
82 | break;
83 | }
84 | case XWCoolTransitionAnimatorTypeHorizontalLines: {
85 | [self xw_setLinesToAnimation:transitionContext vertical:NO];
86 | break;
87 | }
88 | case XWCoolTransitionAnimatorTypeVerticalLines: {
89 | [self xw_setLinesToAnimation:transitionContext vertical:YES];
90 | break;
91 | }
92 | case XWCoolTransitionAnimatorTypeScanningFromLeft: {
93 | [self xw_setScanningToAnimation:transitionContext direction:0];
94 | break;
95 | }
96 | case XWCoolTransitionAnimatorTypeScanningFromRight: {
97 | [self xw_setScanningToAnimation:transitionContext direction:1];
98 | break;
99 | }
100 | case XWCoolTransitionAnimatorTypeScanningFromTop: {
101 | [self xw_setScanningToAnimation:transitionContext direction:2];
102 | break;
103 | }
104 | case XWCoolTransitionAnimatorTypeScanningFromBottom: {
105 | [self xw_setScanningToAnimation:transitionContext direction:3];
106 | break;
107 | }
108 | }
109 | }
110 |
111 | - (void)xw_setBackAnimation:(id)transitionContext{
112 | switch (_type) {
113 | case XWCoolTransitionAnimatorTypePageFlip: {
114 | [self xw_setPageFlipBackAnimation:transitionContext];
115 | break;
116 | }
117 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromLeft: {
118 | [self xw_setMiddlePageFlipBackAnimation:transitionContext direction:XWMiddlePageFlipDirectionRight];
119 | break;
120 | }
121 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromRight: {
122 | [self xw_setMiddlePageFlipBackAnimation:transitionContext direction:XWMiddlePageFlipDirectionLeft];
123 | break;
124 | }
125 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromTop: {
126 | [self xw_setMiddlePageFlipBackAnimation:transitionContext direction:XWMiddlePageFlipDirectionBottom];
127 | break;
128 | }
129 | case XWCoolTransitionAnimatorTypePageMiddleFlipFromBottom: {
130 | [self xw_setMiddlePageFlipBackAnimation:transitionContext direction:XWMiddlePageFlipDirectionTop];
131 | break;
132 | }
133 | case XWCoolTransitionAnimatorTypePortal: {
134 | [self xw_setPortalBackAnimation:transitionContext];
135 | break;
136 | }
137 | case XWCoolTransitionAnimatorTypeFoldFromLeft: {
138 | [self xw_setFoldBackAnimation:transitionContext leftFlag:NO];
139 | break;
140 | }
141 | case XWCoolTransitionAnimatorTypeFoldFromRight: {
142 | [self xw_setFoldBackAnimation:transitionContext leftFlag:YES];
143 | break;
144 | }
145 | case XWCoolTransitionAnimatorTypeExplode: {
146 | [self xw_setExplodeBackAnimation:transitionContext];
147 | break;
148 | }
149 | case XWCoolTransitionAnimatorTypeHorizontalLines: {
150 | [self xw_setLinesBackAnimation:transitionContext vertical:NO];
151 | break;
152 | }
153 | case XWCoolTransitionAnimatorTypeVerticalLines: {
154 | [self xw_setLinesBackAnimation:transitionContext vertical:YES];
155 | break;
156 | }
157 | case XWCoolTransitionAnimatorTypeScanningFromLeft: {
158 | [self xw_setScanningBackAnimation:transitionContext direction:1];
159 | break;
160 | }
161 | case XWCoolTransitionAnimatorTypeScanningFromRight: {
162 | [self xw_setScanningBackAnimation:transitionContext direction:0];
163 | break;
164 | }
165 | case XWCoolTransitionAnimatorTypeScanningFromTop: {
166 | [self xw_setScanningBackAnimation:transitionContext direction:3];
167 | break;
168 | }
169 | case XWCoolTransitionAnimatorTypeScanningFromBottom: {
170 | [self xw_setScanningBackAnimation:transitionContext direction:2];
171 | break;
172 | }
173 | }
174 | }
175 |
176 |
177 |
178 |
179 |
180 | @end
181 |
--------------------------------------------------------------------------------
/XWTransition/XWFilterAnimator/XWFilterAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWFilterAnimator.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/17.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWFilterAnimator.h"
10 | #import "XWFilterAnimator+XWBoxBlur.h"
11 | #import "XWFilterAnimator+XWSwipe.h"
12 | #import "XWFilterAnimator+XWBarSwipe.h"
13 | #import "XWFilterAnimator+XWMask.h"
14 | #import "XWFilterAnimator+XWFlash.h"
15 | #import "XWFilterAnimator+XWMod.h"
16 | #import "XWFilterAnimator+XWPageCurl.h"
17 | #import "XWFilterAnimator+XWRipple.h"
18 | #import "XWFilterAnimator+XWCopyMachine.h"
19 |
20 | @implementation XWFilterAnimator{
21 | UIView *_containerView;
22 | XWFilterAnimatorType _type;
23 | }
24 |
25 |
26 |
27 | + (instancetype)xw_animatorWithType:(XWFilterAnimatorType)type {
28 | return[[self alloc] _initWithType:type];
29 | }
30 |
31 | - (instancetype)_initWithType:(XWFilterAnimatorType)type{
32 | self = [super init];
33 | if (self) {
34 | _type = type;
35 | self.needInteractiveTimer = YES;
36 | _revers = YES;
37 | }
38 | return self;
39 | }
40 |
41 | - (void)xw_setToAnimation:(id)transitionContext{
42 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
43 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
44 | UIView *containerView = [transitionContext containerView];
45 | _containerView = containerView;
46 | [containerView addSubview:toVC.view];
47 | XWFilterTransitionView *filterView = [[XWFilterTransitionView alloc] initWithFrame:containerView.bounds fromImage:[self xw_ImageFromsnapshotView:fromVC.view] toImage:[self xw_ImageFromsnapshotView:toVC.view]];
48 | switch (_type) {
49 | case XWFilterAnimatorTypeBoxBlur: {
50 | [self xw_boxBlurAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration];
51 | break;
52 | }
53 | case XWFilterAnimatorTypeSwipe: {
54 | [self xw_swipeAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration toFlag:YES];
55 | break;
56 | }
57 | case XWFilterAnimatorTypeBarSwipe:{
58 | [self xw_barSwipeAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration toFlag:YES];
59 | break;
60 | }
61 | case XWFilterAnimatorTypeMask:{
62 | [self xw_maskAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration];
63 | break;
64 | }
65 | case XWFilterAnimatorTypeFlash:{
66 | [self xw_flashAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration];
67 | break;
68 | }
69 | case XWFilterAnimatorTypeMod:{
70 | [self xw_modAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration toFlag:YES];
71 | break;
72 | }
73 | case XWFilterAnimatorTypePageCurl:{
74 | [self xw_pageCurlAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration toFlag:YES];
75 | break;
76 | }
77 | case XWFilterAnimatorTypeRipple:{
78 | [self xw_rippleAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration];
79 | break;
80 | }
81 | case XWFilterAnimatorTypeCopyMachine:{
82 | [self xw_copyMachineAnimationFor:filterView transitionContext:transitionContext duration:self.toDuration toFlag:YES];
83 | break;
84 | }
85 | }
86 | [containerView addSubview:filterView];
87 | }
88 |
89 | - (void)xw_setBackAnimation:(id)transitionContext{
90 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
91 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
92 | UIView *containerView = [transitionContext containerView];
93 | [containerView insertSubview:toVC.view atIndex:0];
94 | _containerView = containerView;
95 | XWFilterTransitionView *filterView = [[XWFilterTransitionView alloc] initWithFrame:containerView.bounds fromImage:[self xw_ImageFromsnapshotView:fromVC.view] toImage:[self xw_ImageFromsnapshotView:toVC.view]];
96 | switch (_type) {
97 | case XWFilterAnimatorTypeBoxBlur: {
98 | [self xw_boxBlurAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration];
99 | break;
100 | }
101 | case XWFilterAnimatorTypeSwipe: {
102 | [self xw_swipeAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration toFlag:NO];
103 | break;
104 | }
105 | case XWFilterAnimatorTypeBarSwipe:{
106 | [self xw_barSwipeAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration toFlag:NO];
107 | break;
108 | }
109 | case XWFilterAnimatorTypeMask:{
110 | [self xw_maskAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration];
111 | break;
112 | }
113 | case XWFilterAnimatorTypeFlash:{
114 | [self xw_flashAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration];
115 | break;
116 | }
117 | case XWFilterAnimatorTypeMod:{
118 | [self xw_modAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration toFlag:NO];
119 | break;
120 | }
121 | case XWFilterAnimatorTypePageCurl:{
122 | [self xw_pageCurlAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration toFlag:NO];
123 | break;
124 | }
125 | case XWFilterAnimatorTypeRipple:{
126 | [self xw_rippleAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration];
127 | break;
128 | }
129 | case XWFilterAnimatorTypeCopyMachine:{
130 | [self xw_copyMachineAnimationFor:filterView transitionContext:transitionContext duration:self.backDuration toFlag:NO];
131 | break;
132 | }
133 | }
134 | [containerView addSubview:filterView];
135 | }
136 |
137 | - (UIImage *)xw_ImageFromsnapshotView:(UIView *)view{
138 | CALayer *layer = view.layer;
139 | UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.opaque, 0);
140 | CGContextRef context = UIGraphicsGetCurrentContext();
141 | [layer renderInContext:context];
142 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
143 | UIGraphicsEndImageContext();
144 | return image;
145 | }
146 |
147 | - (void)xw_interactiveTransitionWillBeginTimerAnimation:(XWInteractiveTransition *)interactiveTransition{
148 | _containerView.userInteractionEnabled = NO;
149 | }
150 |
151 | - (void)xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition willEndWithSuccessFlag:(BOOL)flag percent:(CGFloat)percent{
152 | _containerView.userInteractionEnabled = YES;
153 | }
154 |
155 | @end
156 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWFold.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWFold.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWFold.h"
10 | #import "UIView+Snapshot.h"
11 |
12 | @implementation XWCoolAnimator (XWFold)
13 |
14 | - (void)xw_setFoldToAnimation:(id)transitionContext leftFlag:(BOOL)left {
15 | [self _xw_animation:transitionContext flag:left duration:self.toDuration];
16 |
17 | }
18 |
19 | - (void)xw_setFoldBackAnimation:(id)transitionContext leftFlag:(BOOL)left {
20 | [self _xw_animation:transitionContext flag:left duration:self.backDuration];
21 |
22 | }
23 |
24 | - (void)_xw_animation:(id)transitionContext flag:(BOOL)flag duration:(NSTimeInterval)duration{
25 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
26 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
27 | UIView *toView = toVC.view;
28 | UIView *fromView = fromVC.view;
29 | UIView *containerView = [transitionContext containerView];
30 | toView.frame = [transitionContext finalFrameForViewController:toVC];
31 | toView.frame = CGRectOffset(toView.frame, toView.frame.size.width, 0);
32 | [containerView addSubview:toView];
33 | CATransform3D transform = CATransform3DIdentity;
34 | transform.m34 = -0.005;
35 | containerView.layer.sublayerTransform = transform;
36 | CGSize size = toView.frame.size;
37 | float foldWidth = size.width * 0.5 / (float)self.foldCount ;
38 | NSMutableArray* fromViewFolds = [NSMutableArray new];
39 | NSMutableArray* toViewFolds = [NSMutableArray new];
40 | UIImage *fromImage = fromView.snapshotImage;
41 | UIImage *toImage = toView.snapshotImage;
42 | for (int i=0 ;i
11 |
12 | static NSString *const kXWMagicMovePropertyInViewKey = @"kXWMagicMovePropertyInViewKey";
13 |
14 | @implementation UIView (XWTransition)
15 |
16 | - (void)setMagicMoveImageMode:(BOOL)magicMoveImageMode{
17 | objc_setAssociatedObject(self, &kXWMagicMovePropertyInViewKey, @(magicMoveImageMode), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
18 | }
19 |
20 | - (BOOL)magicMoveImageMode{
21 | return [objc_getAssociatedObject(self, &kXWMagicMovePropertyInViewKey) boolValue];
22 | }
23 |
24 |
25 | @end
26 |
27 | @implementation XWMagicMoveAnimator
28 |
29 | - (void)xw_setToAnimation:(id)transitionContext{
30 | [self _xw_doAniamtionWithContext:transitionContext fromFlag:YES];
31 |
32 | }
33 |
34 | - (void)xw_setBackAnimation:(id)transitionContext{
35 | [self _xw_doAniamtionWithContext:transitionContext fromFlag:NO];
36 |
37 | }
38 |
39 | -(void)_xw_doAniamtionWithContext:(id)transitionContext fromFlag:(BOOL)flag{
40 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
41 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
42 | UIViewController *realFromVC = [self _xw_getRealContainsGroupViewController:fromVC];
43 | UIViewController *realToVC = [self _xw_getRealContainsGroupViewController:toVC];
44 | NSArray *startViewGroup = objc_getAssociatedObject(realFromVC, flag ? &kXWMagicMoveAnimatorStartViewVCKey : &kXWMagicMoveAnimatorEndViewVCKey);
45 | NSArray *endViewGroup = objc_getAssociatedObject(realToVC, !flag ? &kXWMagicMoveAnimatorStartViewVCKey : &kXWMagicMoveAnimatorEndViewVCKey);
46 | if (!startViewGroup.count || !endViewGroup.count || startViewGroup.count != endViewGroup.count) {
47 | NSLog(@"神奇移动的视图为空,或者移动前后视图不相等");
48 | [transitionContext completeTransition:NO];
49 | return;
50 | }
51 | UIView *containerView = [transitionContext containerView];
52 | toVC.view.alpha = 0.0f;
53 | [containerView addSubview:toVC.view];
54 | NSArray *toRects = [self _xw_getFrameValueFromViewGroup:endViewGroup inContainerView:containerView];
55 | NSArray *tempViewGroup = [self _xw_makeTempViewGroupWithViewGroup:startViewGroup inContainerView:containerView];
56 | [self _xw_changeHiddenViewInGroup:startViewGroup hidden:YES];
57 | [self _xw_changeHiddenViewInGroup:endViewGroup hidden:YES];
58 | if (self.dampingEnable) {
59 | [UIView animateWithDuration:flag ? self.toDuration : self.backDuration delay:0.0f usingSpringWithDamping:0.55 initialSpringVelocity:1 / 0.55 options:UIViewAnimationOptionCurveLinear animations:^{
60 | fromVC.view.alpha = 0.0f;
61 | toVC.view.alpha = 1.0f;
62 | [tempViewGroup enumerateObjectsUsingBlock:^(UIView *tempSubView, NSUInteger idx, BOOL * _Nonnull stop) {
63 | CGRect toRect = [toRects[idx] CGRectValue];
64 | tempSubView.frame = toRect;
65 | }];
66 |
67 | } completion:^(BOOL finished) {
68 | [tempViewGroup makeObjectsPerformSelector:@selector(removeFromSuperview)];
69 | fromVC.view.alpha = 1.0f;
70 | [self _xw_changeHiddenViewInGroup:startViewGroup hidden:NO];
71 | [self _xw_changeHiddenViewInGroup:endViewGroup hidden:NO];
72 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
73 |
74 | }];
75 | }else{
76 | [UIView animateWithDuration:flag ? self.toDuration : self.backDuration animations:^{
77 | fromVC.view.alpha = 0.0f;
78 | toVC.view.alpha = 1.0f;
79 | [tempViewGroup enumerateObjectsUsingBlock:^(UIView *tempSubView, NSUInteger idx, BOOL * _Nonnull stop) {
80 | CGRect toRect = [toRects[idx] CGRectValue];
81 | tempSubView.frame = toRect;
82 | }];
83 | } completion:^(BOOL finished) {
84 | [tempViewGroup makeObjectsPerformSelector:@selector(removeFromSuperview)];
85 | fromVC.view.alpha = 1.0f;
86 | [self _xw_changeHiddenViewInGroup:startViewGroup hidden:NO];
87 | [self _xw_changeHiddenViewInGroup:endViewGroup hidden:NO];
88 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
89 | }];
90 | }
91 | }
92 |
93 | /**
94 | * 判断当前控制器的类型,从而找到从出存有移动视图组的控制器
95 | */
96 | - (UIViewController *)_xw_getRealContainsGroupViewController:(UIViewController *)controller{
97 | UIViewController *realVC = controller;
98 | if ([controller isKindOfClass:[UITabBarController class]]) {
99 | UITabBarController *tabBarVC = (UITabBarController *)realVC;
100 | if ([tabBarVC.selectedViewController isKindOfClass:[UINavigationController class]]) {
101 | UINavigationController *navVC = (UINavigationController *)tabBarVC.selectedViewController;
102 | realVC = navVC.topViewController;
103 | }else{
104 | realVC = tabBarVC.selectedViewController;
105 | }
106 | }
107 | if ([controller isKindOfClass:[UINavigationController class]]) {
108 | UINavigationController *navVC = (UINavigationController *)controller;
109 | realVC = navVC.topViewController;
110 | }
111 | return realVC;
112 | }
113 |
114 |
115 | - (NSArray *)_xw_getFrameValueFromViewGroup:(NSArray *)group inContainerView:(UIView *)containerView{
116 | NSMutableArray *temp = @[].mutableCopy;
117 | [group enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL * _Nonnull stop) {
118 | CGRect rect = [view convertRect:view.bounds toView:containerView];
119 | [temp addObject:[NSValue valueWithCGRect:rect]];
120 | }];
121 | return temp.copy;
122 | }
123 |
124 | - (NSArray *)_xw_makeTempViewGroupWithViewGroup:(NSArray *)group inContainerView:(UIView *)containerView{
125 | NSMutableArray *temp = @[].mutableCopy;
126 | [group enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL * _Nonnull stop) {
127 | UIView *tempView = [self _xw_snapshotView:view];
128 | tempView.frame = [view convertRect:view.bounds toView:containerView];
129 | [containerView addSubview:tempView];
130 | [temp addObject:tempView];
131 | }];
132 | return temp.copy;
133 | }
134 |
135 | - (void)_xw_changeHiddenViewInGroup:(NSArray *)group hidden:(BOOL)flag{
136 | [group enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
137 | obj.hidden = flag;
138 | }];
139 | }
140 |
141 | - (UIView *)_xw_snapshotView:(UIView *)view{
142 | CALayer *layer = view.layer;
143 | UIView *snapView = [UIView new];
144 | snapView.frame = view.frame;
145 | BOOL imgMode = [objc_getAssociatedObject(view, &kXWMagicMovePropertyInViewKey) boolValue] || _imageMode;
146 | UIImage *img = nil;
147 | if (imgMode) {//如果开启imgMode,优先直接获取图片,避免截图时时从小到大造成的模糊
148 | if ([view isKindOfClass:[UIImageView class]]) {//取imageView中的image
149 | img = [(UIImageView *)view image];
150 | }else if ([view isKindOfClass:[UIButton class]]){//取button中的image
151 | img = [(UIButton *)view currentImage];
152 | }
153 | if (!img && [view isKindOfClass:[UIView class]]) {//没取到尝试取content
154 | img = [UIImage imageWithCGImage:(__bridge CGImageRef)view.layer.contents];
155 | }
156 | }
157 | //若都没有取到,则截图
158 | if (!img) {
159 | UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.opaque, 0);
160 | CGContextRef context = UIGraphicsGetCurrentContext();
161 | [layer renderInContext:context];
162 | img = UIGraphicsGetImageFromCurrentImageContext();
163 | UIGraphicsEndImageContext();
164 | }
165 | snapView.layer.contents = (__bridge id)img.CGImage;
166 | return snapView;
167 | }
168 |
169 |
170 | @end
171 |
172 | NSString *const kXWMagicMoveAnimatorStartViewVCKey = @"kXWMagicMoveAnimatorStartViewVCKey";
173 | NSString *const kXWMagicMoveAnimatorEndViewVCKey = @"kXWMagicMoveAnimatorEndViewVCKey";
174 |
--------------------------------------------------------------------------------
/XWTransition/Main/XWInteractiveTransition.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWInteractiveTransition.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/10.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWInteractiveTransition.h"
10 | #import
11 |
12 | typedef struct {
13 | unsigned int willBegin : 1;
14 | unsigned int isUpdating : 1;
15 | unsigned int willBeginTimer : 1;
16 | unsigned int willEnd : 1;
17 | } delegateFlag;
18 |
19 | @interface XWInteractiveTransition ()
20 | @property (nonatomic, assign) XWInteractiveTransitionGestureDirection direction;
21 | @property (nonatomic, copy) void(^config)(CGPoint startPoint);
22 | @property (nonatomic, strong) CADisplayLink *timer;
23 | @property (nonatomic, assign) CGFloat percent;
24 | @property (nonatomic, assign) CGFloat timeDis;
25 | @property (nonatomic, assign) delegateFlag delegateFlag;
26 | @property (nonatomic, assign) BOOL vertical;
27 | @property (nonatomic, assign) CGFloat edgeSpacing;
28 |
29 |
30 | @end
31 |
32 | @implementation XWInteractiveTransition
33 |
34 | + (instancetype)xw_interactiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction config:(void(^)(CGPoint startPoint))config edgeSpacing:(CGFloat)edgeSpacing{
35 | return [[self alloc] _initInteractiveTransitionWithDirection:direction config:config edgeSpacing:edgeSpacing];
36 | }
37 |
38 | - (instancetype)_initInteractiveTransitionWithDirection:(XWInteractiveTransitionGestureDirection)direction config:(void(^)(CGPoint startPoint))config edgeSpacing:(CGFloat)edgeSpacing{
39 | self = [super init];
40 | if (self) {
41 | _config = config;
42 | _direction = direction;
43 | _edgeSpacing = edgeSpacing;
44 | _vertical = direction == XWInteractiveTransitionGestureDirectionDown || direction == XWInteractiveTransitionGestureDirectionUp;
45 | }
46 | return self;
47 | }
48 |
49 | - (void)setDelegate:(id)delegate{
50 | _delegate = delegate;
51 | _delegateFlag.willBegin = _delegate && [_delegate respondsToSelector:@selector(xw_interactiveTransitionWillBegin:)];
52 | _delegateFlag.isUpdating = _delegate && [_delegate respondsToSelector:@selector(xw_interactiveTransition:isUpdating:)];
53 | _delegateFlag.willBeginTimer = _delegate && [_delegate respondsToSelector:@selector(xw_interactiveTransitionWillBeginTimerAnimation:)];
54 | _delegateFlag.willEnd = _delegate && [_delegate respondsToSelector:@selector(xw_interactiveTransition:willEndWithSuccessFlag:percent:)];
55 | }
56 |
57 | - (void)xw_addPanGestureForView:(UIView *)view to:(BOOL)flag{
58 | UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_xw_handleGesture:)];
59 | //为drawerAnimator记录pan手势
60 | pan.delegate = self;
61 | NSString * panType = flag ? @"xw_interactiveToPan" : @"xw_interactiveBackPan";
62 | objc_setAssociatedObject(pan, "xw_interactivePanKey", panType, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
63 | [view addGestureRecognizer:pan];
64 | }
65 |
66 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
67 | if (_edgeSpacing <= 0) {
68 | return YES;
69 | }
70 | CGPoint point = [gestureRecognizer locationInView:gestureRecognizer.view];
71 | BOOL should = NO;
72 | switch (_direction) {
73 | case XWInteractiveTransitionGestureDirectionLeft: {
74 | should = point.x >= gestureRecognizer.view.frame.size.width - _edgeSpacing;
75 | break;
76 | }
77 | case XWInteractiveTransitionGestureDirectionRight: {
78 | should = point.x <= _edgeSpacing;
79 | break;
80 | }
81 | case XWInteractiveTransitionGestureDirectionUp: {
82 | should = point.y >= gestureRecognizer.view.frame.size.height - _edgeSpacing;
83 | break;
84 | }
85 | case XWInteractiveTransitionGestureDirectionDown: {
86 | should = point.y <= _edgeSpacing;
87 | break;
88 | }
89 | }
90 | return should;
91 | }
92 |
93 | /**
94 | * 手势过渡的过程
95 | */
96 | - (void)_xw_handleGesture:(UIPanGestureRecognizer *)panGesture{
97 | switch (panGesture.state) {
98 | case UIGestureRecognizerStateBegan:
99 | if (_delegateFlag.willBegin) {
100 | [_delegate xw_interactiveTransitionWillBegin:self];
101 | }
102 | CGPoint startPoint = [panGesture locationInView:panGesture.view];
103 | _interation = YES;
104 | if (_config) {
105 | _config(startPoint);
106 | }
107 | [self _xw_caculateMovePercentForGesture:panGesture];
108 | break;
109 | case UIGestureRecognizerStateChanged:{
110 | [self _xw_caculateMovePercentForGesture:panGesture];
111 | [self _xw_updatingWithPercent:_percent];
112 | break;
113 | }
114 | case UIGestureRecognizerStateEnded:{
115 | //判断是否需要timer
116 | if (!_timerEable) {
117 | _percent >= 0.5 ? [self _xw_finish] : [self _xw_cancle];
118 | return;
119 | }
120 | //判断此时是否已经转场完成,大于1或者小于0
121 | BOOL canEnd = [self _xw_canEndInteractiveTransitionWithPercent:_percent];
122 | if (canEnd) return;
123 | //开启timer
124 | [self _xw_setEndAnimationTimerWithPercent:_percent];
125 | break;
126 | }
127 | default:
128 | break;
129 | }
130 | }
131 |
132 | - (BOOL)_xw_canEndInteractiveTransitionWithPercent:(CGFloat)percent{
133 | BOOL can = NO;
134 | if (percent >= 1) {
135 | [self _xw_finish];
136 | can = YES;
137 | }
138 | if (percent <= 0) {
139 | [self _xw_cancle];
140 | can = YES;
141 | }
142 | return can;
143 | }
144 |
145 | - (void)_xw_caculateMovePercentForGesture:(UIPanGestureRecognizer *)panGesture{
146 | static CGFloat baseValue = 0.0f;
147 | baseValue = _panRatioBaseValue > 0 ? _panRatioBaseValue : _vertical ? panGesture.view.frame.size.height : panGesture.view.frame.size.width;
148 | //手势百分比
149 | switch (_direction) {
150 | case XWInteractiveTransitionGestureDirectionLeft:{
151 | CGFloat transitionX = -[panGesture translationInView:panGesture.view].x;
152 | _percent += transitionX / baseValue;
153 | }
154 | break;
155 | case XWInteractiveTransitionGestureDirectionRight:{
156 | CGFloat transitionX = [panGesture translationInView:panGesture.view].x;
157 | _percent += transitionX / baseValue;
158 | }
159 | break;
160 | case XWInteractiveTransitionGestureDirectionUp:{
161 | CGFloat transitionY = -[panGesture translationInView:panGesture.view].y;
162 | _percent += transitionY / baseValue;
163 | }
164 | break;
165 | case XWInteractiveTransitionGestureDirectionDown:{
166 | CGFloat transitionY = [panGesture translationInView:panGesture.view].y;
167 | _percent += transitionY / baseValue;
168 | }
169 | break;
170 | }
171 | [panGesture setTranslation:CGPointZero inView:panGesture.view];
172 | }
173 |
174 | //设置开启timer
175 | - (void)_xw_setEndAnimationTimerWithPercent:(CGFloat)percent{
176 | _percent = percent;
177 | //根据失败还是成功设置刷新间隔
178 | if (percent > 0.5) {
179 | _timeDis = (1 - percent) / ((1 - percent) * 60);
180 | }else{
181 | _timeDis = percent / (percent * 60);
182 | }
183 | if (_delegateFlag.willBeginTimer) {
184 | [_delegate xw_interactiveTransitionWillBeginTimerAnimation:self];
185 | }
186 | //开启timer
187 | [self _xw_startTimer];
188 | }
189 |
190 | - (void)_xw_finish{
191 | if (_delegateFlag.willEnd) {
192 | [_delegate xw_interactiveTransition:self willEndWithSuccessFlag:YES percent:_percent];
193 | }
194 | [self finishInteractiveTransition];
195 | _percent = 0.0f;
196 | _interation = NO;
197 | }
198 |
199 | - (void)_xw_cancle{
200 | if (_delegateFlag.willEnd) {
201 | [_delegate xw_interactiveTransition:self willEndWithSuccessFlag:NO percent:_percent];
202 | }
203 | [self cancelInteractiveTransition];
204 | _percent = 0.0f;
205 | _interation = NO;
206 | }
207 |
208 | - (void)_xw_updatingWithPercent:(CGFloat)percent{
209 | [self updateInteractiveTransition:percent];
210 | if (_delegateFlag.isUpdating) {
211 | [_delegate xw_interactiveTransition:self isUpdating:_percent];
212 | }
213 | }
214 |
215 | - (void)_xw_startTimer{
216 | if (_timer) {
217 | return;
218 | }
219 | _timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(_xw_timerEvent)];
220 | [_timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
221 | }
222 |
223 | - (void)_xw_stopTimer{
224 | if (!_timer) {
225 | return;
226 | }
227 | [_timer invalidate];
228 | _timer = nil;
229 |
230 | }
231 |
232 | //timer 事件
233 | - (void)_xw_timerEvent{
234 | if (_percent > 0.5) {
235 | _percent += _timeDis;
236 | }else{
237 | _percent -= _timeDis;
238 | }
239 | //通过timer不断刷新转场进度
240 | [self _xw_updatingWithPercent:_percent];
241 | BOOL canEnd = [self _xw_canEndInteractiveTransitionWithPercent:_percent];
242 | if (canEnd) {
243 | [self _xw_stopTimer];
244 | }
245 | }
246 | @end
247 |
248 |
--------------------------------------------------------------------------------
/XWTransition/XWCoolAnimator/XWCoolAnimator+XWMiddlePageFlip.m:
--------------------------------------------------------------------------------
1 | //
2 | // XWCoolAnimator+XWMiddlePageFlip.m
3 | // XWTransitionDemo
4 | //
5 | // Created by wazrx on 16/6/13.
6 | // Copyright © 2016年 wazrx. All rights reserved.
7 | //
8 |
9 | #import "XWCoolAnimator+XWMiddlePageFlip.h"
10 | #import "UIView+Snapshot.h"
11 |
12 | @implementation XWCoolAnimator (XWMiddlePageFlip)
13 |
14 |
15 |
16 | - (void)xw_setMiddlePageFlipToAnimation:(id)transitionContext direction:(XWMiddlePageFlipDirection)direction {
17 | [self _xw_animation:transitionContext direction:direction duration:self.toDuration];
18 |
19 | }
20 |
21 | - (void)xw_setMiddlePageFlipBackAnimation:(id)transitionContext direction:(XWMiddlePageFlipDirection)direction {
22 | [self _xw_animation:transitionContext direction:direction duration:self.backDuration];
23 |
24 | }
25 |
26 | - (void)_xw_animation:(id)transitionContext direction:(XWMiddlePageFlipDirection)direction duration:(NSTimeInterval)duration{
27 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
28 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
29 | UIView *toView = toVC.view;
30 | UIView *fromView = fromVC.view;
31 | UIView *containerView = [transitionContext containerView];
32 | [containerView addSubview:toView];
33 | [containerView sendSubviewToBack:toView];
34 | CATransform3D transform = CATransform3DIdentity;
35 | transform.m34 = -0.002;
36 | [containerView.layer setSublayerTransform:transform];
37 | BOOL animation = direction == XWMiddlePageFlipDirectionLeft || direction == XWMiddlePageFlipDirectionTop;
38 | NSArray* toViewSnapshots = [self _xw_animationSnapFlipView:toView withDirection:direction update:YES];
39 | UIView* animationToView = toViewSnapshots[animation ? 1 : 0];
40 | NSArray* fromViewSnapshots = [self _xw_animationSnapFlipView:fromView withDirection:direction update:NO];
41 | UIView* animationFromView = fromViewSnapshots[animation ? 0 : 1];
42 | [self _xw_addShadowWithDirection:direction fromView:animationFromView toView:animationToView];
43 | [self _xw_setAnchorPointWithDirection:direction fromView:animationFromView toView:animationToView];
44 | BOOL rationAngle = direction == XWMiddlePageFlipDirectionLeft || direction == XWMiddlePageFlipDirectionBottom;
45 | BOOL flipDirection = direction == XWMiddlePageFlipDirectionLeft || direction == XWMiddlePageFlipDirectionRight;
46 | animationToView.layer.transform = CATransform3DMakeRotation(rationAngle ? -M_PI_2 : M_PI_2, flipDirection ? 0.0 : 1.0, !flipDirection ? 0.0 : 1.0, 0.0);
47 | [UIView animateKeyframesWithDuration:duration
48 | delay:0.0
49 | options:0
50 | animations:^{
51 | [UIView addKeyframeWithRelativeStartTime:0.0
52 | relativeDuration:0.5
53 | animations:^{
54 | animationFromView.layer.transform = CATransform3DMakeRotation(rationAngle ? M_PI_2 : -M_PI_2, flipDirection ? 0.0 : 1.0, !flipDirection ? 0.0 : 1.0, 0.0);
55 | UIView *shadowView = animationFromView.subviews.lastObject;
56 | shadowView.alpha = 1.0f;
57 | }];
58 |
59 | [UIView addKeyframeWithRelativeStartTime:0.5
60 | relativeDuration:0.5
61 | animations:^{
62 | animationToView.hidden = NO;
63 | animationToView.layer.transform = CATransform3DMakeRotation(rationAngle ? -0.001 : 0.001, flipDirection ? 0.0 : 1.0, !flipDirection ? 0.0 : 1.0, 0.0);
64 | UIView *shadowView = animationToView.subviews.lastObject;
65 | shadowView.alpha = 0.0f;
66 | }];
67 | } completion:^(BOOL finished) {
68 | [toViewSnapshots makeObjectsPerformSelector:@selector(removeFromSuperview)];
69 | [fromViewSnapshots makeObjectsPerformSelector:@selector(removeFromSuperview)];
70 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
71 | }];
72 | }
73 |
74 | - (NSArray *)_xw_animationSnapFlipView:(UIView *)view withDirection:(XWMiddlePageFlipDirection)direction update:(BOOL)update{
75 | UIView *containerView = view.superview;
76 | CGSize size = view.bounds.size;
77 | CGRect rectOne = CGRectZero;
78 | CGRect rectTwo = CGRectZero;
79 | switch (direction) {
80 | case XWMiddlePageFlipDirectionLeft:
81 | case XWMiddlePageFlipDirectionRight:{
82 | rectOne = CGRectMake(0, 0, view.frame.size.width / 2.0f, view.frame.size.height);
83 | rectTwo = CGRectMake(view.frame.size.width / 2.0f, 0, view.frame.size.width / 2.0f, view.frame.size.height);
84 | break;
85 | }
86 | case XWMiddlePageFlipDirectionTop:
87 | case XWMiddlePageFlipDirectionBottom:{
88 | rectOne = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height / 2.0f);
89 | rectTwo = CGRectMake(0, view.frame.size.height / 2.0f, view.frame.size.width, view.frame.size.height / 2.0f);
90 | break;
91 | }
92 | }
93 | UIView *viewOne = [UIView new];
94 | viewOne.contentImage = view.snapshotImage;
95 | UIView *viewTwo = [UIView new];
96 | viewTwo.contentImage = viewOne.contentImage;
97 | viewOne.frame = rectOne;
98 | viewTwo.frame = rectTwo;
99 | viewOne.layer.contentsRect = CGRectMake(rectOne.origin.x / size.width, rectOne.origin.y / size.height, rectOne.size.width / size.width, rectOne.size.height / size.height);
100 | viewTwo.layer.contentsRect = CGRectMake(rectTwo.origin.x / size.width, rectTwo.origin.y / size.height, rectTwo.size.width / size.width, rectTwo.size.height / size.height);
101 | [containerView addSubview:viewOne];
102 | [containerView addSubview:viewTwo];
103 | return @[viewOne, viewTwo];
104 | }
105 |
106 | - (void)_xw_setAnchorPointWithDirection:(XWMiddlePageFlipDirection)direction fromView:(UIView *)fromView toView:(UIView *)toView{
107 | switch (direction) {
108 | case XWMiddlePageFlipDirectionLeft: {
109 | [self _xw_setAnchorPointTo:CGPointMake(1, 0.5) forView:fromView];
110 | [self _xw_setAnchorPointTo:CGPointMake(0, 0.5) forView:toView];
111 | break;
112 | }
113 | case XWMiddlePageFlipDirectionRight: {
114 | [self _xw_setAnchorPointTo:CGPointMake(0, 0.5) forView:fromView];
115 | [self _xw_setAnchorPointTo:CGPointMake(1, 0.5) forView:toView];
116 | break;
117 | }
118 | case XWMiddlePageFlipDirectionTop: {
119 | [self _xw_setAnchorPointTo:CGPointMake(0.5, 1) forView:fromView];
120 | [self _xw_setAnchorPointTo:CGPointMake(0.5, 0) forView:toView];
121 | break;
122 | }
123 | case XWMiddlePageFlipDirectionBottom: {
124 | [self _xw_setAnchorPointTo:CGPointMake(0.5, 0) forView:fromView];
125 | [self _xw_setAnchorPointTo:CGPointMake(0.5, 1) forView:toView];
126 | break;
127 | }
128 | }
129 | }
130 |
131 | - (void)_xw_setAnchorPointTo:(CGPoint)point forView:(UIView *)view{
132 | view.frame = CGRectOffset(view.frame, (point.x - view.layer.anchorPoint.x) * view.frame.size.width, (point.y - view.layer.anchorPoint.y) * view.frame.size.height);
133 | view.layer.anchorPoint = point;
134 | }
135 |
136 | - (void)_xw_addShadowWithDirection:(XWMiddlePageFlipDirection)direction fromView:(UIView *)fromView toView:(UIView *)toView{
137 | CGPoint fstartP = CGPointZero;
138 | CGPoint fendP = CGPointZero;
139 | CGPoint tstartP = CGPointZero;
140 | CGPoint tendP = CGPointZero;
141 | switch (direction) {
142 | case XWMiddlePageFlipDirectionLeft: {
143 | fstartP = CGPointMake(0.0, 0.0);
144 | fendP = CGPointMake(1.0, 0.0);
145 | tstartP = CGPointMake(1.0, 0.0);
146 | tendP = CGPointMake(0.0, 0.0);
147 | break;
148 | }
149 | case XWMiddlePageFlipDirectionRight: {
150 | fstartP = CGPointMake(1.0, 0.0);
151 | fendP = CGPointMake(0.0, 0.0);
152 | tstartP = CGPointMake(0.0, 0.0);
153 | tendP = CGPointMake(1.0, 0.0);
154 | break;
155 | }
156 | case XWMiddlePageFlipDirectionTop: {
157 | fstartP = CGPointMake(0.0, 0.0);
158 | fendP = CGPointMake(0.0, 1.0);
159 | tstartP = CGPointMake(0.0, 1.0);
160 | tendP = CGPointMake(0.0, 0.0);
161 | break;
162 | }
163 | case XWMiddlePageFlipDirectionBottom: {
164 | fstartP = CGPointMake(0.0, 1.0);
165 | fendP = CGPointMake(0.0, 0.0);
166 | tstartP = CGPointMake(0.0, 0.0);
167 | tendP = CGPointMake(0.0, 1.0);
168 | break;
169 | }
170 | }
171 | [self _xw_addGrandientLayerWithStartPoint:fstartP endPoint:fendP forView:fromView].alpha = 0.0f;
172 | [self _xw_addGrandientLayerWithStartPoint:tstartP endPoint:tendP forView:toView].alpha = 1.0f;
173 | }
174 |
175 | - (UIView *)_xw_addGrandientLayerWithStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint forView:(UIView *)view{
176 | CAGradientLayer *gradient = [CAGradientLayer layer];
177 | gradient.frame = view.bounds;
178 | gradient.colors = @[(id)[UIColor colorWithWhite:0.0 alpha:0.0].CGColor,
179 | (id)[UIColor colorWithWhite:0.0 alpha:0.5].CGColor];
180 | gradient.startPoint = startPoint;
181 | gradient.endPoint = endPoint;
182 | UIView* shadowView = [[UIView alloc] initWithFrame:view.bounds];
183 | [shadowView.layer insertSublayer:gradient atIndex:0];
184 | [view addSubview:shadowView];
185 | return shadowView;
186 | }
187 |
188 | #pragma mark -
189 |
190 | - (void)xw_interactiveTransition:(XWInteractiveTransition *)interactiveTransition willEndWithSuccessFlag:(BOOL)flag percent:(CGFloat)percent{
191 | //防止闪烁
192 | if (!flag && percent < 0) {
193 | [interactiveTransition updateInteractiveTransition:0.001];
194 | }
195 | }
196 |
197 | @end
198 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------