├── .gitignore
├── .travis.yml
├── AddCustomLayout.png
├── ExampleProject
├── Cartfile
├── Cartfile.resolved
├── ExampleProject
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ ├── DeleteX.imageset
│ │ │ ├── Contents.json
│ │ │ ├── DeleteX.png
│ │ │ └── DeleteX@2x.png
│ │ ├── Disliked.imageset
│ │ │ ├── Contents.json
│ │ │ ├── Disliked.png
│ │ │ └── Disliked@2x.png
│ │ ├── Liked.imageset
│ │ │ ├── Contents.json
│ │ │ ├── Liked.png
│ │ │ └── Liked@2x.png
│ │ ├── Profile1.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile1.png
│ │ ├── Profile2.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile2.png
│ │ ├── Profile3.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile3.png
│ │ ├── Profile4.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile4.png
│ │ ├── Profile5.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile5.png
│ │ ├── Profile6.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile6.png
│ │ ├── Profile7.imageset
│ │ │ ├── Contents.json
│ │ │ └── Profile7.png
│ │ ├── ProfileMe.imageset
│ │ │ ├── Contents.json
│ │ │ ├── ProfileMe.png
│ │ │ └── ProfileMe@2x.png
│ │ └── Tick.imageset
│ │ │ ├── Contents.json
│ │ │ ├── Tick.png
│ │ │ └── Tick@2x.png
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Card.swift
│ ├── CardCollectionViewCell.swift
│ ├── CardCollectionViewCell.xib
│ ├── CardViewController.swift
│ ├── Cards.plist
│ ├── ColorExtensions.swift
│ └── Info.plist
└── SwipingCards.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ └── contents.xcworkspacedata
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── SwipingCarousel
│ ├── Info.plist
│ ├── Swiping Carousel.h
│ ├── SwipingCarouselCellManager.swift
│ ├── SwipingCarouselCollectionViewCell.swift
│ └── SwipingCarouselFlowLayout.swift
├── Swiping-Carousel-Demo.gif
├── SwipingCarousel.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── Swiping Carousel.xcscheme
└── Tests
└── SwipingCarouselTests
├── Info.plist
└── SwipingCarouselTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 | .DS_Store
5 | /.build
6 |
7 | ## Other
8 | *.xcuserstate
9 | xcuserdata/
10 |
11 | # Swift Package Manager
12 | #
13 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
14 | # Packages/
15 | /*.xcodeproj
16 | .swiftpm
17 |
18 | # Carthage
19 | #
20 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
21 | # Carthage/Checkouts
22 |
23 | ExampleProject/Carthage/
24 | Carthage/
25 | /*.framework.zip
26 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode11.2
3 | script:
4 | - xcodebuild clean test -project "SwipingCarousel.xcodeproj" -scheme "Swiping Carousel" -destination "platform=iOS Simulator,name=iPhone 11,OS=13.2.2" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO ONLY_ACTIVE_ARCH=NO -quiet
5 |
--------------------------------------------------------------------------------
/AddCustomLayout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/AddCustomLayout.png
--------------------------------------------------------------------------------
/ExampleProject/Cartfile:
--------------------------------------------------------------------------------
1 | github "ppacie/SwipingCarousel"
2 |
--------------------------------------------------------------------------------
/ExampleProject/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "ppacie/SwipingCarousel" "1.5"
2 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ExampleProject
4 | //
5 | // Created by Pablo Paciello on 10/27/16.
6 | // Copyright © 2016 PPacie. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 | var window: UIWindow?
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.lightContent, animated: true)
18 | return true
19 | }
20 |
21 | func applicationWillResignActive(_ application: UIApplication) {
22 | // 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.
23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
24 | }
25 |
26 | func applicationDidEnterBackground(_ application: UIApplication) {
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 | func applicationWillEnterForeground(_ application: UIApplication) {
32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
33 | }
34 |
35 | func applicationDidBecomeActive(_ application: UIApplication) {
36 | // 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.
37 | }
38 |
39 | func applicationWillTerminate(_ application: UIApplication) {
40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/DeleteX.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "DeleteX.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "DeleteX@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/DeleteX.imageset/DeleteX.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/DeleteX.imageset/DeleteX.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/DeleteX.imageset/DeleteX@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/DeleteX.imageset/DeleteX@2x.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Disliked.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Disliked.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Disliked@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Disliked.imageset/Disliked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Disliked.imageset/Disliked.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Disliked.imageset/Disliked@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Disliked.imageset/Disliked@2x.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Liked.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Liked.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Liked@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Liked.imageset/Liked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Liked.imageset/Liked.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Liked.imageset/Liked@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Liked.imageset/Liked@2x.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile1.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile1.imageset/Profile1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile1.imageset/Profile1.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile2.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile2.imageset/Profile2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile2.imageset/Profile2.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile3.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile3.imageset/Profile3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile3.imageset/Profile3.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile4.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile4.imageset/Profile4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile4.imageset/Profile4.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile5.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile5.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile5.imageset/Profile5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile5.imageset/Profile5.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile6.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile6.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile6.imageset/Profile6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile6.imageset/Profile6.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile7.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Profile7.png",
6 | "scale" : "1x"
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 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Profile7.imageset/Profile7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Profile7.imageset/Profile7.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/ProfileMe.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "ProfileMe.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "ProfileMe@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/ProfileMe.imageset/ProfileMe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/ProfileMe.imageset/ProfileMe.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/ProfileMe.imageset/ProfileMe@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/ProfileMe.imageset/ProfileMe@2x.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Tick.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Tick.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Tick@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Tick.imageset/Tick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Tick.imageset/Tick.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Assets.xcassets/Tick.imageset/Tick@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/ExampleProject/ExampleProject/Assets.xcassets/Tick.imageset/Tick@2x.png
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/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 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Card.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Card.swift
3 | // Swiping Cards
4 | //
5 | // Created by Pablo Paciello on 8/20/15.
6 | // Copyright (c) 2015 Pablo Paciello. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | struct Card {
12 | let image: UIImage
13 | let name: String
14 | let profession: String
15 | let mainDescription: String
16 | let activity: String
17 | let backgroundColor: UIColor
18 | var likedCard: Bool
19 |
20 | init(dictionary: NSDictionary) {
21 | self.image = UIImage(named: (dictionary["Image"] as! String))!
22 | self.name = dictionary["Name"] as! String
23 | self.profession = dictionary["Profession"] as! String
24 | self.mainDescription = dictionary["Description"] as! String
25 | self.activity = dictionary["Activity"] as! String
26 | self.backgroundColor = UIColor.random
27 | self.likedCard = dictionary["Liked"] as! Bool
28 | }
29 |
30 | //Load some demo information into the [savedCards] Array.
31 | static func loadCards() -> [Card] {
32 | var savedCards = [Card]()
33 | if let URL = Bundle.main.url(forResource: "Cards", withExtension: "plist") {
34 | if let cardsFromPlist = NSArray(contentsOf: URL) {
35 | for card in cardsFromPlist{
36 | let newCard = Card(dictionary: card as! NSDictionary)
37 | savedCards.append(newCard)
38 | }
39 | }
40 | }
41 | return savedCards
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/CardCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CardCollectionViewCell.swift
3 | // ExampleProject
4 | //
5 | // Created by Pablo Paciello on 10/27/16.
6 | // Copyright © 2016 PPacie. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwipingCarousel
11 |
12 | class CardCollectionViewCell: SwipingCarouselCollectionViewCell {
13 | @IBOutlet weak var profileImage: UIImageView!
14 | @IBOutlet weak var nameLabel: UILabel!
15 | @IBOutlet weak var professionLabel: UILabel!
16 | @IBOutlet weak var mainDescriptionLabel: UILabel!
17 | @IBOutlet weak var activityLabel: UILabel!
18 | @IBOutlet weak var likeImage: UIImageView!
19 |
20 | static let reuseIdentifier = "CardCollectionViewCell"
21 | static var nib: UINib {
22 | get {
23 | return UINib(nibName: "CardCollectionViewCell", bundle: nil)
24 | }
25 | }
26 |
27 | override func awakeFromNib() {
28 | super.awakeFromNib()
29 | // Cell Corner and Shadows
30 | layer.masksToBounds = false
31 | layer.cornerRadius = 10
32 | layer.shadowRadius = 5
33 | layer.shadowOpacity = 0.6
34 | // Emphasize the shadow on the bottom and right sides of the cell
35 | layer.shadowOffset = CGSize(width: 4, height: 4)
36 | }
37 |
38 | func populateWith(card: Card) {
39 | profileImage.image = card.image
40 | nameLabel.text = card.name
41 | professionLabel.text = card.profession
42 | mainDescriptionLabel.text = card.mainDescription
43 | activityLabel.text = card.activity
44 | backgroundColor = card.backgroundColor
45 | likeImage.image = card.likedCard ? UIImage(named: "Liked") : UIImage(named:"Disliked")
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/CardCollectionViewCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
32 |
33 |
34 |
35 |
36 |
37 |
43 |
51 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/CardViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CardViewController.swift
3 | // ExampleProject
4 | //
5 | // Created by Pablo Paciello on 10/27/16.
6 | // Copyright © 2016 PPacie. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwipingCarousel
11 |
12 | class CardViewController: UIViewController {
13 | @IBOutlet weak var collectionView: UICollectionView! { didSet {
14 | collectionView.register(CardCollectionViewCell.nib, forCellWithReuseIdentifier: CardCollectionViewCell.reuseIdentifier)
15 | }
16 | }
17 |
18 | // Load allTheCards from SavedCards Class.
19 | private var allTheCards = Card.loadCards()
20 | private let segueIdentifier = "OpenChat"
21 | }
22 | // MARK: UICollectionView DataSource
23 | extension CardViewController: UICollectionViewDataSource, UICollectionViewDelegate {
24 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
25 | //Return the number of items in the section
26 | return allTheCards.count
27 | }
28 |
29 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
30 |
31 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CardCollectionViewCell.reuseIdentifier, for: indexPath) as! CardCollectionViewCell
32 |
33 | // Configure the cell
34 | cell.populateWith(card: allTheCards[(indexPath as NSIndexPath).row])
35 | cell.delegate = self
36 | cell.deleteOnSwipeDown = true
37 | return cell
38 | }
39 |
40 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
41 | if let cell = collectionView.cellForItem(at: indexPath) {
42 | //We check if the selected Card is the one in the middle to open the chat. If it's not, we scroll to the selected side card.
43 | if cell.frame.size.height > cell.bounds.size.height {
44 | performSegue(withIdentifier: segueIdentifier, sender: Any?.self)
45 | } else {
46 | collectionView.scrollToItem(at: indexPath, at: UICollectionView.ScrollPosition.centeredHorizontally, animated: true)
47 | }
48 | }
49 | }
50 | }
51 | // MARK: Conform to the SwipingCarousel Delegate
52 | extension CardViewController: SwipingCarouselDelegate {
53 | func cellSwipedUp(_ cell: UICollectionViewCell) {
54 | guard let cell = cell as? CardCollectionViewCell else { return }
55 | print("Swiped Up - Card to Like/Dislike: \(cell.nameLabel.text!)")
56 | //Get the IndexPath from Cell being passed (swiped up).
57 | if let indexPath = collectionView?.indexPath(for: cell) {
58 | //Change the Like status to Like/Dislike.
59 | allTheCards[(indexPath as NSIndexPath).row].likedCard = !allTheCards[(indexPath as NSIndexPath).row].likedCard
60 | // Update the Like Image
61 | cell.likeImage.image = allTheCards[(indexPath as NSIndexPath).row].likedCard ? UIImage(named: "Liked") : UIImage(named:"Disliked")
62 | //We are going to Scroll to the next item or to the previous one after Liking/Disliking a card.
63 | //So, we check if we ara at the end of the Array to know if we can scroll to the next item.
64 | if (indexPath as NSIndexPath).row+1 < allTheCards.count {
65 | let nextIndexPath = IndexPath(row: (indexPath as NSIndexPath).row + 1, section: 0)
66 | collectionView?.scrollToItem(at: nextIndexPath, at: UICollectionView.ScrollPosition.centeredHorizontally, animated: true)
67 | } else { //Otherwise, we scroll back to the previous one.
68 | let previousIndexPath = IndexPath(row: (indexPath as NSIndexPath).row - 1, section: 0)
69 | collectionView?.scrollToItem(at: previousIndexPath, at: UICollectionView.ScrollPosition.centeredHorizontally, animated: true)
70 | }
71 | }
72 | }
73 |
74 | func cellSwipedDown(_ cell: UICollectionViewCell) {
75 | guard let cell = cell as? CardCollectionViewCell else { return }
76 | print("Swiped Down - Card to Delete: \(cell.nameLabel.text!)")
77 | //Get the IndexPath from Cell being passed (swiped down).
78 | if let indexPath = collectionView?.indexPath(for: cell) {
79 | //Delete the swiped card from the Model.
80 | allTheCards.remove(at: (indexPath as NSIndexPath).row)
81 | //Delete the swiped card from CollectionView.
82 | collectionView?.deleteItems(at: [indexPath])
83 | //Delete cell from View.
84 | cell.removeFromSuperview()
85 | }
86 | }
87 | }
88 | // MARK: Set the size of the cards
89 | extension CardViewController: UICollectionViewDelegateFlowLayout {
90 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
91 | return CGSize(width: 230.0, height: 300.0)
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/Cards.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Name
7 | Nelson
8 | Image
9 | Profile2
10 | Profession
11 | Bogan
12 | Description
13 | Shoplifting is a victimless crime. Like punching someone in the dark.
14 | Activity
15 | 25m @Bart
16 | Liked
17 |
18 |
19 |
20 | Name
21 | Bart
22 | Image
23 | Profile1
24 | Profession
25 | Troublemaker
26 | Description
27 | Aren't we forgetting the true meaning of Christmas: the birth of Santa. I didn't do it. Ay caramba.
28 | Activity
29 | 25m @Nelson
30 | Liked
31 |
32 |
33 |
34 | Name
35 | Sideshow Bob
36 | Image
37 | Profile3
38 | Profession
39 | PhD
40 | Description
41 | I did once try to kill the world's greatest lover. But then I realized there are laws against suicide.
42 | Activity
43 | 42m @Edna
44 | Liked
45 |
46 |
47 |
48 | Name
49 | Homer J.
50 | Image
51 | Profile4
52 | Profession
53 | Beer Drinker
54 | Description
55 | Now, son, you don't want to drink beer. That's for daddies, and kids with fake IDs.
56 | Activity
57 | 15m @Moe
58 | Liked
59 |
60 |
61 |
62 | Name
63 | Steve
64 | Image
65 | Profile5
66 | Profession
67 | Apple Founder
68 | Description
69 | Your time is limited, so don't waste it living someone else's life. Stay hungry, stay foolish.
70 | Activity
71 | 2m @Tim
72 | Liked
73 |
74 |
75 |
76 | Name
77 | Krusty
78 | Image
79 | Profile6
80 | Profession
81 | Clown
82 | Description
83 | Ahh, there's nothing better than a cigarette... unless it's a cigarette lit with a hundred-dollar bill.
84 | Activity
85 | 17m @Monkey
86 | Liked
87 |
88 |
89 |
90 | Name
91 | Diego
92 | Image
93 | Profile7
94 | Profession
95 | Hand of God
96 | Description
97 | La pelota no se mancha. Se le escapó la torguga y LTA.
98 | Activity
99 | 10m @Guillote
100 | Liked
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/ColorExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ColorExtensions.swift
3 | // Swiping Cards
4 | //
5 | // Created by Pablo Paciello on 10/26/16.
6 | // Copyright © 2016 Pablo Paciello. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | //Function to create a color from RGB and Computed property to get a Random UIColor based on this UIColorFromRGB method.
12 | extension UIColor {
13 | class func colorFromRGB(_ r: Int, g: Int, b: Int) -> UIColor {
14 | return UIColor(red: CGFloat(Float(r) / 255), green: CGFloat(Float(g) / 255), blue: CGFloat(Float(b) / 255), alpha: 1)
15 | }
16 |
17 | class var random: UIColor {
18 | switch arc4random() % 13 {
19 | case 0: return UIColor.colorFromRGB(85, g: 0, b: 255)
20 | case 1: return UIColor.colorFromRGB(170, g: 0, b: 170)
21 | case 2: return UIColor.colorFromRGB(85, g: 170, b: 85)
22 | case 3: return UIColor.colorFromRGB(0, g: 85, b: 0)
23 | case 4: return UIColor.colorFromRGB(255, g: 170, b: 0)
24 | case 5: return UIColor.colorFromRGB(255, g: 85, b: 0)
25 | case 6: return UIColor.colorFromRGB(0, g: 85, b: 85)
26 | case 7: return UIColor.colorFromRGB(0, g: 85, b: 255)
27 | case 8: return UIColor.colorFromRGB(170, g: 170, b: 255)
28 | case 9: return UIColor.colorFromRGB(85, g: 0, b: 0)
29 | case 10: return UIColor.colorFromRGB(170, g: 85, b: 85)
30 | case 11: return UIColor.colorFromRGB(85, g: 170, b: 255)
31 | case 12: return UIColor.colorFromRGB(0, g: 170, b: 170)
32 | default : return UIColor.black //Not going to be called
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/ExampleProject/ExampleProject/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 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ExampleProject/SwipingCards.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 670501EA1DC2CA080057DC00 /* SwipingCarousel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 670501E91DC2CA080057DC00 /* SwipingCarousel.framework */; };
11 | 672AF5B823929F540004468D /* ColorExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672AF5B723929F540004468D /* ColorExtensions.swift */; };
12 | 67B016A71DC21CEC006EF53E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B016A61DC21CEC006EF53E /* AppDelegate.swift */; };
13 | 67B016A91DC21CEC006EF53E /* CardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B016A81DC21CEC006EF53E /* CardViewController.swift */; };
14 | 67B016AC1DC21CEC006EF53E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 67B016AA1DC21CEC006EF53E /* Main.storyboard */; };
15 | 67B016AE1DC21CEC006EF53E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67B016AD1DC21CEC006EF53E /* Assets.xcassets */; };
16 | 67B016B11DC21CEC006EF53E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 67B016AF1DC21CEC006EF53E /* LaunchScreen.storyboard */; };
17 | 67B016CE1DC2434C006EF53E /* Card.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B016CD1DC2434C006EF53E /* Card.swift */; };
18 | 67B016D31DC243FA006EF53E /* CardCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B016D11DC243FA006EF53E /* CardCollectionViewCell.swift */; };
19 | 67B016D41DC243FA006EF53E /* CardCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 67B016D21DC243FA006EF53E /* CardCollectionViewCell.xib */; };
20 | 67B016D81DC24419006EF53E /* Cards.plist in Resources */ = {isa = PBXBuildFile; fileRef = 67B016D71DC24419006EF53E /* Cards.plist */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXFileReference section */
24 | 670501E91DC2CA080057DC00 /* SwipingCarousel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwipingCarousel.framework; path = Carthage/Build/iOS/SwipingCarousel.framework; sourceTree = ""; };
25 | 672AF5B723929F540004468D /* ColorExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorExtensions.swift; sourceTree = ""; };
26 | 67B016A31DC21CEC006EF53E /* SwipingCards.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwipingCards.app; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 67B016A61DC21CEC006EF53E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
28 | 67B016A81DC21CEC006EF53E /* CardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardViewController.swift; sourceTree = ""; };
29 | 67B016AB1DC21CEC006EF53E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
30 | 67B016AD1DC21CEC006EF53E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
31 | 67B016B01DC21CEC006EF53E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
32 | 67B016B21DC21CEC006EF53E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | 67B016CD1DC2434C006EF53E /* Card.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Card.swift; sourceTree = ""; };
34 | 67B016D11DC243FA006EF53E /* CardCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardCollectionViewCell.swift; sourceTree = ""; };
35 | 67B016D21DC243FA006EF53E /* CardCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CardCollectionViewCell.xib; sourceTree = ""; };
36 | 67B016D71DC24419006EF53E /* Cards.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Cards.plist; sourceTree = ""; };
37 | /* End PBXFileReference section */
38 |
39 | /* Begin PBXFrameworksBuildPhase section */
40 | 67B016A01DC21CEC006EF53E /* Frameworks */ = {
41 | isa = PBXFrameworksBuildPhase;
42 | buildActionMask = 2147483647;
43 | files = (
44 | 670501EA1DC2CA080057DC00 /* SwipingCarousel.framework in Frameworks */,
45 | );
46 | runOnlyForDeploymentPostprocessing = 0;
47 | };
48 | /* End PBXFrameworksBuildPhase section */
49 |
50 | /* Begin PBXGroup section */
51 | 67B0169A1DC21CEC006EF53E = {
52 | isa = PBXGroup;
53 | children = (
54 | 67B016A51DC21CEC006EF53E /* SwipingCards */,
55 | 67B016A41DC21CEC006EF53E /* Products */,
56 | 67B016C61DC2420D006EF53E /* Frameworks */,
57 | );
58 | sourceTree = "";
59 | };
60 | 67B016A41DC21CEC006EF53E /* Products */ = {
61 | isa = PBXGroup;
62 | children = (
63 | 67B016A31DC21CEC006EF53E /* SwipingCards.app */,
64 | );
65 | name = Products;
66 | sourceTree = "";
67 | };
68 | 67B016A51DC21CEC006EF53E /* SwipingCards */ = {
69 | isa = PBXGroup;
70 | children = (
71 | 67B016CA1DC24315006EF53E /* Model */,
72 | 67B016CB1DC2431E006EF53E /* Views */,
73 | 67B016CC1DC24335006EF53E /* Controllers */,
74 | 67B016CF1DC2435C006EF53E /* Support Files */,
75 | 67B016D01DC24372006EF53E /* Storyboards */,
76 | );
77 | name = SwipingCards;
78 | path = ExampleProject;
79 | sourceTree = "";
80 | };
81 | 67B016C61DC2420D006EF53E /* Frameworks */ = {
82 | isa = PBXGroup;
83 | children = (
84 | 670501E91DC2CA080057DC00 /* SwipingCarousel.framework */,
85 | );
86 | name = Frameworks;
87 | sourceTree = "";
88 | };
89 | 67B016CA1DC24315006EF53E /* Model */ = {
90 | isa = PBXGroup;
91 | children = (
92 | 67B016CD1DC2434C006EF53E /* Card.swift */,
93 | );
94 | name = Model;
95 | sourceTree = "";
96 | };
97 | 67B016CB1DC2431E006EF53E /* Views */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 67B016D11DC243FA006EF53E /* CardCollectionViewCell.swift */,
101 | 67B016D21DC243FA006EF53E /* CardCollectionViewCell.xib */,
102 | );
103 | name = Views;
104 | sourceTree = "";
105 | };
106 | 67B016CC1DC24335006EF53E /* Controllers */ = {
107 | isa = PBXGroup;
108 | children = (
109 | 67B016A81DC21CEC006EF53E /* CardViewController.swift */,
110 | );
111 | name = Controllers;
112 | sourceTree = "";
113 | };
114 | 67B016CF1DC2435C006EF53E /* Support Files */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 67B016A61DC21CEC006EF53E /* AppDelegate.swift */,
118 | 672AF5B723929F540004468D /* ColorExtensions.swift */,
119 | 67B016D71DC24419006EF53E /* Cards.plist */,
120 | 67B016AD1DC21CEC006EF53E /* Assets.xcassets */,
121 | 67B016B21DC21CEC006EF53E /* Info.plist */,
122 | );
123 | name = "Support Files";
124 | sourceTree = "";
125 | };
126 | 67B016D01DC24372006EF53E /* Storyboards */ = {
127 | isa = PBXGroup;
128 | children = (
129 | 67B016AA1DC21CEC006EF53E /* Main.storyboard */,
130 | 67B016AF1DC21CEC006EF53E /* LaunchScreen.storyboard */,
131 | );
132 | name = Storyboards;
133 | sourceTree = "";
134 | };
135 | /* End PBXGroup section */
136 |
137 | /* Begin PBXNativeTarget section */
138 | 67B016A21DC21CEC006EF53E /* SwipingCards */ = {
139 | isa = PBXNativeTarget;
140 | buildConfigurationList = 67B016C01DC21CEC006EF53E /* Build configuration list for PBXNativeTarget "SwipingCards" */;
141 | buildPhases = (
142 | 67B0169F1DC21CEC006EF53E /* Sources */,
143 | 67B016A01DC21CEC006EF53E /* Frameworks */,
144 | 67B016A11DC21CEC006EF53E /* Resources */,
145 | 67B016C91DC2422E006EF53E /* ShellScript */,
146 | );
147 | buildRules = (
148 | );
149 | dependencies = (
150 | );
151 | name = SwipingCards;
152 | productName = ExampleProject;
153 | productReference = 67B016A31DC21CEC006EF53E /* SwipingCards.app */;
154 | productType = "com.apple.product-type.application";
155 | };
156 | /* End PBXNativeTarget section */
157 |
158 | /* Begin PBXProject section */
159 | 67B0169B1DC21CEC006EF53E /* Project object */ = {
160 | isa = PBXProject;
161 | attributes = {
162 | LastSwiftUpdateCheck = 0800;
163 | LastUpgradeCheck = 1120;
164 | ORGANIZATIONNAME = PPacie;
165 | TargetAttributes = {
166 | 67B016A21DC21CEC006EF53E = {
167 | CreatedOnToolsVersion = 8.0;
168 | DevelopmentTeam = 534ZL84PZG;
169 | LastSwiftMigration = 1120;
170 | ProvisioningStyle = Automatic;
171 | };
172 | };
173 | };
174 | buildConfigurationList = 67B0169E1DC21CEC006EF53E /* Build configuration list for PBXProject "SwipingCards" */;
175 | compatibilityVersion = "Xcode 3.2";
176 | developmentRegion = en;
177 | hasScannedForEncodings = 0;
178 | knownRegions = (
179 | en,
180 | Base,
181 | );
182 | mainGroup = 67B0169A1DC21CEC006EF53E;
183 | productRefGroup = 67B016A41DC21CEC006EF53E /* Products */;
184 | projectDirPath = "";
185 | projectRoot = "";
186 | targets = (
187 | 67B016A21DC21CEC006EF53E /* SwipingCards */,
188 | );
189 | };
190 | /* End PBXProject section */
191 |
192 | /* Begin PBXResourcesBuildPhase section */
193 | 67B016A11DC21CEC006EF53E /* Resources */ = {
194 | isa = PBXResourcesBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | 67B016D81DC24419006EF53E /* Cards.plist in Resources */,
198 | 67B016D41DC243FA006EF53E /* CardCollectionViewCell.xib in Resources */,
199 | 67B016B11DC21CEC006EF53E /* LaunchScreen.storyboard in Resources */,
200 | 67B016AE1DC21CEC006EF53E /* Assets.xcassets in Resources */,
201 | 67B016AC1DC21CEC006EF53E /* Main.storyboard in Resources */,
202 | );
203 | runOnlyForDeploymentPostprocessing = 0;
204 | };
205 | /* End PBXResourcesBuildPhase section */
206 |
207 | /* Begin PBXShellScriptBuildPhase section */
208 | 67B016C91DC2422E006EF53E /* ShellScript */ = {
209 | isa = PBXShellScriptBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | );
213 | inputPaths = (
214 | "$(SRCROOT)/Carthage/Build/iOS/SwipingCarousel.framework",
215 | );
216 | outputPaths = (
217 | );
218 | runOnlyForDeploymentPostprocessing = 0;
219 | shellPath = /bin/sh;
220 | shellScript = "/usr/local/bin/carthage copy-frameworks";
221 | };
222 | /* End PBXShellScriptBuildPhase section */
223 |
224 | /* Begin PBXSourcesBuildPhase section */
225 | 67B0169F1DC21CEC006EF53E /* Sources */ = {
226 | isa = PBXSourcesBuildPhase;
227 | buildActionMask = 2147483647;
228 | files = (
229 | 67B016D31DC243FA006EF53E /* CardCollectionViewCell.swift in Sources */,
230 | 672AF5B823929F540004468D /* ColorExtensions.swift in Sources */,
231 | 67B016A91DC21CEC006EF53E /* CardViewController.swift in Sources */,
232 | 67B016CE1DC2434C006EF53E /* Card.swift in Sources */,
233 | 67B016A71DC21CEC006EF53E /* AppDelegate.swift in Sources */,
234 | );
235 | runOnlyForDeploymentPostprocessing = 0;
236 | };
237 | /* End PBXSourcesBuildPhase section */
238 |
239 | /* Begin PBXVariantGroup section */
240 | 67B016AA1DC21CEC006EF53E /* Main.storyboard */ = {
241 | isa = PBXVariantGroup;
242 | children = (
243 | 67B016AB1DC21CEC006EF53E /* Base */,
244 | );
245 | name = Main.storyboard;
246 | sourceTree = "";
247 | };
248 | 67B016AF1DC21CEC006EF53E /* LaunchScreen.storyboard */ = {
249 | isa = PBXVariantGroup;
250 | children = (
251 | 67B016B01DC21CEC006EF53E /* Base */,
252 | );
253 | name = LaunchScreen.storyboard;
254 | sourceTree = "";
255 | };
256 | /* End PBXVariantGroup section */
257 |
258 | /* Begin XCBuildConfiguration section */
259 | 67B016BE1DC21CEC006EF53E /* Debug */ = {
260 | isa = XCBuildConfiguration;
261 | buildSettings = {
262 | ALWAYS_SEARCH_USER_PATHS = NO;
263 | CLANG_ANALYZER_NONNULL = YES;
264 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
265 | CLANG_CXX_LIBRARY = "libc++";
266 | CLANG_ENABLE_MODULES = YES;
267 | CLANG_ENABLE_OBJC_ARC = YES;
268 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
269 | CLANG_WARN_BOOL_CONVERSION = YES;
270 | CLANG_WARN_COMMA = YES;
271 | CLANG_WARN_CONSTANT_CONVERSION = YES;
272 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
273 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
274 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
275 | CLANG_WARN_EMPTY_BODY = YES;
276 | CLANG_WARN_ENUM_CONVERSION = YES;
277 | CLANG_WARN_INFINITE_RECURSION = YES;
278 | CLANG_WARN_INT_CONVERSION = YES;
279 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
280 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
281 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
282 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
283 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
284 | CLANG_WARN_STRICT_PROTOTYPES = YES;
285 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
286 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
287 | CLANG_WARN_UNREACHABLE_CODE = YES;
288 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
289 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
290 | COPY_PHASE_STRIP = NO;
291 | DEBUG_INFORMATION_FORMAT = dwarf;
292 | ENABLE_STRICT_OBJC_MSGSEND = YES;
293 | ENABLE_TESTABILITY = YES;
294 | GCC_C_LANGUAGE_STANDARD = gnu99;
295 | GCC_DYNAMIC_NO_PIC = NO;
296 | GCC_NO_COMMON_BLOCKS = YES;
297 | GCC_OPTIMIZATION_LEVEL = 0;
298 | GCC_PREPROCESSOR_DEFINITIONS = (
299 | "DEBUG=1",
300 | "$(inherited)",
301 | );
302 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
303 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
304 | GCC_WARN_UNDECLARED_SELECTOR = YES;
305 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
306 | GCC_WARN_UNUSED_FUNCTION = YES;
307 | GCC_WARN_UNUSED_VARIABLE = YES;
308 | IPHONEOS_DEPLOYMENT_TARGET = 8.4;
309 | MTL_ENABLE_DEBUG_INFO = YES;
310 | ONLY_ACTIVE_ARCH = YES;
311 | SDKROOT = iphoneos;
312 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
313 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
314 | SWIFT_VERSION = "";
315 | TARGETED_DEVICE_FAMILY = "1,2";
316 | };
317 | name = Debug;
318 | };
319 | 67B016BF1DC21CEC006EF53E /* Release */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ALWAYS_SEARCH_USER_PATHS = NO;
323 | CLANG_ANALYZER_NONNULL = YES;
324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
325 | CLANG_CXX_LIBRARY = "libc++";
326 | CLANG_ENABLE_MODULES = YES;
327 | CLANG_ENABLE_OBJC_ARC = YES;
328 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
329 | CLANG_WARN_BOOL_CONVERSION = YES;
330 | CLANG_WARN_COMMA = YES;
331 | CLANG_WARN_CONSTANT_CONVERSION = YES;
332 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
333 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
334 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
335 | CLANG_WARN_EMPTY_BODY = YES;
336 | CLANG_WARN_ENUM_CONVERSION = YES;
337 | CLANG_WARN_INFINITE_RECURSION = YES;
338 | CLANG_WARN_INT_CONVERSION = YES;
339 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
340 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
344 | CLANG_WARN_STRICT_PROTOTYPES = YES;
345 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
346 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
347 | CLANG_WARN_UNREACHABLE_CODE = YES;
348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
350 | COPY_PHASE_STRIP = NO;
351 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
352 | ENABLE_NS_ASSERTIONS = NO;
353 | ENABLE_STRICT_OBJC_MSGSEND = YES;
354 | GCC_C_LANGUAGE_STANDARD = gnu99;
355 | GCC_NO_COMMON_BLOCKS = YES;
356 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
357 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
358 | GCC_WARN_UNDECLARED_SELECTOR = YES;
359 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
360 | GCC_WARN_UNUSED_FUNCTION = YES;
361 | GCC_WARN_UNUSED_VARIABLE = YES;
362 | IPHONEOS_DEPLOYMENT_TARGET = 8.4;
363 | MTL_ENABLE_DEBUG_INFO = NO;
364 | SDKROOT = iphoneos;
365 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
366 | SWIFT_VERSION = "";
367 | TARGETED_DEVICE_FAMILY = "1,2";
368 | VALIDATE_PRODUCT = YES;
369 | };
370 | name = Release;
371 | };
372 | 67B016C11DC21CEC006EF53E /* Debug */ = {
373 | isa = XCBuildConfiguration;
374 | buildSettings = {
375 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
376 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
377 | DEVELOPMENT_TEAM = 534ZL84PZG;
378 | FRAMEWORK_SEARCH_PATHS = (
379 | "$(inherited)",
380 | "$(PROJECT_DIR)/Carthage/Build/iOS",
381 | );
382 | INFOPLIST_FILE = ExampleProject/Info.plist;
383 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
384 | PRODUCT_BUNDLE_IDENTIFIER = com.ppacie.ExampleProject;
385 | PRODUCT_NAME = "$(TARGET_NAME)";
386 | PROVISIONING_PROFILE = "";
387 | PROVISIONING_PROFILE_SPECIFIER = "";
388 | SWIFT_VERSION = 5.0;
389 | };
390 | name = Debug;
391 | };
392 | 67B016C21DC21CEC006EF53E /* Release */ = {
393 | isa = XCBuildConfiguration;
394 | buildSettings = {
395 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
396 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
397 | DEVELOPMENT_TEAM = 534ZL84PZG;
398 | FRAMEWORK_SEARCH_PATHS = (
399 | "$(inherited)",
400 | "$(PROJECT_DIR)/Carthage/Build/iOS",
401 | );
402 | INFOPLIST_FILE = ExampleProject/Info.plist;
403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
404 | PRODUCT_BUNDLE_IDENTIFIER = com.ppacie.ExampleProject;
405 | PRODUCT_NAME = "$(TARGET_NAME)";
406 | PROVISIONING_PROFILE = "";
407 | PROVISIONING_PROFILE_SPECIFIER = "";
408 | SWIFT_VERSION = 5.0;
409 | };
410 | name = Release;
411 | };
412 | /* End XCBuildConfiguration section */
413 |
414 | /* Begin XCConfigurationList section */
415 | 67B0169E1DC21CEC006EF53E /* Build configuration list for PBXProject "SwipingCards" */ = {
416 | isa = XCConfigurationList;
417 | buildConfigurations = (
418 | 67B016BE1DC21CEC006EF53E /* Debug */,
419 | 67B016BF1DC21CEC006EF53E /* Release */,
420 | );
421 | defaultConfigurationIsVisible = 0;
422 | defaultConfigurationName = Release;
423 | };
424 | 67B016C01DC21CEC006EF53E /* Build configuration list for PBXNativeTarget "SwipingCards" */ = {
425 | isa = XCConfigurationList;
426 | buildConfigurations = (
427 | 67B016C11DC21CEC006EF53E /* Debug */,
428 | 67B016C21DC21CEC006EF53E /* Release */,
429 | );
430 | defaultConfigurationIsVisible = 0;
431 | defaultConfigurationName = Release;
432 | };
433 | /* End XCConfigurationList section */
434 | };
435 | rootObject = 67B0169B1DC21CEC006EF53E /* Project object */;
436 | }
437 |
--------------------------------------------------------------------------------
/ExampleProject/SwipingCards.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Pablo Paciello
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "Swiping Carousel",
6 | platforms: [
7 | .iOS(.v9),
8 | ],
9 | products: [
10 | .library(
11 | name: "Swiping Carousel",
12 | targets: ["SwipingCarousel"]),
13 | ],
14 | dependencies: [
15 | // no dependencies
16 | ],
17 | targets: [
18 | .target(
19 | name: "SwipingCarousel",
20 | dependencies: []),
21 | .testTarget(
22 | name: "SwipingCarouselTests",
23 | dependencies: ["SwipingCarousel"]),
24 | ]
25 | )
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwipingCarousel
2 | 
3 | [](https://swift.org/package-manager)
4 | [](https://github.com/Carthage/Carthage)
5 | 
6 | 
7 | [](https://twitter.com/ppacie)
8 |
9 | 
10 |
11 | ## What does it do?
12 | * When scrolling, the cards magnify when they get to the center.
13 | * You can tap and hold on a card, swipe up to **'Like'** it. Right after, it will scroll to next one.
14 | * You can tap and hold on a card, swipe down to **'Dismiss'** it. After, it will scroll to next card.
15 | * When tapping on the centered card, it will be opened a chat room with the user the card represents.
16 | * When tapping on the side cards, it will scroll to them.
17 | * When swiping up or down on the side cards, they won't be liked or dismissed. Just moved.
18 |
19 | ## Installation
20 | #### Carthage
21 | ~~~
22 | github "ppacie/SwipingCarousel"
23 | ~~~
24 |
25 | ## How to set it up
26 |
27 | 1. Import `SwipingCarousel` module to your `ViewController` and `CollectionViewCell` classes.
28 |
29 | ```swift
30 | import SwipingCarousel
31 | ```
32 | 2. Make your `CollectionViewCell` subclass of `SwipingCarouselCollectionViewCell`.
33 |
34 | ```swift
35 | class MyCollectionViewCell: SwipingCarouselCollectionViewCell {
36 | }
37 | ```
38 | 3. Conform to `SwipingCarouselDelegate` protocol methods `func cellSwipedDown()` and `func cellSwipedUp()`.
39 | e.g.
40 | ```swift
41 | extension MyCollectionViewController: SwipingCarouselDelegate {
42 |
43 | func cellSwipedUp(_ cell: UICollectionViewCell) {
44 | ...
45 | }
46 |
47 | func cellSwipedDown(_ cell: UICollectionViewCell) {
48 | ...
49 | }
50 | }
51 | ```
52 | 4. Finally, you will need to set it as your CollectionView's custom layout: You can do it either in the Interface Builder **OR** programmatically.
53 |
54 | * Interface Builder: Go to your Storyboard file and select the Controller where you have the CollectionView. Later select the CollectionView in the Document Outline and set the `SwipingCarouselFlowLayout` as the Custom Layout in the Attributes Inspector and set the Module to `SwipingCarousel`.
55 |
56 | 
57 |
58 | * Programmaticaly:
59 | Add the following line in the `viewDidLoad()` of your `CollectionViewController` (the ViewController that contains your CollectionView):
60 |
61 | ```swift
62 | collectionView.setCollectionViewLayout(SwipingCarouselFlowLayout(), animated: false)
63 | ```
64 | ## SwipingCarouselCollectionViewCell Properties
65 |
66 | ```swift
67 | weak public var delegate: SwipingCarouselDelegate?
68 | ```
69 | An object that supports the SwipingCarouselDelegate protocol and can respond to swiping events.
70 | ```swift
71 | public var deleteOnSwipeDown = false
72 | ```
73 | Indicates weather to remove the SwipingCarouselCell cell from view or to get it back to the original position when swiping down. Default behavior is to get back to original position.
74 | ```swift
75 | public var deleteOnSwipeUp = false
76 | ```
77 | Indicates weather to remove the SwipingCarouselCell cell from view or to get it back to the original position when swiping up. Default behavior is to get back to original position.
78 |
79 | ## Example
80 | Check the *ExampleProject* folder to see how it works.
81 |
82 | ## Can I customize the Layout?
83 | Sure, you are able to customize the layout by overriding the `UICollectionViewDelegateFlowLayout` methods you desire.
84 | e.g.
85 | ```swift
86 | extension MyCollectionViewController: UICollectionViewDelegateFlowLayout {
87 |
88 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
89 | return UIEdgeInsets(top: 200, left: 120, bottom: 200, right: 120)
90 | }
91 |
92 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
93 | return CGSize(width: 150.0, height: 230.0)
94 | }
95 |
96 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
97 | return 50.0
98 | }
99 | }
100 | ```
101 | Also if you set the layout programmatically you will be allowed to change the ```activeDistance``` value. This property will get you access to modify the layoutAttributes of the collectionView. It represents the distance from the center where the cell/item will start zooming in and out. Default value is 200.0
102 |
103 | ```swift
104 | let layout = SwipingCarouselFlowLayout()
105 | layout.activeDistance = 50
106 | collectionView.setCollectionViewLayout(layout, animated: false)
107 | ```
108 |
--------------------------------------------------------------------------------
/Sources/SwipingCarousel/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.5
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Sources/SwipingCarousel/Swiping Carousel.h:
--------------------------------------------------------------------------------
1 | //
2 | // Swiping Carousel.h
3 | // Swiping Carousel
4 | //
5 | // Created by Pablo Paciello on 10/27/16.
6 | // Copyright © 2016 PPacie. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for Swiping Carousel.
12 | FOUNDATION_EXPORT double Swiping_CarouselVersionNumber;
13 |
14 | //! Project version string for Swiping Carousel.
15 | FOUNDATION_EXPORT const unsigned char Swiping_CarouselVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Sources/SwipingCarousel/SwipingCarouselCellManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwipingCarouselCellManager.swift
3 | // SwipingCarousel
4 | //
5 | // Created by Pablo Paciello on 8/1/17.
6 | // Copyright © 2017 PPacie. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class SwpingCarouselCellManager {
12 | private var cell: SwipingCarouselCollectionViewCell!
13 | lazy var swipeDistanceOnY = CGFloat() //Distance of the swipe over "y" axis.
14 | lazy var originalPoint = CGPoint()
15 |
16 | init(withCell cell: SwipingCarouselCollectionViewCell) {
17 | self.cell = cell
18 | }
19 |
20 | //MARK: - Gestures Handling
21 | private enum Constants {
22 | static let SwipeDistanceToTakeAction: CGFloat = UIScreen.main.bounds.size.height / 5 //Distance required for the cell to go off the screen.
23 | static let SwipeImageAnimationDuration: TimeInterval = 0.30 //Duration of the Animation when Swiping Up/Down.
24 | static let CenterImageAnimationDuration: TimeInterval = 0.20 //Duration of the Animation when image gets back to original postion.
25 | }
26 |
27 | func handlePanGesture(_ sender: UIPanGestureRecognizer) {
28 | //Get the distance of the Swipe on "y" axis.
29 | swipeDistanceOnY = sender.translation(in: self.cell).y
30 |
31 | switch sender.state {
32 | case .began:
33 | originalPoint = cell.center //Get the center of the Cell.
34 | case .changed:
35 | //Move the cell to the Y point while gesturing.
36 | cell.center = CGPoint(x: originalPoint.x, y: originalPoint.y + swipeDistanceOnY)
37 | case .ended:
38 | //Take action after the Swipe gesture ends.
39 | afterSwipeAction()
40 | default:
41 | break
42 | }
43 | }
44 |
45 | func afterSwipeAction() {
46 | //First, we check if the swiped cell is the one in the middle of screen by cheking its size. If the cell is one of the sides, we send it back to its original position.
47 | if (cell.frame.size.height > cell.bounds.size.height) {
48 | //If the cell is the one at the center (biggest one), we proceed to check wheather or not the distance of the gesture is enough to move the cell off the screen (up or down).
49 | if swipeDistanceOnY > Constants.SwipeDistanceToTakeAction {
50 | downAction()
51 | } else if swipeDistanceOnY < -Constants.SwipeDistanceToTakeAction {
52 | upAction()
53 | } else {
54 | UIView.animate(withDuration: Constants.CenterImageAnimationDuration, animations: {
55 | self.cell?.center = self.originalPoint
56 | })
57 | }
58 | } else {
59 | UIView.animate(withDuration: Constants.CenterImageAnimationDuration, animations: {
60 | self.cell?.center = self.originalPoint
61 | })
62 | }
63 | }
64 |
65 | func upAction() {
66 | /* The maxUpperPoint will depend on deleteOnSwipeUp variable.
67 | Under default behavior, 'false', the cell will go back to the original position.
68 | If it's set to 'true' the cell will go down off the screen to be able to delete it throught its delegate. */
69 | let maxUpperPoint: CGPoint = cell.deleteOnSwipeUp ? CGPoint(x: originalPoint.x, y: 2 * cell.frame.minY) : originalPoint
70 | UIView.animate(withDuration: Constants.SwipeImageAnimationDuration, animations: { () -> Void in
71 | self.cell?.center = maxUpperPoint //Move the cell to the maxUpperPoint.
72 | self.cell?.superview?.isUserInteractionEnabled = false //Deactivate the user interaction in the Superview (In this case will be in the collection view). To avoid scrolling during the animation.
73 | }, completion: { (completion) -> Void in
74 | self.cell?.superview?.isUserInteractionEnabled = true // Re-activate the user interaction.
75 | self.cell?.delegate?.cellSwipedUp(self.cell!) //Delegate the SwipeUp action and send the view with it.
76 | })
77 | }
78 |
79 | func downAction() {
80 | /* The maxDownPoint will depend on deleteOnSwipeDown variable.
81 | Under default behavior, 'false', the cell will go back to the original position.
82 | If it's set to 'true' the cell will go down off the screen to be able to delete it throught its delegate. */
83 | let maxDownPoint: CGPoint = cell.deleteOnSwipeDown ? CGPoint(x: originalPoint.x, y: 2 * cell.frame.maxY) : originalPoint
84 | UIView.animate(withDuration: Constants.SwipeImageAnimationDuration, animations: { () -> Void in
85 | self.cell?.center = maxDownPoint //Move the cell to the maxDownPoint.
86 | self.cell?.superview?.isUserInteractionEnabled = false //Deactivate the user interaction in the Superview (In this case will be in the collection view). To avoid scrolling during the animation.
87 | }, completion: { (completion) -> Void in
88 | self.cell?.superview?.isUserInteractionEnabled = true // Re-activate the user interaction.
89 | self.cell?.delegate?.cellSwipedDown(self.cell!) //Delegate the SwipeDown action and send the view with it.
90 | })
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Sources/SwipingCarousel/SwipingCarouselCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwipingCarouselCollectionViewCell.swift
3 | // Swiping Cards
4 | //
5 | // Created by Pablo Paciello on 10/26/16.
6 | // Copyright © 2016 Pablo Paciello. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | //Protocol to inform that cell is being swiped up or down.
12 | public protocol SwipingCarouselDelegate : class {
13 | func cellSwipedUp(_ cell: UICollectionViewCell)
14 | func cellSwipedDown(_ cell: UICollectionViewCell)
15 | }
16 |
17 | open class SwipingCarouselCollectionViewCell: UICollectionViewCell {
18 | public weak var delegate: SwipingCarouselDelegate?
19 | public var deleteOnSwipeUp = false
20 | public var deleteOnSwipeDown = false
21 | private var cellManager: SwpingCarouselCellManager!
22 |
23 | open override func awakeFromNib() {
24 | super.awakeFromNib()
25 | //Init the Cell Manager
26 | cellManager = SwpingCarouselCellManager(withCell: self)
27 | // Add Gesture to Cell
28 | addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))))
29 | }
30 |
31 | @objc private func handlePanGesture(_ sender: UIPanGestureRecognizer) {
32 | cellManager.handlePanGesture(sender)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/SwipingCarousel/SwipingCarouselFlowLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwipingCarouselFlowLayout.swift
3 | // Swiping Cards
4 | //
5 | // Created by Pablo Paciello on 8/20/15.
6 | // Copyright (c) 2015 Pablo Paciello. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class SwipingCarouselFlowLayout: UICollectionViewFlowLayout {
12 |
13 | // MARK: - Constants
14 | private enum Constants {
15 | static let zoomFactor: CGFloat = 0.3
16 | static let itemWidth: CGFloat = 230 //Width of the Cell.
17 | static let itemHeight: CGFloat = 300 //Height of the Cell.
18 | static let minLineSpacing: CGFloat = 50.0
19 | }
20 |
21 | public var activeDistance: CGFloat = 200
22 |
23 | override public func prepare() {
24 | super.prepare()
25 |
26 | itemSize = CGSize(width: Constants.itemWidth, height: Constants.itemHeight)
27 | scrollDirection = .horizontal
28 | minimumLineSpacing = Constants.minLineSpacing
29 | //These numbers will depend on the size of your cards you have set in the CardsViewFlowConstants.
30 | //60 - will let the first and last card of the CollectionView to be centered.
31 | //100 - will avoid the double rows in the CollectionView
32 | sectionInset = UIEdgeInsets.init(top: 100.0, left: 60.0, bottom: 100, right: 60.0)
33 | }
34 |
35 | // Here is where the magic happens
36 | // Add zooming to the Layout Attributes.
37 | override public func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
38 |
39 | let array = super.layoutAttributesForElements(in: rect)
40 | var attributesCopy = [UICollectionViewLayoutAttributes]()
41 |
42 | var visibleRect = CGRect()
43 | visibleRect.origin = collectionView!.contentOffset
44 | visibleRect.size = collectionView!.bounds.size
45 |
46 | for itemAttributes in array! {
47 | //let newAttributes: UICollectionViewLayoutAttributes = itemAttributes
48 | let itemAttributesCopy = itemAttributes.copy() as! UICollectionViewLayoutAttributes
49 | if itemAttributesCopy.frame.intersects(rect) {
50 | let distance = visibleRect.midX - itemAttributes.center.x
51 | let normalizedDistance = distance / activeDistance
52 | if (abs(distance)) < activeDistance {
53 | let zoom = 1 + Constants.zoomFactor*(1 - abs(normalizedDistance))
54 | itemAttributesCopy.transform3D = CATransform3DMakeScale(zoom, zoom, 1.0)
55 | itemAttributesCopy.zIndex = 1
56 | }
57 | }
58 | attributesCopy.append(itemAttributesCopy)
59 | }
60 | return attributesCopy
61 | }
62 |
63 | //Focus the zoom in the middle Card.
64 | override public func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
65 |
66 | var offsetAdjustment:CGFloat = CGFloat(MAXFLOAT)
67 | let horizontalCenter = proposedContentOffset.x + (collectionView!.bounds.width / 2.0)
68 |
69 | let targetRect = CGRect(x: proposedContentOffset.x, y: 0.0, width: collectionView!.bounds.size.width, height: collectionView!.bounds.size.height)
70 |
71 | if let array = super.layoutAttributesForElements(in: targetRect) {
72 | for layoutAttributes in array {
73 | let itemHorizontalCenter: CGFloat = layoutAttributes.center.x
74 | if (abs(itemHorizontalCenter - horizontalCenter) < abs(offsetAdjustment)) {
75 | offsetAdjustment = itemHorizontalCenter - horizontalCenter
76 | }
77 | }
78 | }
79 | return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)
80 | }
81 |
82 | // Invalidate the Layout when the user is scrolling
83 | override public func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
84 | return true
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Swiping-Carousel-Demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PPacie/SwipingCarousel/4247840a2ae7a799d0710495ae3d3ff49590036b/Swiping-Carousel-Demo.gif
--------------------------------------------------------------------------------
/SwipingCarousel.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 67895D8A1F3095FD0004DB9E /* SwipingCarouselTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67895D891F3095FD0004DB9E /* SwipingCarouselTests.swift */; };
11 | 67895D8C1F3095FD0004DB9E /* SwipingCarousel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 67B0166E1DC2041F006EF53E /* SwipingCarousel.framework */; };
12 | 67B0167F1DC2041F006EF53E /* Swiping Carousel.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B016711DC2041F006EF53E /* Swiping Carousel.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | 67B0168A1DC20B1D006EF53E /* SwipingCarouselFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B016881DC20B1D006EF53E /* SwipingCarouselFlowLayout.swift */; };
14 | 67B0168B1DC20B1D006EF53E /* SwipingCarouselCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B016891DC20B1D006EF53E /* SwipingCarouselCollectionViewCell.swift */; };
15 | 67CBE1721F3089FC00F35988 /* SwipingCarouselCellManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67CBE1711F3089FC00F35988 /* SwipingCarouselCellManager.swift */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXContainerItemProxy section */
19 | 67895D8D1F3095FD0004DB9E /* PBXContainerItemProxy */ = {
20 | isa = PBXContainerItemProxy;
21 | containerPortal = 67B016651DC2041F006EF53E /* Project object */;
22 | proxyType = 1;
23 | remoteGlobalIDString = 67B0166D1DC2041F006EF53E;
24 | remoteInfo = SwipingCarousel;
25 | };
26 | /* End PBXContainerItemProxy section */
27 |
28 | /* Begin PBXFileReference section */
29 | 6759C10E23A24C2600B7F506 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; };
30 | 67895D871F3095FD0004DB9E /* SwipingCarouselTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwipingCarouselTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
31 | 67895D891F3095FD0004DB9E /* SwipingCarouselTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipingCarouselTests.swift; sourceTree = ""; };
32 | 67895D8B1F3095FD0004DB9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
33 | 67B0166E1DC2041F006EF53E /* SwipingCarousel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwipingCarousel.framework; sourceTree = BUILT_PRODUCTS_DIR; };
34 | 67B016711DC2041F006EF53E /* Swiping Carousel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Swiping Carousel.h"; sourceTree = ""; };
35 | 67B016721DC2041F006EF53E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
36 | 67B016881DC20B1D006EF53E /* SwipingCarouselFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwipingCarouselFlowLayout.swift; sourceTree = ""; };
37 | 67B016891DC20B1D006EF53E /* SwipingCarouselCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwipingCarouselCollectionViewCell.swift; sourceTree = ""; };
38 | 67CBE1711F3089FC00F35988 /* SwipingCarouselCellManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwipingCarouselCellManager.swift; sourceTree = ""; };
39 | /* End PBXFileReference section */
40 |
41 | /* Begin PBXFrameworksBuildPhase section */
42 | 67895D841F3095FD0004DB9E /* Frameworks */ = {
43 | isa = PBXFrameworksBuildPhase;
44 | buildActionMask = 2147483647;
45 | files = (
46 | 67895D8C1F3095FD0004DB9E /* SwipingCarousel.framework in Frameworks */,
47 | );
48 | runOnlyForDeploymentPostprocessing = 0;
49 | };
50 | 67B0166A1DC2041F006EF53E /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | );
55 | runOnlyForDeploymentPostprocessing = 0;
56 | };
57 | /* End PBXFrameworksBuildPhase section */
58 |
59 | /* Begin PBXGroup section */
60 | 6759C10C23A24ADF00B7F506 /* Sources */ = {
61 | isa = PBXGroup;
62 | children = (
63 | 67B016701DC2041F006EF53E /* SwipingCarousel */,
64 | );
65 | path = Sources;
66 | sourceTree = "";
67 | };
68 | 6759C10D23A24B4700B7F506 /* Tests */ = {
69 | isa = PBXGroup;
70 | children = (
71 | 67895D881F3095FD0004DB9E /* SwipingCarouselTests */,
72 | );
73 | path = Tests;
74 | sourceTree = "";
75 | };
76 | 67895D881F3095FD0004DB9E /* SwipingCarouselTests */ = {
77 | isa = PBXGroup;
78 | children = (
79 | 67895D891F3095FD0004DB9E /* SwipingCarouselTests.swift */,
80 | 67895D8B1F3095FD0004DB9E /* Info.plist */,
81 | );
82 | path = SwipingCarouselTests;
83 | sourceTree = "";
84 | };
85 | 67B016641DC2041F006EF53E = {
86 | isa = PBXGroup;
87 | children = (
88 | 6759C10E23A24C2600B7F506 /* Package.swift */,
89 | 6759C10C23A24ADF00B7F506 /* Sources */,
90 | 6759C10D23A24B4700B7F506 /* Tests */,
91 | 67B0166F1DC2041F006EF53E /* Products */,
92 | );
93 | sourceTree = "";
94 | };
95 | 67B0166F1DC2041F006EF53E /* Products */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 67B0166E1DC2041F006EF53E /* SwipingCarousel.framework */,
99 | 67895D871F3095FD0004DB9E /* SwipingCarouselTests.xctest */,
100 | );
101 | name = Products;
102 | sourceTree = "";
103 | };
104 | 67B016701DC2041F006EF53E /* SwipingCarousel */ = {
105 | isa = PBXGroup;
106 | children = (
107 | 67B016881DC20B1D006EF53E /* SwipingCarouselFlowLayout.swift */,
108 | 67B016891DC20B1D006EF53E /* SwipingCarouselCollectionViewCell.swift */,
109 | 67CBE1711F3089FC00F35988 /* SwipingCarouselCellManager.swift */,
110 | 67B016711DC2041F006EF53E /* Swiping Carousel.h */,
111 | 67B016721DC2041F006EF53E /* Info.plist */,
112 | );
113 | path = SwipingCarousel;
114 | sourceTree = "";
115 | };
116 | /* End PBXGroup section */
117 |
118 | /* Begin PBXHeadersBuildPhase section */
119 | 67B0166B1DC2041F006EF53E /* Headers */ = {
120 | isa = PBXHeadersBuildPhase;
121 | buildActionMask = 2147483647;
122 | files = (
123 | 67B0167F1DC2041F006EF53E /* Swiping Carousel.h in Headers */,
124 | );
125 | runOnlyForDeploymentPostprocessing = 0;
126 | };
127 | /* End PBXHeadersBuildPhase section */
128 |
129 | /* Begin PBXNativeTarget section */
130 | 67895D861F3095FD0004DB9E /* SwipingCarouselTests */ = {
131 | isa = PBXNativeTarget;
132 | buildConfigurationList = 67895D8F1F3095FD0004DB9E /* Build configuration list for PBXNativeTarget "SwipingCarouselTests" */;
133 | buildPhases = (
134 | 67895D831F3095FD0004DB9E /* Sources */,
135 | 67895D841F3095FD0004DB9E /* Frameworks */,
136 | 67895D851F3095FD0004DB9E /* Resources */,
137 | );
138 | buildRules = (
139 | );
140 | dependencies = (
141 | 67895D8E1F3095FD0004DB9E /* PBXTargetDependency */,
142 | );
143 | name = SwipingCarouselTests;
144 | productName = SwipingCarouselTests;
145 | productReference = 67895D871F3095FD0004DB9E /* SwipingCarouselTests.xctest */;
146 | productType = "com.apple.product-type.bundle.unit-test";
147 | };
148 | 67B0166D1DC2041F006EF53E /* SwipingCarousel */ = {
149 | isa = PBXNativeTarget;
150 | buildConfigurationList = 67B016821DC2041F006EF53E /* Build configuration list for PBXNativeTarget "SwipingCarousel" */;
151 | buildPhases = (
152 | 67B016691DC2041F006EF53E /* Sources */,
153 | 67B0166A1DC2041F006EF53E /* Frameworks */,
154 | 67B0166B1DC2041F006EF53E /* Headers */,
155 | 67B0166C1DC2041F006EF53E /* Resources */,
156 | );
157 | buildRules = (
158 | );
159 | dependencies = (
160 | );
161 | name = SwipingCarousel;
162 | productName = "Swiping Carousel";
163 | productReference = 67B0166E1DC2041F006EF53E /* SwipingCarousel.framework */;
164 | productType = "com.apple.product-type.framework";
165 | };
166 | /* End PBXNativeTarget section */
167 |
168 | /* Begin PBXProject section */
169 | 67B016651DC2041F006EF53E /* Project object */ = {
170 | isa = PBXProject;
171 | attributes = {
172 | LastSwiftUpdateCheck = 0830;
173 | LastUpgradeCheck = 1120;
174 | ORGANIZATIONNAME = PPacie;
175 | TargetAttributes = {
176 | 67895D861F3095FD0004DB9E = {
177 | CreatedOnToolsVersion = 8.3.3;
178 | DevelopmentTeam = 534ZL84PZG;
179 | LastSwiftMigration = 1120;
180 | ProvisioningStyle = Automatic;
181 | };
182 | 67B0166D1DC2041F006EF53E = {
183 | CreatedOnToolsVersion = 8.0;
184 | DevelopmentTeam = 534ZL84PZG;
185 | LastSwiftMigration = 1120;
186 | ProvisioningStyle = Automatic;
187 | };
188 | };
189 | };
190 | buildConfigurationList = 67B016681DC2041F006EF53E /* Build configuration list for PBXProject "SwipingCarousel" */;
191 | compatibilityVersion = "Xcode 3.2";
192 | developmentRegion = en;
193 | hasScannedForEncodings = 0;
194 | knownRegions = (
195 | en,
196 | Base,
197 | );
198 | mainGroup = 67B016641DC2041F006EF53E;
199 | productRefGroup = 67B0166F1DC2041F006EF53E /* Products */;
200 | projectDirPath = "";
201 | projectRoot = "";
202 | targets = (
203 | 67B0166D1DC2041F006EF53E /* SwipingCarousel */,
204 | 67895D861F3095FD0004DB9E /* SwipingCarouselTests */,
205 | );
206 | };
207 | /* End PBXProject section */
208 |
209 | /* Begin PBXResourcesBuildPhase section */
210 | 67895D851F3095FD0004DB9E /* Resources */ = {
211 | isa = PBXResourcesBuildPhase;
212 | buildActionMask = 2147483647;
213 | files = (
214 | );
215 | runOnlyForDeploymentPostprocessing = 0;
216 | };
217 | 67B0166C1DC2041F006EF53E /* Resources */ = {
218 | isa = PBXResourcesBuildPhase;
219 | buildActionMask = 2147483647;
220 | files = (
221 | );
222 | runOnlyForDeploymentPostprocessing = 0;
223 | };
224 | /* End PBXResourcesBuildPhase section */
225 |
226 | /* Begin PBXSourcesBuildPhase section */
227 | 67895D831F3095FD0004DB9E /* Sources */ = {
228 | isa = PBXSourcesBuildPhase;
229 | buildActionMask = 2147483647;
230 | files = (
231 | 67895D8A1F3095FD0004DB9E /* SwipingCarouselTests.swift in Sources */,
232 | );
233 | runOnlyForDeploymentPostprocessing = 0;
234 | };
235 | 67B016691DC2041F006EF53E /* Sources */ = {
236 | isa = PBXSourcesBuildPhase;
237 | buildActionMask = 2147483647;
238 | files = (
239 | 67CBE1721F3089FC00F35988 /* SwipingCarouselCellManager.swift in Sources */,
240 | 67B0168B1DC20B1D006EF53E /* SwipingCarouselCollectionViewCell.swift in Sources */,
241 | 67B0168A1DC20B1D006EF53E /* SwipingCarouselFlowLayout.swift in Sources */,
242 | );
243 | runOnlyForDeploymentPostprocessing = 0;
244 | };
245 | /* End PBXSourcesBuildPhase section */
246 |
247 | /* Begin PBXTargetDependency section */
248 | 67895D8E1F3095FD0004DB9E /* PBXTargetDependency */ = {
249 | isa = PBXTargetDependency;
250 | target = 67B0166D1DC2041F006EF53E /* SwipingCarousel */;
251 | targetProxy = 67895D8D1F3095FD0004DB9E /* PBXContainerItemProxy */;
252 | };
253 | /* End PBXTargetDependency section */
254 |
255 | /* Begin XCBuildConfiguration section */
256 | 67895D901F3095FD0004DB9E /* Debug */ = {
257 | isa = XCBuildConfiguration;
258 | buildSettings = {
259 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
260 | CODE_SIGN_IDENTITY = "iPhone Developer";
261 | CODE_SIGN_STYLE = Automatic;
262 | DEVELOPMENT_TEAM = 534ZL84PZG;
263 | INFOPLIST_FILE = Tests/SwipingCarouselTests/Info.plist;
264 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
265 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
266 | PRODUCT_BUNDLE_IDENTIFIER = com.ppacie.SwipingCarouselTests;
267 | PRODUCT_NAME = "$(TARGET_NAME)";
268 | PROVISIONING_PROFILE_SPECIFIER = "";
269 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
270 | SWIFT_VERSION = 5.0;
271 | };
272 | name = Debug;
273 | };
274 | 67895D911F3095FD0004DB9E /* Release */ = {
275 | isa = XCBuildConfiguration;
276 | buildSettings = {
277 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
278 | CODE_SIGN_IDENTITY = "iPhone Developer";
279 | CODE_SIGN_STYLE = Automatic;
280 | DEVELOPMENT_TEAM = 534ZL84PZG;
281 | INFOPLIST_FILE = Tests/SwipingCarouselTests/Info.plist;
282 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
283 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
284 | PRODUCT_BUNDLE_IDENTIFIER = com.ppacie.SwipingCarouselTests;
285 | PRODUCT_NAME = "$(TARGET_NAME)";
286 | PROVISIONING_PROFILE_SPECIFIER = "";
287 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
288 | SWIFT_VERSION = 5.0;
289 | };
290 | name = Release;
291 | };
292 | 67B016801DC2041F006EF53E /* Debug */ = {
293 | isa = XCBuildConfiguration;
294 | buildSettings = {
295 | ALWAYS_SEARCH_USER_PATHS = NO;
296 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
297 | CLANG_ANALYZER_NONNULL = YES;
298 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
299 | CLANG_CXX_LIBRARY = "libc++";
300 | CLANG_ENABLE_MODULES = YES;
301 | CLANG_ENABLE_OBJC_ARC = YES;
302 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
303 | CLANG_WARN_BOOL_CONVERSION = YES;
304 | CLANG_WARN_COMMA = YES;
305 | CLANG_WARN_CONSTANT_CONVERSION = YES;
306 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
307 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
308 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
309 | CLANG_WARN_EMPTY_BODY = YES;
310 | CLANG_WARN_ENUM_CONVERSION = YES;
311 | CLANG_WARN_INFINITE_RECURSION = YES;
312 | CLANG_WARN_INT_CONVERSION = YES;
313 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
314 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
315 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
316 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
317 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
318 | CLANG_WARN_STRICT_PROTOTYPES = YES;
319 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
320 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
321 | CLANG_WARN_UNREACHABLE_CODE = YES;
322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
324 | COPY_PHASE_STRIP = NO;
325 | CURRENT_PROJECT_VERSION = 1;
326 | DEBUG_INFORMATION_FORMAT = dwarf;
327 | ENABLE_STRICT_OBJC_MSGSEND = YES;
328 | ENABLE_TESTABILITY = YES;
329 | GCC_C_LANGUAGE_STANDARD = gnu99;
330 | GCC_DYNAMIC_NO_PIC = NO;
331 | GCC_NO_COMMON_BLOCKS = YES;
332 | GCC_OPTIMIZATION_LEVEL = 0;
333 | GCC_PREPROCESSOR_DEFINITIONS = (
334 | "DEBUG=1",
335 | "$(inherited)",
336 | );
337 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
338 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
339 | GCC_WARN_UNDECLARED_SELECTOR = YES;
340 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
341 | GCC_WARN_UNUSED_FUNCTION = YES;
342 | GCC_WARN_UNUSED_VARIABLE = YES;
343 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
344 | MTL_ENABLE_DEBUG_INFO = YES;
345 | ONLY_ACTIVE_ARCH = YES;
346 | SDKROOT = iphoneos;
347 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
348 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
349 | TARGETED_DEVICE_FAMILY = "1,2";
350 | VERSIONING_SYSTEM = "apple-generic";
351 | VERSION_INFO_PREFIX = "";
352 | };
353 | name = Debug;
354 | };
355 | 67B016811DC2041F006EF53E /* Release */ = {
356 | isa = XCBuildConfiguration;
357 | buildSettings = {
358 | ALWAYS_SEARCH_USER_PATHS = NO;
359 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
360 | CLANG_ANALYZER_NONNULL = YES;
361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
362 | CLANG_CXX_LIBRARY = "libc++";
363 | CLANG_ENABLE_MODULES = YES;
364 | CLANG_ENABLE_OBJC_ARC = YES;
365 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
366 | CLANG_WARN_BOOL_CONVERSION = YES;
367 | CLANG_WARN_COMMA = YES;
368 | CLANG_WARN_CONSTANT_CONVERSION = YES;
369 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
370 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
371 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
372 | CLANG_WARN_EMPTY_BODY = YES;
373 | CLANG_WARN_ENUM_CONVERSION = YES;
374 | CLANG_WARN_INFINITE_RECURSION = YES;
375 | CLANG_WARN_INT_CONVERSION = YES;
376 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
377 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
378 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
380 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
381 | CLANG_WARN_STRICT_PROTOTYPES = YES;
382 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
383 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
384 | CLANG_WARN_UNREACHABLE_CODE = YES;
385 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
387 | COPY_PHASE_STRIP = NO;
388 | CURRENT_PROJECT_VERSION = 1;
389 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
390 | ENABLE_NS_ASSERTIONS = NO;
391 | ENABLE_STRICT_OBJC_MSGSEND = YES;
392 | GCC_C_LANGUAGE_STANDARD = gnu99;
393 | GCC_NO_COMMON_BLOCKS = YES;
394 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
395 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
396 | GCC_WARN_UNDECLARED_SELECTOR = YES;
397 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
398 | GCC_WARN_UNUSED_FUNCTION = YES;
399 | GCC_WARN_UNUSED_VARIABLE = YES;
400 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
401 | MTL_ENABLE_DEBUG_INFO = NO;
402 | SDKROOT = iphoneos;
403 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
404 | TARGETED_DEVICE_FAMILY = "1,2";
405 | VALIDATE_PRODUCT = YES;
406 | VERSIONING_SYSTEM = "apple-generic";
407 | VERSION_INFO_PREFIX = "";
408 | };
409 | name = Release;
410 | };
411 | 67B016831DC2041F006EF53E /* Debug */ = {
412 | isa = XCBuildConfiguration;
413 | buildSettings = {
414 | CLANG_ENABLE_MODULES = YES;
415 | CODE_SIGN_IDENTITY = "";
416 | CODE_SIGN_STYLE = Automatic;
417 | DEFINES_MODULE = YES;
418 | DEVELOPMENT_TEAM = 534ZL84PZG;
419 | DYLIB_COMPATIBILITY_VERSION = 1;
420 | DYLIB_CURRENT_VERSION = 1;
421 | DYLIB_INSTALL_NAME_BASE = "@rpath";
422 | INFOPLIST_FILE = Sources/SwipingCarousel/Info.plist;
423 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
424 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
425 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
426 | PRODUCT_BUNDLE_IDENTIFIER = com.ppacie.SwipingCarousel;
427 | PRODUCT_NAME = "$(TARGET_NAME)";
428 | PROVISIONING_PROFILE_SPECIFIER = "";
429 | SKIP_INSTALL = YES;
430 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
431 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
432 | SWIFT_VERSION = 5.0;
433 | };
434 | name = Debug;
435 | };
436 | 67B016841DC2041F006EF53E /* Release */ = {
437 | isa = XCBuildConfiguration;
438 | buildSettings = {
439 | CLANG_ENABLE_MODULES = YES;
440 | CODE_SIGN_IDENTITY = "";
441 | CODE_SIGN_STYLE = Automatic;
442 | DEFINES_MODULE = YES;
443 | DEVELOPMENT_TEAM = 534ZL84PZG;
444 | DYLIB_COMPATIBILITY_VERSION = 1;
445 | DYLIB_CURRENT_VERSION = 1;
446 | DYLIB_INSTALL_NAME_BASE = "@rpath";
447 | INFOPLIST_FILE = Sources/SwipingCarousel/Info.plist;
448 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
449 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
451 | PRODUCT_BUNDLE_IDENTIFIER = com.ppacie.SwipingCarousel;
452 | PRODUCT_NAME = "$(TARGET_NAME)";
453 | PROVISIONING_PROFILE_SPECIFIER = "";
454 | SKIP_INSTALL = YES;
455 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
456 | SWIFT_VERSION = 5.0;
457 | };
458 | name = Release;
459 | };
460 | /* End XCBuildConfiguration section */
461 |
462 | /* Begin XCConfigurationList section */
463 | 67895D8F1F3095FD0004DB9E /* Build configuration list for PBXNativeTarget "SwipingCarouselTests" */ = {
464 | isa = XCConfigurationList;
465 | buildConfigurations = (
466 | 67895D901F3095FD0004DB9E /* Debug */,
467 | 67895D911F3095FD0004DB9E /* Release */,
468 | );
469 | defaultConfigurationIsVisible = 0;
470 | defaultConfigurationName = Release;
471 | };
472 | 67B016681DC2041F006EF53E /* Build configuration list for PBXProject "SwipingCarousel" */ = {
473 | isa = XCConfigurationList;
474 | buildConfigurations = (
475 | 67B016801DC2041F006EF53E /* Debug */,
476 | 67B016811DC2041F006EF53E /* Release */,
477 | );
478 | defaultConfigurationIsVisible = 0;
479 | defaultConfigurationName = Release;
480 | };
481 | 67B016821DC2041F006EF53E /* Build configuration list for PBXNativeTarget "SwipingCarousel" */ = {
482 | isa = XCConfigurationList;
483 | buildConfigurations = (
484 | 67B016831DC2041F006EF53E /* Debug */,
485 | 67B016841DC2041F006EF53E /* Release */,
486 | );
487 | defaultConfigurationIsVisible = 0;
488 | defaultConfigurationName = Release;
489 | };
490 | /* End XCConfigurationList section */
491 | };
492 | rootObject = 67B016651DC2041F006EF53E /* Project object */;
493 | }
494 |
--------------------------------------------------------------------------------
/SwipingCarousel.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SwipingCarousel.xcodeproj/xcshareddata/xcschemes/Swiping Carousel.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Tests/SwipingCarouselTests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Tests/SwipingCarouselTests/SwipingCarouselTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwipingCarouselTests.swift
3 | // SwipingCarouselTests
4 | //
5 | // Created by Pablo Paciello on 8/1/17.
6 | // Copyright © 2017 PPacie. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import SwipingCarousel
11 |
12 | class SwipingCarouselTests: XCTestCase {
13 |
14 | var cellManager: SwpingCarouselCellManager!
15 | var cell: SwipingCarouselCollectionViewCell!
16 |
17 | override func setUp() {
18 | super.setUp()
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | cell = SwipingCarouselCollectionViewCell()
21 | let initialSize = CGSize(width: 210, height: 278)
22 | cell.frame.size = initialSize
23 | cell.bounds.size = initialSize
24 | cellManager = SwpingCarouselCellManager(withCell: cell)
25 | cellManager.originalPoint = CGPoint(x: 165.0, y: 301.5)
26 | }
27 |
28 | override func tearDown() {
29 | cell = nil
30 | cellManager = nil
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | super.tearDown()
33 | }
34 |
35 | func testSwipingSideCells() {
36 | //After swiping up or down over a cell which is not the one in the middle of the screen, the cell should go back to its original position.
37 | cellManager.swipeDistanceOnY = 200
38 | cell.frame.size.height = 200
39 | cellManager.afterSwipeAction()
40 |
41 | XCTAssertEqual(cell.center, cellManager.originalPoint, "Cell Should go back to CenterY position")
42 | }
43 |
44 |
45 | func testSwipingDownNoDeletion() {
46 | //After swiping down over a cell which has deleteOnSwipeDown disabled, the cell should go back to its original position.
47 | cellManager.swipeDistanceOnY = 300
48 | cell.deleteOnSwipeDown = false
49 | cellManager.downAction()
50 |
51 | XCTAssertEqual(cell.center, cellManager.originalPoint, "Cell Should go back to CenterY if Delete is disabled")
52 | }
53 |
54 | func testSwipingDownAndDeletion() {
55 | //After swiping down over a cell which has deleteOnSwipeDown enabled, the cell should go to the maxY possible, disappearing from Screen.
56 | cellManager.swipeDistanceOnY = 300
57 | cell.deleteOnSwipeDown = true
58 | cellManager.downAction()
59 |
60 | XCTAssertNotEqual(cell.center, cellManager.originalPoint, "Cell Should go off screen")
61 | }
62 |
63 | func testSwipingUpNoDeletion() {
64 | //After swiping up over a cell which has deleteOnSwipeUp disabled, the cell should go back to its original position.
65 | cellManager.swipeDistanceOnY = -300
66 | cell.deleteOnSwipeUp = false
67 | cellManager.upAction()
68 |
69 | XCTAssertEqual(cell.center, cellManager.originalPoint, "Cell Should go back to CenterY if Delete is disabled")
70 | }
71 |
72 | func testSwipingUpAndDeletion() {
73 | //After swiping up over a cell which has deleteOnSwipeUp enabled, the cell should go to the maxY possible, disappearing from Screen.
74 | cellManager.swipeDistanceOnY = -300
75 | cell.deleteOnSwipeUp = true
76 | cellManager.upAction()
77 |
78 | XCTAssertNotEqual(cell.center, cellManager.originalPoint, "Cell Should go off screen")
79 | }
80 |
81 | func testPerformanceExample() {
82 | // This is an example of a performance test case.
83 | self.measure {
84 | // Put the code you want to measure the time of here.
85 | }
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------