├── .DS_Store
├── Demo
├── .DS_Store
├── JCScrollView
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── jay_2.jpg
│ ├── Images.xcassets
│ │ ├── 1.imageset
│ │ │ ├── bgc2.png
│ │ │ └── Contents.json
│ │ ├── 4.imageset
│ │ │ ├── 背景(1).png
│ │ │ └── Contents.json
│ │ ├── 3.imageset
│ │ │ ├── login_bg.png
│ │ │ └── Contents.json
│ │ ├── 2.imageset
│ │ │ ├── myMission_cell_bg111.png
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── LaunchImage.launchimage
│ │ │ └── Contents.json
│ ├── JCViewController.h
│ ├── JCAppDelegate.h
│ ├── main.m
│ ├── JCScrollView-Prefix.pch
│ ├── JCScrollView-Info.plist
│ ├── JCViewController.m
│ ├── JCAppDelegate.m
│ ├── JCScrollView.h
│ ├── Base.lproj
│ │ └── Main.storyboard
│ └── JCScrollView.m
├── JCScrollViewTests
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ ├── JCScrollViewTests-Info.plist
│ └── JCScrollViewTests.m
└── JCScrollView.xcodeproj
│ ├── project.xcworkspace
│ └── contents.xcworkspacedata
│ └── project.pbxproj
├── JCScrollView
├── .DS_Store
├── JCScrollView.h
└── JCScrollView.m
├── README.md
└── .gitignore
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/.DS_Store
--------------------------------------------------------------------------------
/Demo/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/Demo/.DS_Store
--------------------------------------------------------------------------------
/Demo/JCScrollView/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Demo/JCScrollViewTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/JCScrollView/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/JCScrollView/.DS_Store
--------------------------------------------------------------------------------
/Demo/JCScrollView/jay_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/Demo/JCScrollView/jay_2.jpg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | JCScrollView
2 | ============
3 |
4 | easiest way to add a scrollView and pagecontrol to your view , you can switch scrollDirection with animation.
5 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/1.imageset/bgc2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/Demo/JCScrollView/Images.xcassets/1.imageset/bgc2.png
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/4.imageset/背景(1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/Demo/JCScrollView/Images.xcassets/4.imageset/背景(1).png
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/3.imageset/login_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/Demo/JCScrollView/Images.xcassets/3.imageset/login_bg.png
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/2.imageset/myMission_cell_bg111.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zys456465111/JCScrollView/HEAD/Demo/JCScrollView/Images.xcassets/2.imageset/myMission_cell_bg111.png
--------------------------------------------------------------------------------
/Demo/JCScrollView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCViewController.h
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JCViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCAppDelegate.h
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JCAppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "JCAppDelegate.h"
12 |
13 | int main(int argc, char * argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([JCAppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "bgc2.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "背景(1).png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "login_bg.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCScrollView-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | #import
15 | #import
16 | #endif
17 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "myMission_cell_bg111.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.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" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "60x60",
21 | "scale" : "3x"
22 | }
23 | ],
24 | "info" : {
25 | "version" : 1,
26 | "author" : "xcode"
27 | }
28 | }
--------------------------------------------------------------------------------
/Demo/JCScrollView/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | # Pods/
27 |
--------------------------------------------------------------------------------
/Demo/JCScrollViewTests/JCScrollViewTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.zys.jay.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Demo/JCScrollViewTests/JCScrollViewTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCScrollViewTests.m
3 | // JCScrollViewTests
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface JCScrollViewTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation JCScrollViewTests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCScrollView-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | com.zys.jay.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCViewController.m
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import "JCViewController.h"
10 | #import "JCScrollView.h"
11 |
12 | @interface JCViewController ()
13 | @property (nonatomic, weak)IBOutlet JCScrollView *jcSV;
14 | @end
15 |
16 | @implementation JCViewController
17 |
18 | - (void)viewDidLoad
19 | {
20 | [super viewDidLoad];
21 |
22 | [self.jcSV addImageNames:@[@"1",@"2",@"3",@"4"]];
23 | // self.jcSV.pageControlEnabled = NO;
24 | self.jcSV.animationDuration = 0.8;
25 | self.jcSV.animationDelegate = self;
26 | self.jcSV.scrollDirection = JCScrollViewScrollDirectionVertical;
27 | }
28 |
29 | int i = 0;
30 | - (IBAction)changeDirection {
31 | i = i == 1 ? 0 : 1;
32 | [self.jcSV setScrollDirection:i animated:YES];
33 |
34 | }
35 |
36 | int o = 0;
37 | - (IBAction)addImageLast {
38 |
39 | if (o++ == 3)
40 | o = 0;
41 |
42 | NSArray *array = @[@"1",@"2",@"3",@"4"];
43 | [self.jcSV addImageName:array[o]];
44 | }
45 |
46 | /**
47 | * insert lots of images
48 | */
49 | - (void)addImages {
50 |
51 | NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)];
52 | [self.jcSV insertImageNames:@[@"jay_1",@"jay_2.jpg"] atIndex:set];
53 | }
54 |
55 | - (BOOL)prefersStatusBarHidden {
56 | return YES;
57 | }
58 |
59 | #pragma mark - jcScrollViewDelegate
60 |
61 | /**
62 | * 动画开始就会调用
63 | */
64 | - (void)scrollViewDidBeginAnimating:(JCScrollView *)scrollView {
65 | NSLog(@"动画开始");
66 | }
67 |
68 | /**
69 | * 动画结束就会调用
70 | */
71 | - (void)scrollViewDidEndAnimating:(JCScrollView *)scrollView {
72 | NSLog(@"动画结束");
73 | }
74 |
75 | @end
76 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCAppDelegate.m
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import "JCAppDelegate.h"
10 |
11 | @implementation JCAppDelegate
12 |
13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 | {
15 | // Override point for customization after application launch.
16 | return YES;
17 | }
18 |
19 | - (void)applicationWillResignActive:(UIApplication *)application
20 | {
21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
23 | }
24 |
25 | - (void)applicationDidEnterBackground:(UIApplication *)application
26 | {
27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
29 | }
30 |
31 | - (void)applicationWillEnterForeground:(UIApplication *)application
32 | {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | - (void)applicationDidBecomeActive:(UIApplication *)application
37 | {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application
42 | {
43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/JCScrollView/JCScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCScrollView.h
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class JCScrollView;
12 | @protocol JCScrollViewDelegate
13 |
14 | /**
15 | * 动画开始就会调用
16 | */
17 | - (void)scrollViewDidBeginAnimating:(JCScrollView *)scrollView;
18 |
19 | /**
20 | * 动画结束就会调用
21 | */
22 | - (void)scrollViewDidEndAnimating:(JCScrollView *)scrollView;
23 |
24 | @end
25 |
26 | /**
27 | * 滚动方向
28 | */
29 | typedef enum {
30 |
31 | JCScrollViewScrollDirectionHorizontal = 0,
32 |
33 | JCScrollViewScrollDirectionVertical
34 |
35 | }JCScrollViewScrollDirection;
36 |
37 | @interface JCScrollView : UIScrollView
38 |
39 | /**
40 | * 动画代理
41 | */
42 | @property (nonatomic, weak)id animationDelegate;
43 |
44 | /**
45 | * 滚动方向
46 | */
47 | @property (nonatomic, assign)JCScrollViewScrollDirection scrollDirection;
48 |
49 | /**
50 | * 样式可以拿去设置
51 | */
52 | @property (nonatomic, strong)UIPageControl *pageControl;
53 |
54 | /**
55 | * pageControl,默认开启
56 | */
57 | @property (nonatomic, assign, getter = isPageControlEnabled)BOOL pageControlEnabled;
58 |
59 | /**
60 | * 动画执行时间,当你调用这个方法时才用,默认- (void)setScrollDirection:(JCScrollViewScrollDirection)direction animated:(BOOL)animated;
61 | */
62 | @property (nonatomic, assign)CGFloat animationDuration;
63 |
64 | /**
65 | * 正在动画
66 | */
67 | @property (nonatomic, assign, readonly, getter = isAnimating)BOOL animating;
68 | /**
69 | * 添加多张图片名称
70 | *
71 | */
72 | - (void)addImageNames:(NSArray *)names;
73 |
74 | /**
75 | * 添加单张图片名称
76 | *
77 | */
78 | - (void)addImageName:(NSString *)name;
79 |
80 | /**
81 | * 添加单张图片在指定位置
82 | */
83 | - (void)insertImageName:(NSString *)name atIndex:(NSUInteger)index;
84 |
85 | /**
86 | * 添加多张图片在指定位置
87 | *
88 | */
89 | - (void)insertImageNames:(NSArray *)names atIndex:(NSIndexSet *)indexes;
90 |
91 | /**
92 | * 改变滚动方向
93 | *
94 | * @param direction 方向
95 | * @param animated 动画
96 | */
97 | - (void)setScrollDirection:(JCScrollViewScrollDirection)direction animated:(BOOL)animated;
98 |
99 | /**
100 | * 快速创建
101 | */
102 | + (instancetype)scrollViewWithFrame:(CGRect)frame andImageNames:(NSArray *)imageNames;
103 |
104 | @end
105 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCScrollView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JCScrollView.h
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class JCScrollView;
12 | @protocol JCScrollViewDelegate
13 |
14 | /**
15 | * 动画开始就会调用
16 | */
17 | - (void)scrollViewDidBeginAnimating:(JCScrollView *)scrollView;
18 |
19 | /**
20 | * 动画结束就会调用
21 | */
22 | - (void)scrollViewDidEndAnimating:(JCScrollView *)scrollView;
23 |
24 | @end
25 |
26 | /**
27 | * 滚动方向
28 | */
29 | typedef enum {
30 |
31 | JCScrollViewScrollDirectionHorizontal = 0,
32 |
33 | JCScrollViewScrollDirectionVertical
34 |
35 | }JCScrollViewScrollDirection;
36 |
37 | @interface JCScrollView : UIScrollView
38 |
39 | /**
40 | * 动画代理
41 | */
42 | @property (nonatomic, weak)id animationDelegate;
43 |
44 | /**
45 | * 滚动方向
46 | */
47 | @property (nonatomic, assign)JCScrollViewScrollDirection scrollDirection;
48 |
49 | /**
50 | * 样式可以拿去设置
51 | */
52 | @property (nonatomic, strong)UIPageControl *pageControl;
53 |
54 | /**
55 | * pageControl,默认开启
56 | */
57 | @property (nonatomic, assign, getter = isPageControlEnabled)BOOL pageControlEnabled;
58 |
59 | /**
60 | * 动画执行时间,当你调用这个方法时才用,默认- (void)setScrollDirection:(JCScrollViewScrollDirection)direction animated:(BOOL)animated;
61 | */
62 | @property (nonatomic, assign)CGFloat animationDuration;
63 |
64 | /**
65 | * 正在动画
66 | */
67 | @property (nonatomic, assign, readonly, getter = isAnimating)BOOL animating;
68 | /**
69 | * 添加多张图片名称
70 | *
71 | */
72 | - (void)addImageNames:(NSArray *)names;
73 |
74 | /**
75 | * 添加单张图片名称
76 | *
77 | */
78 | - (void)addImageName:(NSString *)name;
79 |
80 | /**
81 | * 添加单张图片在指定位置
82 | */
83 | - (void)insertImageName:(NSString *)name atIndex:(NSUInteger)index;
84 |
85 | /**
86 | * 添加多张图片在指定位置
87 | *
88 | */
89 | - (void)insertImageNames:(NSArray *)names atIndex:(NSIndexSet *)indexes;
90 |
91 | /**
92 | * 改变滚动方向
93 | *
94 | * @param direction 方向
95 | * @param animated 动画
96 | */
97 | - (void)setScrollDirection:(JCScrollViewScrollDirection)direction animated:(BOOL)animated;
98 |
99 | /**
100 | * 快速创建
101 | */
102 | + (instancetype)scrollViewWithFrame:(CGRect)frame andImageNames:(NSArray *)imageNames;
103 |
104 | @end
105 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/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 |
30 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/Demo/JCScrollView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6975725219FF7D6B009754B5 /* jay_2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 6975725119FF7D6B009754B5 /* jay_2.jpg */; };
11 | 69DB906319FE07EC00B5F257 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DB906219FE07EC00B5F257 /* Foundation.framework */; };
12 | 69DB906519FE07EC00B5F257 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DB906419FE07EC00B5F257 /* CoreGraphics.framework */; };
13 | 69DB906719FE07EC00B5F257 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DB906619FE07EC00B5F257 /* UIKit.framework */; };
14 | 69DB906D19FE07EC00B5F257 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69DB906B19FE07EC00B5F257 /* InfoPlist.strings */; };
15 | 69DB906F19FE07EC00B5F257 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 69DB906E19FE07EC00B5F257 /* main.m */; };
16 | 69DB907319FE07EC00B5F257 /* JCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 69DB907219FE07EC00B5F257 /* JCAppDelegate.m */; };
17 | 69DB907619FE07EC00B5F257 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 69DB907419FE07EC00B5F257 /* Main.storyboard */; };
18 | 69DB907919FE07EC00B5F257 /* JCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 69DB907819FE07EC00B5F257 /* JCViewController.m */; };
19 | 69DB907B19FE07EC00B5F257 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69DB907A19FE07EC00B5F257 /* Images.xcassets */; };
20 | 69DB908219FE07EC00B5F257 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DB908119FE07EC00B5F257 /* XCTest.framework */; };
21 | 69DB908319FE07EC00B5F257 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DB906219FE07EC00B5F257 /* Foundation.framework */; };
22 | 69DB908419FE07EC00B5F257 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DB906619FE07EC00B5F257 /* UIKit.framework */; };
23 | 69DB908C19FE07EC00B5F257 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69DB908A19FE07EC00B5F257 /* InfoPlist.strings */; };
24 | 69DB908E19FE07EC00B5F257 /* JCScrollViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 69DB908D19FE07EC00B5F257 /* JCScrollViewTests.m */; };
25 | 69DB909919FE080200B5F257 /* JCScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 69DB909819FE080200B5F257 /* JCScrollView.m */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXContainerItemProxy section */
29 | 69DB908519FE07EC00B5F257 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 69DB905719FE07EC00B5F257 /* Project object */;
32 | proxyType = 1;
33 | remoteGlobalIDString = 69DB905E19FE07EC00B5F257;
34 | remoteInfo = JCScrollView;
35 | };
36 | /* End PBXContainerItemProxy section */
37 |
38 | /* Begin PBXFileReference section */
39 | 6975725119FF7D6B009754B5 /* jay_2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = jay_2.jpg; sourceTree = ""; };
40 | 69DB905F19FE07EC00B5F257 /* JCScrollView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JCScrollView.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 69DB906219FE07EC00B5F257 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
42 | 69DB906419FE07EC00B5F257 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
43 | 69DB906619FE07EC00B5F257 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
44 | 69DB906A19FE07EC00B5F257 /* JCScrollView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "JCScrollView-Info.plist"; sourceTree = ""; };
45 | 69DB906C19FE07EC00B5F257 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
46 | 69DB906E19FE07EC00B5F257 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
47 | 69DB907019FE07EC00B5F257 /* JCScrollView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JCScrollView-Prefix.pch"; sourceTree = ""; };
48 | 69DB907119FE07EC00B5F257 /* JCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JCAppDelegate.h; sourceTree = ""; };
49 | 69DB907219FE07EC00B5F257 /* JCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JCAppDelegate.m; sourceTree = ""; };
50 | 69DB907519FE07EC00B5F257 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
51 | 69DB907719FE07EC00B5F257 /* JCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JCViewController.h; sourceTree = ""; };
52 | 69DB907819FE07EC00B5F257 /* JCViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JCViewController.m; sourceTree = ""; };
53 | 69DB907A19FE07EC00B5F257 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
54 | 69DB908019FE07EC00B5F257 /* JCScrollViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JCScrollViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
55 | 69DB908119FE07EC00B5F257 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
56 | 69DB908919FE07EC00B5F257 /* JCScrollViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "JCScrollViewTests-Info.plist"; sourceTree = ""; };
57 | 69DB908B19FE07EC00B5F257 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
58 | 69DB908D19FE07EC00B5F257 /* JCScrollViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JCScrollViewTests.m; sourceTree = ""; };
59 | 69DB909719FE080200B5F257 /* JCScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JCScrollView.h; sourceTree = ""; };
60 | 69DB909819FE080200B5F257 /* JCScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JCScrollView.m; sourceTree = ""; };
61 | /* End PBXFileReference section */
62 |
63 | /* Begin PBXFrameworksBuildPhase section */
64 | 69DB905C19FE07EC00B5F257 /* Frameworks */ = {
65 | isa = PBXFrameworksBuildPhase;
66 | buildActionMask = 2147483647;
67 | files = (
68 | 69DB906519FE07EC00B5F257 /* CoreGraphics.framework in Frameworks */,
69 | 69DB906719FE07EC00B5F257 /* UIKit.framework in Frameworks */,
70 | 69DB906319FE07EC00B5F257 /* Foundation.framework in Frameworks */,
71 | );
72 | runOnlyForDeploymentPostprocessing = 0;
73 | };
74 | 69DB907D19FE07EC00B5F257 /* Frameworks */ = {
75 | isa = PBXFrameworksBuildPhase;
76 | buildActionMask = 2147483647;
77 | files = (
78 | 69DB908219FE07EC00B5F257 /* XCTest.framework in Frameworks */,
79 | 69DB908419FE07EC00B5F257 /* UIKit.framework in Frameworks */,
80 | 69DB908319FE07EC00B5F257 /* Foundation.framework in Frameworks */,
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | /* End PBXFrameworksBuildPhase section */
85 |
86 | /* Begin PBXGroup section */
87 | 69D60C411A2C0AFB0086E0AA /* JCScrollView */ = {
88 | isa = PBXGroup;
89 | children = (
90 | 69DB909719FE080200B5F257 /* JCScrollView.h */,
91 | 69DB909819FE080200B5F257 /* JCScrollView.m */,
92 | );
93 | name = JCScrollView;
94 | sourceTree = "";
95 | };
96 | 69DB905619FE07EC00B5F257 = {
97 | isa = PBXGroup;
98 | children = (
99 | 69DB906819FE07EC00B5F257 /* JCScrollView */,
100 | 69DB908719FE07EC00B5F257 /* JCScrollViewTests */,
101 | 69DB906119FE07EC00B5F257 /* Frameworks */,
102 | 69DB906019FE07EC00B5F257 /* Products */,
103 | );
104 | sourceTree = "";
105 | };
106 | 69DB906019FE07EC00B5F257 /* Products */ = {
107 | isa = PBXGroup;
108 | children = (
109 | 69DB905F19FE07EC00B5F257 /* JCScrollView.app */,
110 | 69DB908019FE07EC00B5F257 /* JCScrollViewTests.xctest */,
111 | );
112 | name = Products;
113 | sourceTree = "";
114 | };
115 | 69DB906119FE07EC00B5F257 /* Frameworks */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 69DB906219FE07EC00B5F257 /* Foundation.framework */,
119 | 69DB906419FE07EC00B5F257 /* CoreGraphics.framework */,
120 | 69DB906619FE07EC00B5F257 /* UIKit.framework */,
121 | 69DB908119FE07EC00B5F257 /* XCTest.framework */,
122 | );
123 | name = Frameworks;
124 | sourceTree = "";
125 | };
126 | 69DB906819FE07EC00B5F257 /* JCScrollView */ = {
127 | isa = PBXGroup;
128 | children = (
129 | 69DB907119FE07EC00B5F257 /* JCAppDelegate.h */,
130 | 69DB907219FE07EC00B5F257 /* JCAppDelegate.m */,
131 | 69DB907419FE07EC00B5F257 /* Main.storyboard */,
132 | 69DB907719FE07EC00B5F257 /* JCViewController.h */,
133 | 69DB907819FE07EC00B5F257 /* JCViewController.m */,
134 | 69DB907A19FE07EC00B5F257 /* Images.xcassets */,
135 | 69DB906919FE07EC00B5F257 /* Supporting Files */,
136 | 69D60C411A2C0AFB0086E0AA /* JCScrollView */,
137 | );
138 | path = JCScrollView;
139 | sourceTree = "";
140 | };
141 | 69DB906919FE07EC00B5F257 /* Supporting Files */ = {
142 | isa = PBXGroup;
143 | children = (
144 | 6975725119FF7D6B009754B5 /* jay_2.jpg */,
145 | 69DB906A19FE07EC00B5F257 /* JCScrollView-Info.plist */,
146 | 69DB906B19FE07EC00B5F257 /* InfoPlist.strings */,
147 | 69DB906E19FE07EC00B5F257 /* main.m */,
148 | 69DB907019FE07EC00B5F257 /* JCScrollView-Prefix.pch */,
149 | );
150 | name = "Supporting Files";
151 | sourceTree = "";
152 | };
153 | 69DB908719FE07EC00B5F257 /* JCScrollViewTests */ = {
154 | isa = PBXGroup;
155 | children = (
156 | 69DB908D19FE07EC00B5F257 /* JCScrollViewTests.m */,
157 | 69DB908819FE07EC00B5F257 /* Supporting Files */,
158 | );
159 | path = JCScrollViewTests;
160 | sourceTree = "";
161 | };
162 | 69DB908819FE07EC00B5F257 /* Supporting Files */ = {
163 | isa = PBXGroup;
164 | children = (
165 | 69DB908919FE07EC00B5F257 /* JCScrollViewTests-Info.plist */,
166 | 69DB908A19FE07EC00B5F257 /* InfoPlist.strings */,
167 | );
168 | name = "Supporting Files";
169 | sourceTree = "";
170 | };
171 | /* End PBXGroup section */
172 |
173 | /* Begin PBXNativeTarget section */
174 | 69DB905E19FE07EC00B5F257 /* JCScrollView */ = {
175 | isa = PBXNativeTarget;
176 | buildConfigurationList = 69DB909119FE07EC00B5F257 /* Build configuration list for PBXNativeTarget "JCScrollView" */;
177 | buildPhases = (
178 | 69DB905B19FE07EC00B5F257 /* Sources */,
179 | 69DB905C19FE07EC00B5F257 /* Frameworks */,
180 | 69DB905D19FE07EC00B5F257 /* Resources */,
181 | );
182 | buildRules = (
183 | );
184 | dependencies = (
185 | );
186 | name = JCScrollView;
187 | productName = JCScrollView;
188 | productReference = 69DB905F19FE07EC00B5F257 /* JCScrollView.app */;
189 | productType = "com.apple.product-type.application";
190 | };
191 | 69DB907F19FE07EC00B5F257 /* JCScrollViewTests */ = {
192 | isa = PBXNativeTarget;
193 | buildConfigurationList = 69DB909419FE07EC00B5F257 /* Build configuration list for PBXNativeTarget "JCScrollViewTests" */;
194 | buildPhases = (
195 | 69DB907C19FE07EC00B5F257 /* Sources */,
196 | 69DB907D19FE07EC00B5F257 /* Frameworks */,
197 | 69DB907E19FE07EC00B5F257 /* Resources */,
198 | );
199 | buildRules = (
200 | );
201 | dependencies = (
202 | 69DB908619FE07EC00B5F257 /* PBXTargetDependency */,
203 | );
204 | name = JCScrollViewTests;
205 | productName = JCScrollViewTests;
206 | productReference = 69DB908019FE07EC00B5F257 /* JCScrollViewTests.xctest */;
207 | productType = "com.apple.product-type.bundle.unit-test";
208 | };
209 | /* End PBXNativeTarget section */
210 |
211 | /* Begin PBXProject section */
212 | 69DB905719FE07EC00B5F257 /* Project object */ = {
213 | isa = PBXProject;
214 | attributes = {
215 | CLASSPREFIX = JC;
216 | LastUpgradeCheck = 0510;
217 | ORGANIZATIONNAME = zys;
218 | TargetAttributes = {
219 | 69DB907F19FE07EC00B5F257 = {
220 | TestTargetID = 69DB905E19FE07EC00B5F257;
221 | };
222 | };
223 | };
224 | buildConfigurationList = 69DB905A19FE07EC00B5F257 /* Build configuration list for PBXProject "JCScrollView" */;
225 | compatibilityVersion = "Xcode 3.2";
226 | developmentRegion = English;
227 | hasScannedForEncodings = 0;
228 | knownRegions = (
229 | en,
230 | Base,
231 | );
232 | mainGroup = 69DB905619FE07EC00B5F257;
233 | productRefGroup = 69DB906019FE07EC00B5F257 /* Products */;
234 | projectDirPath = "";
235 | projectRoot = "";
236 | targets = (
237 | 69DB905E19FE07EC00B5F257 /* JCScrollView */,
238 | 69DB907F19FE07EC00B5F257 /* JCScrollViewTests */,
239 | );
240 | };
241 | /* End PBXProject section */
242 |
243 | /* Begin PBXResourcesBuildPhase section */
244 | 69DB905D19FE07EC00B5F257 /* Resources */ = {
245 | isa = PBXResourcesBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | 69DB907B19FE07EC00B5F257 /* Images.xcassets in Resources */,
249 | 6975725219FF7D6B009754B5 /* jay_2.jpg in Resources */,
250 | 69DB906D19FE07EC00B5F257 /* InfoPlist.strings in Resources */,
251 | 69DB907619FE07EC00B5F257 /* Main.storyboard in Resources */,
252 | );
253 | runOnlyForDeploymentPostprocessing = 0;
254 | };
255 | 69DB907E19FE07EC00B5F257 /* Resources */ = {
256 | isa = PBXResourcesBuildPhase;
257 | buildActionMask = 2147483647;
258 | files = (
259 | 69DB908C19FE07EC00B5F257 /* InfoPlist.strings in Resources */,
260 | );
261 | runOnlyForDeploymentPostprocessing = 0;
262 | };
263 | /* End PBXResourcesBuildPhase section */
264 |
265 | /* Begin PBXSourcesBuildPhase section */
266 | 69DB905B19FE07EC00B5F257 /* Sources */ = {
267 | isa = PBXSourcesBuildPhase;
268 | buildActionMask = 2147483647;
269 | files = (
270 | 69DB909919FE080200B5F257 /* JCScrollView.m in Sources */,
271 | 69DB906F19FE07EC00B5F257 /* main.m in Sources */,
272 | 69DB907919FE07EC00B5F257 /* JCViewController.m in Sources */,
273 | 69DB907319FE07EC00B5F257 /* JCAppDelegate.m in Sources */,
274 | );
275 | runOnlyForDeploymentPostprocessing = 0;
276 | };
277 | 69DB907C19FE07EC00B5F257 /* Sources */ = {
278 | isa = PBXSourcesBuildPhase;
279 | buildActionMask = 2147483647;
280 | files = (
281 | 69DB908E19FE07EC00B5F257 /* JCScrollViewTests.m in Sources */,
282 | );
283 | runOnlyForDeploymentPostprocessing = 0;
284 | };
285 | /* End PBXSourcesBuildPhase section */
286 |
287 | /* Begin PBXTargetDependency section */
288 | 69DB908619FE07EC00B5F257 /* PBXTargetDependency */ = {
289 | isa = PBXTargetDependency;
290 | target = 69DB905E19FE07EC00B5F257 /* JCScrollView */;
291 | targetProxy = 69DB908519FE07EC00B5F257 /* PBXContainerItemProxy */;
292 | };
293 | /* End PBXTargetDependency section */
294 |
295 | /* Begin PBXVariantGroup section */
296 | 69DB906B19FE07EC00B5F257 /* InfoPlist.strings */ = {
297 | isa = PBXVariantGroup;
298 | children = (
299 | 69DB906C19FE07EC00B5F257 /* en */,
300 | );
301 | name = InfoPlist.strings;
302 | sourceTree = "";
303 | };
304 | 69DB907419FE07EC00B5F257 /* Main.storyboard */ = {
305 | isa = PBXVariantGroup;
306 | children = (
307 | 69DB907519FE07EC00B5F257 /* Base */,
308 | );
309 | name = Main.storyboard;
310 | sourceTree = "";
311 | };
312 | 69DB908A19FE07EC00B5F257 /* InfoPlist.strings */ = {
313 | isa = PBXVariantGroup;
314 | children = (
315 | 69DB908B19FE07EC00B5F257 /* en */,
316 | );
317 | name = InfoPlist.strings;
318 | sourceTree = "";
319 | };
320 | /* End PBXVariantGroup section */
321 |
322 | /* Begin XCBuildConfiguration section */
323 | 69DB908F19FE07EC00B5F257 /* Debug */ = {
324 | isa = XCBuildConfiguration;
325 | buildSettings = {
326 | ALWAYS_SEARCH_USER_PATHS = NO;
327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
328 | CLANG_CXX_LIBRARY = "libc++";
329 | CLANG_ENABLE_MODULES = YES;
330 | CLANG_ENABLE_OBJC_ARC = YES;
331 | CLANG_WARN_BOOL_CONVERSION = YES;
332 | CLANG_WARN_CONSTANT_CONVERSION = YES;
333 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
334 | CLANG_WARN_EMPTY_BODY = YES;
335 | CLANG_WARN_ENUM_CONVERSION = YES;
336 | CLANG_WARN_INT_CONVERSION = YES;
337 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
338 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
339 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
340 | COPY_PHASE_STRIP = NO;
341 | GCC_C_LANGUAGE_STANDARD = gnu99;
342 | GCC_DYNAMIC_NO_PIC = NO;
343 | GCC_OPTIMIZATION_LEVEL = 0;
344 | GCC_PREPROCESSOR_DEFINITIONS = (
345 | "DEBUG=1",
346 | "$(inherited)",
347 | );
348 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
349 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
350 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
351 | GCC_WARN_UNDECLARED_SELECTOR = YES;
352 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
353 | GCC_WARN_UNUSED_FUNCTION = YES;
354 | GCC_WARN_UNUSED_VARIABLE = YES;
355 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
356 | ONLY_ACTIVE_ARCH = YES;
357 | SDKROOT = iphoneos;
358 | };
359 | name = Debug;
360 | };
361 | 69DB909019FE07EC00B5F257 /* Release */ = {
362 | isa = XCBuildConfiguration;
363 | buildSettings = {
364 | ALWAYS_SEARCH_USER_PATHS = NO;
365 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
366 | CLANG_CXX_LIBRARY = "libc++";
367 | CLANG_ENABLE_MODULES = YES;
368 | CLANG_ENABLE_OBJC_ARC = YES;
369 | CLANG_WARN_BOOL_CONVERSION = YES;
370 | CLANG_WARN_CONSTANT_CONVERSION = YES;
371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
372 | CLANG_WARN_EMPTY_BODY = YES;
373 | CLANG_WARN_ENUM_CONVERSION = YES;
374 | CLANG_WARN_INT_CONVERSION = YES;
375 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
378 | COPY_PHASE_STRIP = YES;
379 | ENABLE_NS_ASSERTIONS = NO;
380 | GCC_C_LANGUAGE_STANDARD = gnu99;
381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
383 | GCC_WARN_UNDECLARED_SELECTOR = YES;
384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
385 | GCC_WARN_UNUSED_FUNCTION = YES;
386 | GCC_WARN_UNUSED_VARIABLE = YES;
387 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
388 | SDKROOT = iphoneos;
389 | VALIDATE_PRODUCT = YES;
390 | };
391 | name = Release;
392 | };
393 | 69DB909219FE07EC00B5F257 /* Debug */ = {
394 | isa = XCBuildConfiguration;
395 | buildSettings = {
396 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
397 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
398 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
399 | GCC_PREFIX_HEADER = "JCScrollView/JCScrollView-Prefix.pch";
400 | INFOPLIST_FILE = "JCScrollView/JCScrollView-Info.plist";
401 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
402 | PRODUCT_NAME = "$(TARGET_NAME)";
403 | TARGETED_DEVICE_FAMILY = 1;
404 | WRAPPER_EXTENSION = app;
405 | };
406 | name = Debug;
407 | };
408 | 69DB909319FE07EC00B5F257 /* Release */ = {
409 | isa = XCBuildConfiguration;
410 | buildSettings = {
411 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
412 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
413 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
414 | GCC_PREFIX_HEADER = "JCScrollView/JCScrollView-Prefix.pch";
415 | INFOPLIST_FILE = "JCScrollView/JCScrollView-Info.plist";
416 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
417 | PRODUCT_NAME = "$(TARGET_NAME)";
418 | TARGETED_DEVICE_FAMILY = 1;
419 | WRAPPER_EXTENSION = app;
420 | };
421 | name = Release;
422 | };
423 | 69DB909519FE07EC00B5F257 /* Debug */ = {
424 | isa = XCBuildConfiguration;
425 | buildSettings = {
426 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/JCScrollView.app/JCScrollView";
427 | FRAMEWORK_SEARCH_PATHS = (
428 | "$(SDKROOT)/Developer/Library/Frameworks",
429 | "$(inherited)",
430 | "$(DEVELOPER_FRAMEWORKS_DIR)",
431 | );
432 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
433 | GCC_PREFIX_HEADER = "JCScrollView/JCScrollView-Prefix.pch";
434 | GCC_PREPROCESSOR_DEFINITIONS = (
435 | "DEBUG=1",
436 | "$(inherited)",
437 | );
438 | INFOPLIST_FILE = "JCScrollViewTests/JCScrollViewTests-Info.plist";
439 | PRODUCT_NAME = "$(TARGET_NAME)";
440 | TEST_HOST = "$(BUNDLE_LOADER)";
441 | WRAPPER_EXTENSION = xctest;
442 | };
443 | name = Debug;
444 | };
445 | 69DB909619FE07EC00B5F257 /* Release */ = {
446 | isa = XCBuildConfiguration;
447 | buildSettings = {
448 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/JCScrollView.app/JCScrollView";
449 | FRAMEWORK_SEARCH_PATHS = (
450 | "$(SDKROOT)/Developer/Library/Frameworks",
451 | "$(inherited)",
452 | "$(DEVELOPER_FRAMEWORKS_DIR)",
453 | );
454 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
455 | GCC_PREFIX_HEADER = "JCScrollView/JCScrollView-Prefix.pch";
456 | INFOPLIST_FILE = "JCScrollViewTests/JCScrollViewTests-Info.plist";
457 | PRODUCT_NAME = "$(TARGET_NAME)";
458 | TEST_HOST = "$(BUNDLE_LOADER)";
459 | WRAPPER_EXTENSION = xctest;
460 | };
461 | name = Release;
462 | };
463 | /* End XCBuildConfiguration section */
464 |
465 | /* Begin XCConfigurationList section */
466 | 69DB905A19FE07EC00B5F257 /* Build configuration list for PBXProject "JCScrollView" */ = {
467 | isa = XCConfigurationList;
468 | buildConfigurations = (
469 | 69DB908F19FE07EC00B5F257 /* Debug */,
470 | 69DB909019FE07EC00B5F257 /* Release */,
471 | );
472 | defaultConfigurationIsVisible = 0;
473 | defaultConfigurationName = Release;
474 | };
475 | 69DB909119FE07EC00B5F257 /* Build configuration list for PBXNativeTarget "JCScrollView" */ = {
476 | isa = XCConfigurationList;
477 | buildConfigurations = (
478 | 69DB909219FE07EC00B5F257 /* Debug */,
479 | 69DB909319FE07EC00B5F257 /* Release */,
480 | );
481 | defaultConfigurationIsVisible = 0;
482 | defaultConfigurationName = Release;
483 | };
484 | 69DB909419FE07EC00B5F257 /* Build configuration list for PBXNativeTarget "JCScrollViewTests" */ = {
485 | isa = XCConfigurationList;
486 | buildConfigurations = (
487 | 69DB909519FE07EC00B5F257 /* Debug */,
488 | 69DB909619FE07EC00B5F257 /* Release */,
489 | );
490 | defaultConfigurationIsVisible = 0;
491 | defaultConfigurationName = Release;
492 | };
493 | /* End XCConfigurationList section */
494 | };
495 | rootObject = 69DB905719FE07EC00B5F257 /* Project object */;
496 | }
497 |
--------------------------------------------------------------------------------
/JCScrollView/JCScrollView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCScrollView.m
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import "JCScrollView.h"
10 |
11 | //direction Next -1 Previous 1便于后面计算
12 | typedef enum {
13 | JCScrollViewMoveDirectionNext = -1,
14 | JCScrollViewMoveDirectionPrevious = 1
15 | }JCScrollViewMoveDirection;
16 |
17 | @interface JCScrollView ()
18 |
19 | /**
20 | * 循环利用imageView数组
21 | */
22 | @property (nonatomic, strong)NSArray *imageViews;
23 |
24 | /**
25 | * 记录当前的索引
26 | */
27 | @property (nonatomic, assign)NSInteger currentIndex;
28 |
29 | /**
30 | * 图片数组
31 | */
32 | @property (nonatomic, strong)NSMutableArray *imageNames;
33 |
34 | @end
35 |
36 | @implementation JCScrollView
37 |
38 | + (instancetype)scrollViewWithFrame:(CGRect)frame andImageNames:(NSArray *)imageNames {
39 | JCScrollView *jcSV = [[JCScrollView alloc]initWithFrame:frame];
40 | jcSV.imageNames = [NSMutableArray arrayWithArray:imageNames];
41 | return jcSV;
42 | }
43 |
44 | - (void)setCurrentIndex:(NSInteger)currentIndex {
45 | if (currentIndex == 3) {
46 | currentIndex = 0;
47 | } else if (currentIndex == -1) {
48 | currentIndex = 2;
49 | }
50 | _currentIndex = currentIndex;
51 | }
52 |
53 | - (void)setScrollDirection:(JCScrollViewScrollDirection)scrollDirection {
54 | if (_scrollDirection == scrollDirection) return;
55 |
56 | [self setScrollDirection:scrollDirection animated:NO];
57 |
58 | _scrollDirection = scrollDirection;
59 | }
60 |
61 | - (void)setPageControlEnabled:(BOOL)pageControlEnabled {
62 |
63 | if(_pageControlEnabled == pageControlEnabled) return;
64 |
65 | if(pageControlEnabled)
66 | [self.superview addSubview:self.pageControl];
67 | else
68 | [self.pageControl removeFromSuperview];
69 |
70 | _pageControlEnabled = pageControlEnabled;
71 | }
72 |
73 | - (void)setContentOffset:(CGPoint)contentOffset {
74 |
75 | [super setContentOffset:contentOffset];
76 |
77 | NSUInteger prePage = self.pageControl.currentPage;
78 |
79 | switch (_scrollDirection) {
80 | case JCScrollViewScrollDirectionHorizontal:
81 |
82 | _pageControl.currentPage = contentOffset.x / self.bounds.size.width + 0.5;
83 |
84 | break;
85 |
86 | case JCScrollViewScrollDirectionVertical:
87 |
88 | _pageControl.currentPage = contentOffset.y / self.bounds.size.height + 0.5;
89 |
90 | break;
91 | default:
92 | break;
93 | }
94 |
95 | if (_pageControl.currentPage > prePage) { //图片向前走
96 |
97 | [self moveImageViewWithDirection:JCScrollViewMoveDirectionNext];
98 |
99 | } else if (_pageControl.currentPage < prePage) {
100 |
101 | [self moveImageViewWithDirection:JCScrollViewMoveDirectionPrevious];
102 |
103 | }
104 |
105 | }
106 |
107 | - (NSArray *)imageViews {
108 | if (!_imageViews) {
109 |
110 | NSMutableArray *imageViews = [NSMutableArray array];
111 |
112 | /**
113 | * 如果图片数量小于3张,就只创建图片数量的imageView
114 | */
115 | NSInteger count = self.imageNames.count < 3 ? self.imageNames.count + 1 : 3;
116 | int startNum = self.imageNames.count < 3 ? 1 : 0;
117 | for (int i = startNum; i index) {
244 |
245 | self.currentIndex++;
246 | [self moveImageViewWithDirection:JCScrollViewMoveDirectionPrevious];
247 |
248 | //插入的图片那正好是当前图片
249 | } else if (self.pageControl.currentPage == index) {
250 |
251 | [self setImageWithImageIndex:self.currentIndex andImageNameIndex:index];
252 |
253 | }
254 |
255 | }
256 |
257 | /**
258 | * 转换垂直或水平滚动时子控件重新布局
259 | */
260 | - (void)convertImageViewsBetweenHorizontalAndVertical {
261 |
262 | for (UIImageView *imageView in self.imageViews) {
263 | //只改变当前这张
264 |
265 | //还原一下尺寸
266 | // imageView.transform = CGAffineTransformIdentity;
267 |
268 | switch (self.scrollDirection) {
269 | case JCScrollViewScrollDirectionHorizontal:
270 | //来到这里的imageView说明以前是垂直的,也就是说x为0 y有值,那么就转换一下
271 | {
272 | NSInteger currentPage = imageView.frame.origin.y / self.bounds.size.height;
273 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,0},imageView.bounds.size};
274 | // NSLog(@"%@",NSStringFromCGRect(imageView.frame));
275 | break;
276 | }
277 | case JCScrollViewScrollDirectionVertical:
278 | {
279 | NSInteger currentPage = imageView.frame.origin.x / self.bounds.size.width;
280 | imageView.frame = (CGRect){{0,currentPage * self.bounds.size.height},imageView.bounds.size};
281 | break;
282 | }
283 | default:
284 | break;
285 | }
286 |
287 | }
288 |
289 | //要同时进行,不知不觉中切换,暗度陈仓
290 | switch (self.scrollDirection) {
291 | case JCScrollViewScrollDirectionHorizontal:
292 |
293 | [self setContentOffset:CGPointMake(self.pageControl.currentPage * self.bounds.size.width, 0)];
294 |
295 | break;
296 |
297 | case JCScrollViewScrollDirectionVertical:
298 |
299 | [self setContentOffset:CGPointMake(0, self.pageControl.currentPage * self.bounds.size.height)];
300 |
301 | break;
302 |
303 | default:
304 | break;
305 | }
306 |
307 | [self resizeContentWithIndex:-1];
308 | }
309 |
310 | /**
311 | * 动态切换滚动方向
312 | *
313 | * @param direction 方向
314 | * @param animated 是否执行动画
315 | */
316 | - (void)setScrollDirection:(JCScrollViewScrollDirection)direction animated:(BOOL)animated {
317 |
318 | if (!animated) {
319 | /**
320 | * 方向相同不执行
321 | */
322 | if (_scrollDirection == direction) return;
323 | _scrollDirection = direction;
324 | [self convertImageViewsBetweenHorizontalAndVertical];
325 | return;
326 | }
327 |
328 | if (self.isAnimating)
329 | return;
330 |
331 | void (^JCAffineTransformTranslate)(UIImageView*, CGFloat, CGFloat) = ^(UIImageView *imageView, CGFloat tx, CGFloat ty){
332 |
333 | CGRect imageframe = imageView.frame;
334 | imageframe.origin.x += tx;
335 | imageframe.origin.y += ty;
336 | imageView.frame = imageframe;
337 |
338 | };
339 |
340 | void (^JCAffineTransformScale)(UIImageView*, CGFloat) = ^(UIImageView *imageView, CGFloat scale){
341 | CGRect imageBounds = imageView.bounds;
342 | imageBounds.size.width *= scale;
343 | imageBounds.size.height *= scale;
344 | imageView.bounds = imageBounds;
345 | };
346 |
347 | /**
348 | * 缩放比例 占据屏幕的3分之一
349 | */
350 | CGFloat scale = 0.33;
351 |
352 | /**
353 | * 动画时长
354 | */
355 | CGFloat duration = self.animationDuration;
356 |
357 | self.animating = YES;
358 |
359 | /**
360 | * 通知代理开始动画
361 | */
362 | if ([self.animationDelegate respondsToSelector:@selector(scrollViewDidBeginAnimating:)]) {
363 | [self.animationDelegate scrollViewDidBeginAnimating:self];
364 | }
365 |
366 | [UIView animateWithDuration:duration animations:^{
367 |
368 | for (UIImageView *imageView in self.imageViews) {
369 |
370 | if (self.currentIndex == [self.imageViews indexOfObject:imageView]) {
371 |
372 | JCAffineTransformScale(imageView,scale);
373 |
374 | } else {
375 |
376 | switch (self.scrollDirection) {
377 | case JCScrollViewScrollDirectionHorizontal:
378 |
379 | JCAffineTransformTranslate(imageView,(self.contentOffset.x - imageView.frame.origin.x) * 0.65,0);
380 |
381 | break;
382 | case JCScrollViewScrollDirectionVertical:
383 |
384 | JCAffineTransformTranslate(imageView,0,(self.contentOffset.y - imageView.frame.origin.y) * 0.65);
385 |
386 | break;
387 | default:
388 | break;
389 | }
390 | }
391 | }
392 |
393 | } completion:^(BOOL finished) {
394 |
395 | [UIView animateWithDuration:duration animations:^{
396 |
397 | for (UIImageView *imageView in self.imageViews) {
398 |
399 | if (self.currentIndex == [self.imageViews indexOfObject:imageView]) {
400 |
401 | continue;
402 |
403 | } else {
404 |
405 | /**
406 | * 适配IOS8, IOS8中调用UIView动画连续调用两个不同的transform会有卡顿
407 | */
408 | JCAffineTransformScale(imageView,scale);
409 | }
410 | }
411 |
412 | //第三步,乾坤大挪移
413 | } completion:^(BOOL finished) {
414 | //如果方向没有改变,恢复,退出
415 | if (self.scrollDirection == direction) {
416 |
417 | [UIView animateWithDuration:duration animations:^{
418 | for (UIImageView *imageView in self.imageViews) {
419 |
420 | JCAffineTransformScale(imageView, 1/scale);
421 |
422 | switch (self.scrollDirection) {
423 | case JCScrollViewScrollDirectionHorizontal:
424 | {
425 | NSInteger currentPage = (imageView.frame.origin.x-self.bounds.size.width*self.pageControl.currentPage) / (self.bounds.size.width*scale);
426 | currentPage += self.pageControl.currentPage;
427 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,imageView.frame.origin.y},imageView.bounds.size};
428 | break;
429 | }
430 | case JCScrollViewScrollDirectionVertical:
431 | {
432 | NSInteger currentPage = (imageView.frame.origin.y-self.bounds.size.height*self.pageControl.currentPage) / (self.bounds.size.height*scale);
433 | currentPage += self.pageControl.currentPage;
434 | imageView.frame = (CGRect){{imageView.frame.origin.x,currentPage * self.bounds.size.height},imageView.bounds.size};
435 |
436 | break;
437 | }
438 | default:
439 | break;
440 | }
441 |
442 | }
443 | }completion:^(BOOL finished) {
444 | self.animating = NO;
445 | if ([self.animationDelegate respondsToSelector:@selector(scrollViewDidEndAnimating:)]) {
446 | [self.animationDelegate scrollViewDidEndAnimating:self];
447 | }
448 | }];
449 |
450 | return;
451 | }
452 |
453 | //能来到这里说明方向不同
454 | _scrollDirection = direction;
455 |
456 | [UIView animateWithDuration:duration animations:^{
457 |
458 | CGFloat paddingV = 6.5;
459 | CGFloat paddingH = 11.5;
460 | CGFloat padding = 0;
461 | NSInteger flag = 0;
462 | for (UIImageView *imageView in self.imageViews) {
463 | //当前显示的这张不变
464 | if (self.currentIndex == [self.imageViews indexOfObject:imageView]) {
465 |
466 | continue;
467 |
468 | } else {
469 | //要切换成哪个方向
470 | switch (direction) {
471 | case JCScrollViewScrollDirectionHorizontal:
472 | {
473 |
474 | flag = imageView.frame.origin.y > self.contentOffset.y ? 1 : -1;
475 |
476 | padding = paddingH;
477 |
478 | break;
479 | }
480 | case JCScrollViewScrollDirectionVertical:
481 | {
482 |
483 | flag = imageView.frame.origin.x > self.contentOffset.x ? -1 : 1;
484 |
485 | padding = paddingV;
486 |
487 | break;
488 | }
489 |
490 | default:
491 | break;
492 | }
493 |
494 | JCAffineTransformTranslate(imageView,(imageView.bounds.size.width + padding)*flag,(-imageView.bounds.size.height - padding)*flag);
495 |
496 | }
497 |
498 | }
499 |
500 | } completion:^(BOOL finished) {
501 |
502 | [UIView animateWithDuration:duration animations:^{
503 | for (UIImageView *imageView in self.imageViews) {
504 |
505 | JCAffineTransformScale(imageView, 1/scale);
506 |
507 | switch (self.scrollDirection) {
508 | case JCScrollViewScrollDirectionHorizontal:
509 | {
510 | NSInteger currentPage = imageView.frame.origin.x / (self.bounds.size.width*scale);
511 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,imageView.frame.origin.y},imageView.bounds.size};
512 | break;
513 | }
514 | case JCScrollViewScrollDirectionVertical:
515 | {
516 | NSInteger currentPage = imageView.frame.origin.y / (self.bounds.size.height*scale);
517 | imageView.frame = (CGRect){{imageView.frame.origin.x,currentPage * self.bounds.size.height},imageView.bounds.size};
518 | break;
519 | }
520 | default:
521 | break;
522 | }
523 |
524 | }
525 | } completion:^(BOOL finished) {
526 |
527 | for (UIImageView *imageView in self.imageViews) {
528 |
529 | switch (self.scrollDirection) {
530 | case JCScrollViewScrollDirectionHorizontal:
531 | {
532 | NSInteger currentPage = imageView.frame.origin.x / self.bounds.size.width;
533 | currentPage += self.pageControl.currentPage;
534 | imageView.frame = (CGRect){{0,currentPage * self.bounds.size.height},imageView.bounds.size};
535 | break;
536 | }
537 | case JCScrollViewScrollDirectionVertical:
538 | {
539 | NSInteger currentPage = imageView.frame.origin.y / self.bounds.size.height;
540 | currentPage += self.pageControl.currentPage;
541 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,0},imageView.bounds.size};
542 | break;
543 | }
544 | default:
545 | break;
546 | }
547 |
548 |
549 | }
550 |
551 | [self convertImageViewsBetweenHorizontalAndVertical];
552 |
553 | self.animating = NO;
554 |
555 | if ([self.animationDelegate respondsToSelector:@selector(scrollViewDidEndAnimating:)]) {
556 | [self.animationDelegate scrollViewDidEndAnimating:self];
557 | }
558 | }];
559 |
560 | }];
561 |
562 | }];
563 |
564 | }];
565 |
566 | }
567 |
568 | - (instancetype)initWithCoder:(NSCoder *)coder
569 | {
570 | self = [super initWithCoder:coder];
571 | if (self) {
572 | [self setup];
573 | }
574 | return self;
575 | }
576 |
577 | - (id)initWithFrame:(CGRect)frame
578 | {
579 | if (self = [super initWithFrame:frame]) {
580 | [self setup];
581 | }
582 | return self;
583 | }
584 |
585 | - (void)setup {
586 | self.currentIndex = 1;
587 | self.bounces = NO;
588 | self.showsHorizontalScrollIndicator = NO;
589 | self.showsVerticalScrollIndicator = NO;
590 | self.pagingEnabled = YES;
591 | self.imageNames = [NSMutableArray array];
592 | self.animationDuration = 1;
593 | self.pageControlEnabled = YES;
594 | // _scrollDirection = JCScrollViewScrollDirectionVertical;
595 | }
596 |
597 | - (void)layoutSubviews {
598 | [super layoutSubviews];
599 | [self imageViews];
600 | CGFloat pageControlW = self.bounds.size.width;
601 | CGFloat pageControlH = self.bounds.size.height * 0.1;
602 | CGFloat pageControlX = self.frame.origin.x;
603 | CGFloat pageControlY = self.bounds.size.height - pageControlH * 1.5;
604 | self.pageControl.frame = CGRectMake(pageControlX, pageControlY, pageControlW, pageControlH);
605 |
606 | if (self.pageControlEnabled)
607 | [self.superview addSubview:self.pageControl];
608 | }
609 |
610 | //direction Next -1 Previous 1
611 | - (void)moveImageViewWithDirection:(JCScrollViewMoveDirection)direction{
612 |
613 | NSInteger preIndex = self.currentIndex + direction;
614 | if (preIndex == 3)
615 | preIndex = 0;
616 | else if (preIndex == -1)
617 | preIndex = 2;
618 |
619 | NSInteger offset = _pageControl.currentPage - direction;
620 |
621 | self.currentIndex-=direction;
622 |
623 | //把前一张或后一张移动
624 | [self setImageWithImageIndex:preIndex andImageNameIndex:offset];
625 | }
626 |
627 | - (void)setImageWithImageIndex:(NSInteger)imageIndex andImageNameIndex:(NSInteger)nameIndex {
628 | if (self.imageNames.count < 3) {
629 | return;
630 | }
631 | UIImageView *imageView = self.imageViews[imageIndex];
632 | CGRect imageRect = imageView.frame;
633 |
634 | switch (_scrollDirection) {
635 | case JCScrollViewScrollDirectionHorizontal:
636 |
637 | imageRect.origin.x = (nameIndex) * self.bounds.size.width;
638 |
639 | break;
640 | case JCScrollViewScrollDirectionVertical:
641 |
642 | imageRect.origin.y = (nameIndex) * self.bounds.size.height;
643 |
644 | break;
645 |
646 | default:
647 | break;
648 | }
649 |
650 | imageView.frame = imageRect;
651 |
652 | if (nameIndex < self.imageNames.count && nameIndex >= 0) {
653 | imageView.image = [UIImage imageNamed:self.imageNames[nameIndex]];
654 | }
655 |
656 | }
657 |
658 | @end
659 |
--------------------------------------------------------------------------------
/Demo/JCScrollView/JCScrollView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JCScrollView.m
3 | // JCScrollView
4 | //
5 | // Created by JayChou on 14-10-27.
6 | // Copyright (c) 2014年 zys. All rights reserved.
7 | //
8 |
9 | #import "JCScrollView.h"
10 |
11 | //direction Next -1 Previous 1便于后面计算
12 | typedef enum {
13 | JCScrollViewMoveDirectionNext = -1,
14 | JCScrollViewMoveDirectionPrevious = 1
15 | }JCScrollViewMoveDirection;
16 |
17 | @interface JCScrollView ()
18 |
19 | /**
20 | * 循环利用imageView数组
21 | */
22 | @property (nonatomic, strong)NSArray *imageViews;
23 |
24 | /**
25 | * 记录当前的索引
26 | */
27 | @property (nonatomic, assign)NSInteger currentIndex;
28 |
29 | /**
30 | * 图片数组
31 | */
32 | @property (nonatomic, strong)NSMutableArray *imageNames;
33 |
34 | @end
35 |
36 | @implementation JCScrollView
37 |
38 | + (instancetype)scrollViewWithFrame:(CGRect)frame andImageNames:(NSArray *)imageNames {
39 | JCScrollView *jcSV = [[JCScrollView alloc]initWithFrame:frame];
40 | jcSV.imageNames = [NSMutableArray arrayWithArray:imageNames];
41 | return jcSV;
42 | }
43 |
44 | - (void)setCurrentIndex:(NSInteger)currentIndex {
45 | if (currentIndex == 3) {
46 | currentIndex = 0;
47 | } else if (currentIndex == -1) {
48 | currentIndex = 2;
49 | }
50 | _currentIndex = currentIndex;
51 | }
52 |
53 | - (void)setScrollDirection:(JCScrollViewScrollDirection)scrollDirection {
54 | if (_scrollDirection == scrollDirection) return;
55 |
56 | [self setScrollDirection:scrollDirection animated:NO];
57 |
58 | _scrollDirection = scrollDirection;
59 | }
60 |
61 | - (void)setPageControlEnabled:(BOOL)pageControlEnabled {
62 |
63 | if(_pageControlEnabled == pageControlEnabled) return;
64 |
65 | if(pageControlEnabled)
66 | [self.superview addSubview:self.pageControl];
67 | else
68 | [self.pageControl removeFromSuperview];
69 |
70 | _pageControlEnabled = pageControlEnabled;
71 | }
72 |
73 | - (void)setContentOffset:(CGPoint)contentOffset {
74 |
75 | [super setContentOffset:contentOffset];
76 |
77 | NSUInteger prePage = self.pageControl.currentPage;
78 |
79 | switch (_scrollDirection) {
80 | case JCScrollViewScrollDirectionHorizontal:
81 |
82 | _pageControl.currentPage = contentOffset.x / self.bounds.size.width + 0.5;
83 |
84 | break;
85 |
86 | case JCScrollViewScrollDirectionVertical:
87 |
88 | _pageControl.currentPage = contentOffset.y / self.bounds.size.height + 0.5;
89 |
90 | break;
91 | default:
92 | break;
93 | }
94 |
95 | if (_pageControl.currentPage > prePage) { //图片向前走
96 |
97 | [self moveImageViewWithDirection:JCScrollViewMoveDirectionNext];
98 |
99 | } else if (_pageControl.currentPage < prePage) {
100 |
101 | [self moveImageViewWithDirection:JCScrollViewMoveDirectionPrevious];
102 |
103 | }
104 |
105 | }
106 |
107 | - (NSArray *)imageViews {
108 | if (!_imageViews) {
109 |
110 | NSMutableArray *imageViews = [NSMutableArray array];
111 |
112 | /**
113 | * 如果图片数量小于3张,就只创建图片数量的imageView
114 | */
115 | NSInteger count = self.imageNames.count < 3 ? self.imageNames.count + 1 : 3;
116 | int startNum = self.imageNames.count < 3 ? 1 : 0;
117 | for (int i = startNum; i index) {
244 |
245 | self.currentIndex++;
246 | [self moveImageViewWithDirection:JCScrollViewMoveDirectionPrevious];
247 |
248 | //插入的图片那正好是当前图片
249 | } else if (self.pageControl.currentPage == index) {
250 |
251 | [self setImageWithImageIndex:self.currentIndex andImageNameIndex:index];
252 |
253 | }
254 |
255 | }
256 |
257 | /**
258 | * 转换垂直或水平滚动时子控件重新布局
259 | */
260 | - (void)convertImageViewsBetweenHorizontalAndVertical {
261 |
262 | for (UIImageView *imageView in self.imageViews) {
263 | //只改变当前这张
264 |
265 | //还原一下尺寸
266 | // imageView.transform = CGAffineTransformIdentity;
267 |
268 | switch (self.scrollDirection) {
269 | case JCScrollViewScrollDirectionHorizontal:
270 | //来到这里的imageView说明以前是垂直的,也就是说x为0 y有值,那么就转换一下
271 | {
272 | NSInteger currentPage = imageView.frame.origin.y / self.bounds.size.height;
273 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,0},imageView.bounds.size};
274 | // NSLog(@"%@",NSStringFromCGRect(imageView.frame));
275 | break;
276 | }
277 | case JCScrollViewScrollDirectionVertical:
278 | {
279 | NSInteger currentPage = imageView.frame.origin.x / self.bounds.size.width;
280 | imageView.frame = (CGRect){{0,currentPage * self.bounds.size.height},imageView.bounds.size};
281 | break;
282 | }
283 | default:
284 | break;
285 | }
286 |
287 | }
288 |
289 | //要同时进行,不知不觉中切换,暗度陈仓
290 | switch (self.scrollDirection) {
291 | case JCScrollViewScrollDirectionHorizontal:
292 |
293 | [self setContentOffset:CGPointMake(self.pageControl.currentPage * self.bounds.size.width, 0)];
294 |
295 | break;
296 |
297 | case JCScrollViewScrollDirectionVertical:
298 |
299 | [self setContentOffset:CGPointMake(0, self.pageControl.currentPage * self.bounds.size.height)];
300 |
301 | break;
302 |
303 | default:
304 | break;
305 | }
306 |
307 | [self resizeContentWithIndex:-1];
308 | }
309 |
310 | /**
311 | * 动态切换滚动方向
312 | *
313 | * @param direction 方向
314 | * @param animated 是否执行动画
315 | */
316 | - (void)setScrollDirection:(JCScrollViewScrollDirection)direction animated:(BOOL)animated {
317 |
318 | if (!animated) {
319 | /**
320 | * 方向相同不执行
321 | */
322 | if (_scrollDirection == direction) return;
323 | _scrollDirection = direction;
324 | [self convertImageViewsBetweenHorizontalAndVertical];
325 | return;
326 | }
327 |
328 | if (self.isAnimating)
329 | return;
330 |
331 | void (^JCAffineTransformTranslate)(UIImageView*, CGFloat, CGFloat) = ^(UIImageView *imageView, CGFloat tx, CGFloat ty){
332 |
333 | CGRect imageframe = imageView.frame;
334 | imageframe.origin.x += tx;
335 | imageframe.origin.y += ty;
336 | imageView.frame = imageframe;
337 |
338 | };
339 |
340 | void (^JCAffineTransformScale)(UIImageView*, CGFloat) = ^(UIImageView *imageView, CGFloat scale){
341 | CGRect imageBounds = imageView.bounds;
342 | imageBounds.size.width *= scale;
343 | imageBounds.size.height *= scale;
344 | imageView.bounds = imageBounds;
345 | };
346 |
347 | /**
348 | * 缩放比例 占据屏幕的3分之一
349 | */
350 | CGFloat scale = 0.33;
351 |
352 | /**
353 | * 动画时长
354 | */
355 | CGFloat duration = self.animationDuration;
356 |
357 | self.animating = YES;
358 |
359 | /**
360 | * 通知代理开始动画
361 | */
362 | if ([self.animationDelegate respondsToSelector:@selector(scrollViewDidBeginAnimating:)]) {
363 | [self.animationDelegate scrollViewDidBeginAnimating:self];
364 | }
365 |
366 | [UIView animateWithDuration:duration animations:^{
367 |
368 | for (UIImageView *imageView in self.imageViews) {
369 |
370 | if (self.currentIndex == [self.imageViews indexOfObject:imageView]) {
371 |
372 | JCAffineTransformScale(imageView,scale);
373 |
374 | } else {
375 |
376 | switch (self.scrollDirection) {
377 | case JCScrollViewScrollDirectionHorizontal:
378 |
379 | JCAffineTransformTranslate(imageView,(self.contentOffset.x - imageView.frame.origin.x) * 0.65,0);
380 |
381 | break;
382 | case JCScrollViewScrollDirectionVertical:
383 |
384 | JCAffineTransformTranslate(imageView,0,(self.contentOffset.y - imageView.frame.origin.y) * 0.65);
385 |
386 | break;
387 | default:
388 | break;
389 | }
390 | }
391 | }
392 |
393 | } completion:^(BOOL finished) {
394 |
395 | [UIView animateWithDuration:duration animations:^{
396 |
397 | for (UIImageView *imageView in self.imageViews) {
398 |
399 | if (self.currentIndex == [self.imageViews indexOfObject:imageView]) {
400 |
401 | continue;
402 |
403 | } else {
404 |
405 | /**
406 | * 适配IOS8, IOS8中调用UIView动画连续调用两个不同的transform会有卡顿
407 | */
408 | JCAffineTransformScale(imageView,scale);
409 | }
410 | }
411 |
412 | //第三步,乾坤大挪移
413 | } completion:^(BOOL finished) {
414 | //如果方向没有改变,恢复,退出
415 | if (self.scrollDirection == direction) {
416 |
417 | [UIView animateWithDuration:duration animations:^{
418 | for (UIImageView *imageView in self.imageViews) {
419 |
420 | JCAffineTransformScale(imageView, 1/scale);
421 |
422 | switch (self.scrollDirection) {
423 | case JCScrollViewScrollDirectionHorizontal:
424 | {
425 | NSInteger currentPage = (imageView.frame.origin.x-self.bounds.size.width*self.pageControl.currentPage) / (self.bounds.size.width*scale);
426 | currentPage += self.pageControl.currentPage;
427 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,imageView.frame.origin.y},imageView.bounds.size};
428 | break;
429 | }
430 | case JCScrollViewScrollDirectionVertical:
431 | {
432 | NSInteger currentPage = (imageView.frame.origin.y-self.bounds.size.height*self.pageControl.currentPage) / (self.bounds.size.height*scale);
433 | currentPage += self.pageControl.currentPage;
434 | imageView.frame = (CGRect){{imageView.frame.origin.x,currentPage * self.bounds.size.height},imageView.bounds.size};
435 |
436 | break;
437 | }
438 | default:
439 | break;
440 | }
441 |
442 | }
443 | }completion:^(BOOL finished) {
444 | self.animating = NO;
445 | if ([self.animationDelegate respondsToSelector:@selector(scrollViewDidEndAnimating:)]) {
446 | [self.animationDelegate scrollViewDidEndAnimating:self];
447 | }
448 | }];
449 |
450 | return;
451 | }
452 |
453 | //能来到这里说明方向不同
454 | _scrollDirection = direction;
455 |
456 | [UIView animateWithDuration:duration animations:^{
457 |
458 | CGFloat paddingV = 6.5;
459 | CGFloat paddingH = 11.5;
460 | CGFloat padding = 0;
461 | NSInteger flag = 0;
462 | for (UIImageView *imageView in self.imageViews) {
463 | //当前显示的这张不变
464 | if (self.currentIndex == [self.imageViews indexOfObject:imageView]) {
465 |
466 | continue;
467 |
468 | } else {
469 | //要切换成哪个方向
470 | switch (direction) {
471 | case JCScrollViewScrollDirectionHorizontal:
472 | {
473 |
474 | flag = imageView.frame.origin.y > self.contentOffset.y ? 1 : -1;
475 |
476 | padding = paddingH;
477 |
478 | break;
479 | }
480 | case JCScrollViewScrollDirectionVertical:
481 | {
482 |
483 | flag = imageView.frame.origin.x > self.contentOffset.x ? -1 : 1;
484 |
485 | padding = paddingV;
486 |
487 | break;
488 | }
489 |
490 | default:
491 | break;
492 | }
493 |
494 | JCAffineTransformTranslate(imageView,(imageView.bounds.size.width + padding)*flag,(-imageView.bounds.size.height - padding)*flag);
495 |
496 | }
497 |
498 | }
499 |
500 | } completion:^(BOOL finished) {
501 |
502 | [UIView animateWithDuration:duration animations:^{
503 | for (UIImageView *imageView in self.imageViews) {
504 |
505 | JCAffineTransformScale(imageView, 1/scale);
506 |
507 | switch (self.scrollDirection) {
508 | case JCScrollViewScrollDirectionHorizontal:
509 | {
510 | NSInteger currentPage = imageView.frame.origin.x / (self.bounds.size.width*scale);
511 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,imageView.frame.origin.y},imageView.bounds.size};
512 | break;
513 | }
514 | case JCScrollViewScrollDirectionVertical:
515 | {
516 | NSInteger currentPage = imageView.frame.origin.y / (self.bounds.size.height*scale);
517 | imageView.frame = (CGRect){{imageView.frame.origin.x,currentPage * self.bounds.size.height},imageView.bounds.size};
518 | break;
519 | }
520 | default:
521 | break;
522 | }
523 |
524 | }
525 | } completion:^(BOOL finished) {
526 |
527 | for (UIImageView *imageView in self.imageViews) {
528 |
529 | switch (self.scrollDirection) {
530 | case JCScrollViewScrollDirectionHorizontal:
531 | {
532 | NSInteger currentPage = imageView.frame.origin.x / self.bounds.size.width;
533 | currentPage += self.pageControl.currentPage;
534 | imageView.frame = (CGRect){{0,currentPage * self.bounds.size.height},imageView.bounds.size};
535 | break;
536 | }
537 | case JCScrollViewScrollDirectionVertical:
538 | {
539 | NSInteger currentPage = imageView.frame.origin.y / self.bounds.size.height;
540 | currentPage += self.pageControl.currentPage;
541 | imageView.frame = (CGRect){{currentPage * self.bounds.size.width,0},imageView.bounds.size};
542 | break;
543 | }
544 | default:
545 | break;
546 | }
547 |
548 |
549 | }
550 |
551 | [self convertImageViewsBetweenHorizontalAndVertical];
552 |
553 | self.animating = NO;
554 |
555 | if ([self.animationDelegate respondsToSelector:@selector(scrollViewDidEndAnimating:)]) {
556 | [self.animationDelegate scrollViewDidEndAnimating:self];
557 | }
558 | }];
559 |
560 | }];
561 |
562 | }];
563 |
564 | }];
565 |
566 | }
567 |
568 | - (instancetype)initWithCoder:(NSCoder *)coder
569 | {
570 | self = [super initWithCoder:coder];
571 | if (self) {
572 | [self setup];
573 | }
574 | return self;
575 | }
576 |
577 | - (id)initWithFrame:(CGRect)frame
578 | {
579 | if (self = [super initWithFrame:frame]) {
580 | [self setup];
581 | }
582 | return self;
583 | }
584 |
585 | - (void)setup {
586 | self.currentIndex = 1;
587 | self.bounces = NO;
588 | self.showsHorizontalScrollIndicator = NO;
589 | self.showsVerticalScrollIndicator = NO;
590 | self.pagingEnabled = YES;
591 | self.imageNames = [NSMutableArray array];
592 | self.animationDuration = 1;
593 | self.pageControlEnabled = YES;
594 | // _scrollDirection = JCScrollViewScrollDirectionVertical;
595 | }
596 |
597 | - (void)layoutSubviews {
598 | [super layoutSubviews];
599 | [self imageViews];
600 | CGFloat pageControlW = self.bounds.size.width;
601 | CGFloat pageControlH = self.bounds.size.height * 0.1;
602 | CGFloat pageControlX = self.frame.origin.x;
603 | CGFloat pageControlY = self.bounds.size.height - pageControlH * 1.5;
604 | self.pageControl.frame = CGRectMake(pageControlX, pageControlY, pageControlW, pageControlH);
605 |
606 | if (self.pageControlEnabled)
607 | [self.superview addSubview:self.pageControl];
608 | }
609 |
610 | //direction Next -1 Previous 1
611 | - (void)moveImageViewWithDirection:(JCScrollViewMoveDirection)direction{
612 |
613 | NSInteger preIndex = self.currentIndex + direction;
614 | if (preIndex == 3)
615 | preIndex = 0;
616 | else if (preIndex == -1)
617 | preIndex = 2;
618 |
619 | NSInteger offset = _pageControl.currentPage - direction;
620 |
621 | self.currentIndex-=direction;
622 |
623 | //把前一张或后一张移动
624 | [self setImageWithImageIndex:preIndex andImageNameIndex:offset];
625 | }
626 |
627 | - (void)setImageWithImageIndex:(NSInteger)imageIndex andImageNameIndex:(NSInteger)nameIndex {
628 | if (self.imageNames.count < 3) {
629 | return;
630 | }
631 | UIImageView *imageView = self.imageViews[imageIndex];
632 | CGRect imageRect = imageView.frame;
633 |
634 | switch (_scrollDirection) {
635 | case JCScrollViewScrollDirectionHorizontal:
636 |
637 | imageRect.origin.x = (nameIndex) * self.bounds.size.width;
638 |
639 | break;
640 | case JCScrollViewScrollDirectionVertical:
641 |
642 | imageRect.origin.y = (nameIndex) * self.bounds.size.height;
643 |
644 | break;
645 |
646 | default:
647 | break;
648 | }
649 |
650 | imageView.frame = imageRect;
651 |
652 | if (nameIndex < self.imageNames.count && nameIndex >= 0) {
653 | imageView.image = [UIImage imageNamed:self.imageNames[nameIndex]];
654 | }
655 |
656 | }
657 |
658 | @end
659 |
--------------------------------------------------------------------------------