├── BubbleCollectionViewLayout.xcworkspace
├── contents.xcworkspacedata
├── xcshareddata
│ └── IDEWorkspaceChecks.plist
└── xcuserdata
│ ├── mac-0007.xcuserdatad
│ └── UserInterfaceState.xcuserstate
│ ├── mind-0023.xcuserdatad
│ ├── UserInterfaceState.xcuserstate
│ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ └── mind.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── LICENSE
├── ObjectiveCDemo
├── ObjectiveCDemo.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ │ ├── mind-0023.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── mind.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ │ ├── mac-0007.xcuserdatad
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ │ ├── mind-0023.xcuserdatad
│ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ │ └── mind.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── ObjectiveCDemo
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Images
│ │ ├── Contents.json
│ │ └── chocolate.imageset
│ │ │ ├── Contents.json
│ │ │ └── chocolate.jpg
│ ├── close_circle.imageset
│ │ ├── Contents.json
│ │ └── close_circle.png
│ └── close_circle_selected.imageset
│ │ ├── Contents.json
│ │ └── close_circle_selected.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Class
│ ├── MIBubbleCollectionViewCell.h
│ ├── MIBubbleCollectionViewCell.m
│ ├── MICollectionViewBubbleLayout.h
│ ├── MICollectionViewBubbleLayout.m
│ ├── MIMainViewController.h
│ └── MIMainViewController.m
│ ├── Info.plist
│ └── main.m
├── README.md
└── SwiftDemo
├── SwiftDemo.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ ├── mind-0023.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ │ └── mind.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── xcuserdata
│ ├── mac-0007.xcuserdatad
│ └── xcschemes
│ │ └── xcschememanagement.plist
│ ├── mind-0023.xcuserdatad
│ └── xcschemes
│ │ └── xcschememanagement.plist
│ └── mind.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
└── SwiftDemo
├── AppDelegate.swift
├── Base.lproj
├── LaunchScreen.storyboard
└── Main.storyboard
├── Class
├── HeaderView.swift
├── MIBubbleCollectionViewCell.swift
├── MICollectionViewBubbleLayout.swift
├── MIMainViewController.swift
└── RoundImageView.swift
├── Info.plist
├── Model
└── Item.swift
└── Resources
├── Assets.xcassets
├── AppIcon.appiconset
│ └── Contents.json
├── Contents.json
├── Images
│ ├── Contents.json
│ └── chocolate.imageset
│ │ ├── Contents.json
│ │ └── chocolate.jpg
├── close_circle.imageset
│ ├── Contents.json
│ └── close_circle.png
└── close_circle_selected.imageset
│ ├── Contents.json
│ └── close_circle_selected.png
└── ItemResources.swift
/BubbleCollectionViewLayout.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BubbleCollectionViewLayout.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mac-0007.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mac-0007.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mind-0023.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mind-0023.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mind-0023.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
17 |
18 |
19 |
21 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mind.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/BubbleCollectionViewLayout.xcworkspace/xcuserdata/mind.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Mindinventory
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 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 781F56881FD6A2E3002E226A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 781F56871FD6A2E3002E226A /* AppDelegate.m */; };
11 | 781F568E1FD6A2E3002E226A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 781F568C1FD6A2E3002E226A /* Main.storyboard */; };
12 | 781F56901FD6A2E3002E226A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 781F568F1FD6A2E3002E226A /* Assets.xcassets */; };
13 | 781F56931FD6A2E3002E226A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 781F56911FD6A2E3002E226A /* LaunchScreen.storyboard */; };
14 | 781F56961FD6A2E3002E226A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 781F56951FD6A2E3002E226A /* main.m */; };
15 | 781F56A01FD6B045002E226A /* MICollectionViewBubbleLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 781F569F1FD6B045002E226A /* MICollectionViewBubbleLayout.m */; };
16 | 781F56A31FD6B713002E226A /* MIMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 781F56A21FD6B713002E226A /* MIMainViewController.m */; };
17 | 781F56A61FD6B73F002E226A /* MIBubbleCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 781F56A51FD6B73F002E226A /* MIBubbleCollectionViewCell.m */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXFileReference section */
21 | 781F56831FD6A2E3002E226A /* ObjectiveCDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ObjectiveCDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
22 | 781F56861FD6A2E3002E226A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
23 | 781F56871FD6A2E3002E226A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
24 | 781F568D1FD6A2E3002E226A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
25 | 781F568F1FD6A2E3002E226A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
26 | 781F56921FD6A2E3002E226A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
27 | 781F56941FD6A2E3002E226A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | 781F56951FD6A2E3002E226A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
29 | 781F569E1FD6B045002E226A /* MICollectionViewBubbleLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MICollectionViewBubbleLayout.h; sourceTree = ""; };
30 | 781F569F1FD6B045002E226A /* MICollectionViewBubbleLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MICollectionViewBubbleLayout.m; sourceTree = ""; };
31 | 781F56A11FD6B713002E226A /* MIMainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MIMainViewController.h; sourceTree = ""; };
32 | 781F56A21FD6B713002E226A /* MIMainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MIMainViewController.m; sourceTree = ""; };
33 | 781F56A41FD6B73F002E226A /* MIBubbleCollectionViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MIBubbleCollectionViewCell.h; sourceTree = ""; };
34 | 781F56A51FD6B73F002E226A /* MIBubbleCollectionViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MIBubbleCollectionViewCell.m; sourceTree = ""; };
35 | /* End PBXFileReference section */
36 |
37 | /* Begin PBXFrameworksBuildPhase section */
38 | 781F56801FD6A2E3002E226A /* Frameworks */ = {
39 | isa = PBXFrameworksBuildPhase;
40 | buildActionMask = 2147483647;
41 | files = (
42 | );
43 | runOnlyForDeploymentPostprocessing = 0;
44 | };
45 | /* End PBXFrameworksBuildPhase section */
46 |
47 | /* Begin PBXGroup section */
48 | 781F567A1FD6A2E3002E226A = {
49 | isa = PBXGroup;
50 | children = (
51 | 781F56851FD6A2E3002E226A /* ObjectiveCDemo */,
52 | 781F56841FD6A2E3002E226A /* Products */,
53 | );
54 | sourceTree = "";
55 | };
56 | 781F56841FD6A2E3002E226A /* Products */ = {
57 | isa = PBXGroup;
58 | children = (
59 | 781F56831FD6A2E3002E226A /* ObjectiveCDemo.app */,
60 | );
61 | name = Products;
62 | sourceTree = "";
63 | };
64 | 781F56851FD6A2E3002E226A /* ObjectiveCDemo */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 781F56861FD6A2E3002E226A /* AppDelegate.h */,
68 | 781F56871FD6A2E3002E226A /* AppDelegate.m */,
69 | 781F56941FD6A2E3002E226A /* Info.plist */,
70 | 781F568F1FD6A2E3002E226A /* Assets.xcassets */,
71 | 781F56911FD6A2E3002E226A /* LaunchScreen.storyboard */,
72 | 781F568C1FD6A2E3002E226A /* Main.storyboard */,
73 | 781F569D1FD6A4A5002E226A /* Class */,
74 | 781F56951FD6A2E3002E226A /* main.m */,
75 | );
76 | path = ObjectiveCDemo;
77 | sourceTree = "";
78 | };
79 | 781F569D1FD6A4A5002E226A /* Class */ = {
80 | isa = PBXGroup;
81 | children = (
82 | 781F56A11FD6B713002E226A /* MIMainViewController.h */,
83 | 781F56A21FD6B713002E226A /* MIMainViewController.m */,
84 | 781F56A41FD6B73F002E226A /* MIBubbleCollectionViewCell.h */,
85 | 781F56A51FD6B73F002E226A /* MIBubbleCollectionViewCell.m */,
86 | 781F569E1FD6B045002E226A /* MICollectionViewBubbleLayout.h */,
87 | 781F569F1FD6B045002E226A /* MICollectionViewBubbleLayout.m */,
88 | );
89 | path = Class;
90 | sourceTree = "";
91 | };
92 | /* End PBXGroup section */
93 |
94 | /* Begin PBXNativeTarget section */
95 | 781F56821FD6A2E3002E226A /* ObjectiveCDemo */ = {
96 | isa = PBXNativeTarget;
97 | buildConfigurationList = 781F56991FD6A2E3002E226A /* Build configuration list for PBXNativeTarget "ObjectiveCDemo" */;
98 | buildPhases = (
99 | 781F567F1FD6A2E3002E226A /* Sources */,
100 | 781F56801FD6A2E3002E226A /* Frameworks */,
101 | 781F56811FD6A2E3002E226A /* Resources */,
102 | );
103 | buildRules = (
104 | );
105 | dependencies = (
106 | );
107 | name = ObjectiveCDemo;
108 | productName = ObjectiveCDemo;
109 | productReference = 781F56831FD6A2E3002E226A /* ObjectiveCDemo.app */;
110 | productType = "com.apple.product-type.application";
111 | };
112 | /* End PBXNativeTarget section */
113 |
114 | /* Begin PBXProject section */
115 | 781F567B1FD6A2E3002E226A /* Project object */ = {
116 | isa = PBXProject;
117 | attributes = {
118 | LastUpgradeCheck = 1240;
119 | ORGANIZATIONNAME = "Jignesh-0007";
120 | TargetAttributes = {
121 | 781F56821FD6A2E3002E226A = {
122 | CreatedOnToolsVersion = 9.1;
123 | ProvisioningStyle = Manual;
124 | };
125 | };
126 | };
127 | buildConfigurationList = 781F567E1FD6A2E3002E226A /* Build configuration list for PBXProject "ObjectiveCDemo" */;
128 | compatibilityVersion = "Xcode 8.0";
129 | developmentRegion = en;
130 | hasScannedForEncodings = 0;
131 | knownRegions = (
132 | en,
133 | Base,
134 | );
135 | mainGroup = 781F567A1FD6A2E3002E226A;
136 | productRefGroup = 781F56841FD6A2E3002E226A /* Products */;
137 | projectDirPath = "";
138 | projectRoot = "";
139 | targets = (
140 | 781F56821FD6A2E3002E226A /* ObjectiveCDemo */,
141 | );
142 | };
143 | /* End PBXProject section */
144 |
145 | /* Begin PBXResourcesBuildPhase section */
146 | 781F56811FD6A2E3002E226A /* Resources */ = {
147 | isa = PBXResourcesBuildPhase;
148 | buildActionMask = 2147483647;
149 | files = (
150 | 781F56931FD6A2E3002E226A /* LaunchScreen.storyboard in Resources */,
151 | 781F56901FD6A2E3002E226A /* Assets.xcassets in Resources */,
152 | 781F568E1FD6A2E3002E226A /* Main.storyboard in Resources */,
153 | );
154 | runOnlyForDeploymentPostprocessing = 0;
155 | };
156 | /* End PBXResourcesBuildPhase section */
157 |
158 | /* Begin PBXSourcesBuildPhase section */
159 | 781F567F1FD6A2E3002E226A /* Sources */ = {
160 | isa = PBXSourcesBuildPhase;
161 | buildActionMask = 2147483647;
162 | files = (
163 | 781F56A61FD6B73F002E226A /* MIBubbleCollectionViewCell.m in Sources */,
164 | 781F56A01FD6B045002E226A /* MICollectionViewBubbleLayout.m in Sources */,
165 | 781F56961FD6A2E3002E226A /* main.m in Sources */,
166 | 781F56881FD6A2E3002E226A /* AppDelegate.m in Sources */,
167 | 781F56A31FD6B713002E226A /* MIMainViewController.m in Sources */,
168 | );
169 | runOnlyForDeploymentPostprocessing = 0;
170 | };
171 | /* End PBXSourcesBuildPhase section */
172 |
173 | /* Begin PBXVariantGroup section */
174 | 781F568C1FD6A2E3002E226A /* Main.storyboard */ = {
175 | isa = PBXVariantGroup;
176 | children = (
177 | 781F568D1FD6A2E3002E226A /* Base */,
178 | );
179 | name = Main.storyboard;
180 | sourceTree = "";
181 | };
182 | 781F56911FD6A2E3002E226A /* LaunchScreen.storyboard */ = {
183 | isa = PBXVariantGroup;
184 | children = (
185 | 781F56921FD6A2E3002E226A /* Base */,
186 | );
187 | name = LaunchScreen.storyboard;
188 | sourceTree = "";
189 | };
190 | /* End PBXVariantGroup section */
191 |
192 | /* Begin XCBuildConfiguration section */
193 | 781F56971FD6A2E3002E226A /* Debug */ = {
194 | isa = XCBuildConfiguration;
195 | buildSettings = {
196 | ALWAYS_SEARCH_USER_PATHS = NO;
197 | CLANG_ANALYZER_NONNULL = YES;
198 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
200 | CLANG_CXX_LIBRARY = "libc++";
201 | CLANG_ENABLE_MODULES = YES;
202 | CLANG_ENABLE_OBJC_ARC = YES;
203 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
204 | CLANG_WARN_BOOL_CONVERSION = YES;
205 | CLANG_WARN_COMMA = YES;
206 | CLANG_WARN_CONSTANT_CONVERSION = YES;
207 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
209 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
210 | CLANG_WARN_EMPTY_BODY = YES;
211 | CLANG_WARN_ENUM_CONVERSION = YES;
212 | CLANG_WARN_INFINITE_RECURSION = YES;
213 | CLANG_WARN_INT_CONVERSION = YES;
214 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
215 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
216 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
217 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
218 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
219 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
220 | CLANG_WARN_STRICT_PROTOTYPES = YES;
221 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
222 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
223 | CLANG_WARN_UNREACHABLE_CODE = YES;
224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
225 | CODE_SIGN_IDENTITY = "iPhone Developer";
226 | COPY_PHASE_STRIP = NO;
227 | DEBUG_INFORMATION_FORMAT = dwarf;
228 | ENABLE_STRICT_OBJC_MSGSEND = YES;
229 | ENABLE_TESTABILITY = YES;
230 | GCC_C_LANGUAGE_STANDARD = gnu11;
231 | GCC_DYNAMIC_NO_PIC = NO;
232 | GCC_NO_COMMON_BLOCKS = YES;
233 | GCC_OPTIMIZATION_LEVEL = 0;
234 | GCC_PREPROCESSOR_DEFINITIONS = (
235 | "DEBUG=1",
236 | "$(inherited)",
237 | );
238 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
239 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
240 | GCC_WARN_UNDECLARED_SELECTOR = YES;
241 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
242 | GCC_WARN_UNUSED_FUNCTION = YES;
243 | GCC_WARN_UNUSED_VARIABLE = YES;
244 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
245 | MTL_ENABLE_DEBUG_INFO = YES;
246 | ONLY_ACTIVE_ARCH = YES;
247 | SDKROOT = iphoneos;
248 | };
249 | name = Debug;
250 | };
251 | 781F56981FD6A2E3002E226A /* Release */ = {
252 | isa = XCBuildConfiguration;
253 | buildSettings = {
254 | ALWAYS_SEARCH_USER_PATHS = NO;
255 | CLANG_ANALYZER_NONNULL = YES;
256 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
257 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
258 | CLANG_CXX_LIBRARY = "libc++";
259 | CLANG_ENABLE_MODULES = YES;
260 | CLANG_ENABLE_OBJC_ARC = YES;
261 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
262 | CLANG_WARN_BOOL_CONVERSION = YES;
263 | CLANG_WARN_COMMA = YES;
264 | CLANG_WARN_CONSTANT_CONVERSION = YES;
265 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
266 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
267 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
268 | CLANG_WARN_EMPTY_BODY = YES;
269 | CLANG_WARN_ENUM_CONVERSION = YES;
270 | CLANG_WARN_INFINITE_RECURSION = YES;
271 | CLANG_WARN_INT_CONVERSION = YES;
272 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
273 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
274 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
276 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
277 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
278 | CLANG_WARN_STRICT_PROTOTYPES = YES;
279 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
280 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
281 | CLANG_WARN_UNREACHABLE_CODE = YES;
282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
283 | CODE_SIGN_IDENTITY = "iPhone Developer";
284 | COPY_PHASE_STRIP = NO;
285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
286 | ENABLE_NS_ASSERTIONS = NO;
287 | ENABLE_STRICT_OBJC_MSGSEND = YES;
288 | GCC_C_LANGUAGE_STANDARD = gnu11;
289 | GCC_NO_COMMON_BLOCKS = YES;
290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
292 | GCC_WARN_UNDECLARED_SELECTOR = YES;
293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
294 | GCC_WARN_UNUSED_FUNCTION = YES;
295 | GCC_WARN_UNUSED_VARIABLE = YES;
296 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
297 | MTL_ENABLE_DEBUG_INFO = NO;
298 | SDKROOT = iphoneos;
299 | VALIDATE_PRODUCT = YES;
300 | };
301 | name = Release;
302 | };
303 | 781F569A1FD6A2E3002E226A /* Debug */ = {
304 | isa = XCBuildConfiguration;
305 | buildSettings = {
306 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
307 | CODE_SIGN_STYLE = Manual;
308 | DEVELOPMENT_TEAM = "";
309 | INFOPLIST_FILE = ObjectiveCDemo/Info.plist;
310 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
311 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
312 | PRODUCT_BUNDLE_IDENTIFIER = com.mi.ObjectiveCDemo;
313 | PRODUCT_NAME = "$(TARGET_NAME)";
314 | PROVISIONING_PROFILE_SPECIFIER = "";
315 | TARGETED_DEVICE_FAMILY = "1,2";
316 | };
317 | name = Debug;
318 | };
319 | 781F569B1FD6A2E3002E226A /* Release */ = {
320 | isa = XCBuildConfiguration;
321 | buildSettings = {
322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
323 | CODE_SIGN_STYLE = Manual;
324 | DEVELOPMENT_TEAM = "";
325 | INFOPLIST_FILE = ObjectiveCDemo/Info.plist;
326 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
327 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
328 | PRODUCT_BUNDLE_IDENTIFIER = com.mi.ObjectiveCDemo;
329 | PRODUCT_NAME = "$(TARGET_NAME)";
330 | PROVISIONING_PROFILE_SPECIFIER = "";
331 | TARGETED_DEVICE_FAMILY = "1,2";
332 | };
333 | name = Release;
334 | };
335 | /* End XCBuildConfiguration section */
336 |
337 | /* Begin XCConfigurationList section */
338 | 781F567E1FD6A2E3002E226A /* Build configuration list for PBXProject "ObjectiveCDemo" */ = {
339 | isa = XCConfigurationList;
340 | buildConfigurations = (
341 | 781F56971FD6A2E3002E226A /* Debug */,
342 | 781F56981FD6A2E3002E226A /* Release */,
343 | );
344 | defaultConfigurationIsVisible = 0;
345 | defaultConfigurationName = Release;
346 | };
347 | 781F56991FD6A2E3002E226A /* Build configuration list for PBXNativeTarget "ObjectiveCDemo" */ = {
348 | isa = XCConfigurationList;
349 | buildConfigurations = (
350 | 781F569A1FD6A2E3002E226A /* Debug */,
351 | 781F569B1FD6A2E3002E226A /* Release */,
352 | );
353 | defaultConfigurationIsVisible = 0;
354 | defaultConfigurationName = Release;
355 | };
356 | /* End XCConfigurationList section */
357 | };
358 | rootObject = 781F567B1FD6A2E3002E226A /* Project object */;
359 | }
360 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.xcworkspace/xcuserdata/mind-0023.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.xcworkspace/xcuserdata/mind-0023.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.xcworkspace/xcuserdata/mind.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/project.xcworkspace/xcuserdata/mind.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/xcuserdata/mac-0007.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ObjectiveCDemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 781F56821FD6A2E3002E226A
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/xcuserdata/mind-0023.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ObjectiveCDemo.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo.xcodeproj/xcuserdata/mind.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ObjectiveCDemo.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 1
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // 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.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // 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.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // 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.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // 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.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/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 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/Images/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/Images/chocolate.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "chocolate.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/Images/chocolate.imageset/chocolate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/Images/chocolate.imageset/chocolate.jpg
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/close_circle.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "close_circle.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | },
21 | "properties" : {
22 | "template-rendering-intent" : "template"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/close_circle.imageset/close_circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/close_circle.imageset/close_circle.png
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/close_circle_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "close_circle_selected.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/close_circle_selected.imageset/close_circle_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/ObjectiveCDemo/ObjectiveCDemo/Assets.xcassets/close_circle_selected.imageset/close_circle_selected.png
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | HelveticaNeue-Bold
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/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 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
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 |
106 |
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 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Class/MIBubbleCollectionViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // MIBubbleCollectionViewCell.h
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MIBubbleCollectionViewCell : UICollectionViewCell
12 | @property (weak, nonatomic) IBOutlet UILabel *lblTitle;
13 | @property (weak, nonatomic) IBOutlet UIImageView *imageRoundItem;
14 | @property (weak, nonatomic) IBOutlet UIButton *btnClose;
15 | @property (strong, nonatomic) NSArray *arrayFiltered;
16 | @end
17 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Class/MIBubbleCollectionViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // MIBubbleCollectionViewCell.m
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import "MIBubbleCollectionViewCell.h"
10 |
11 | @implementation MIBubbleCollectionViewCell
12 |
13 |
14 | - (void)awakeFromNib {
15 | [super awakeFromNib];
16 | }
17 |
18 | - (void)layoutSubviews {
19 | [super layoutSubviews];
20 | [self.layer setCornerRadius:self.frame.size.height/2];
21 | }
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Class/MICollectionViewBubbleLayout.h:
--------------------------------------------------------------------------------
1 | //
2 | // MICollectionViewBubbleLayout.h
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol MICollectionViewBubbleLayoutDelegate
12 |
13 | - (CGSize)collectionView:(UICollectionView *)collectionView itemSizeAtIndexPath:(NSIndexPath *)indexPath;
14 |
15 | @end
16 |
17 | @interface MICollectionViewBubbleLayout : UICollectionViewFlowLayout
18 |
19 | @property (nonatomic, weak) id delegate;
20 |
21 | - (id)initWithDelegate:(id )delegate;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Class/MICollectionViewBubbleLayout.m:
--------------------------------------------------------------------------------
1 | //
2 | // MICollectionViewBubbleLayout.m
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import "MICollectionViewBubbleLayout.h"
10 |
11 | #define kDefaultInterItemSpacing 5.0f
12 | #define kDefaultLineSpacing 5.0f
13 |
14 | @interface MICollectionViewBubbleLayout ()
15 |
16 | @property (nonatomic, strong) NSDictionary *itemLayoutDictionary;
17 | @property (nonatomic) CGSize contentSize;
18 |
19 | @end
20 |
21 | @implementation MICollectionViewBubbleLayout
22 |
23 | - (id)initWithDelegate:(id )delegate
24 | {
25 | self = [super init];
26 |
27 | if (self) {
28 | self.delegate = delegate;
29 | self.scrollDirection = UICollectionViewScrollDirectionVertical;
30 | self.minimumLineSpacing = kDefaultLineSpacing;
31 | self.minimumInteritemSpacing = kDefaultInterItemSpacing;
32 | }
33 |
34 | return self;
35 | }
36 |
37 | - (void)prepareLayout
38 | {
39 | [super prepareLayout];
40 |
41 | if (self.collectionView.numberOfSections == 0 || [self.collectionView numberOfItemsInSection:0] == 0)
42 | return;
43 |
44 | if (self.itemLayoutDictionary) self.itemLayoutDictionary = nil;
45 |
46 | CGFloat x = 0.0f;
47 | CGFloat y = 0.0f;
48 | CGSize iSize = CGSizeZero;
49 |
50 | NSIndexPath *indexPath;
51 | NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];
52 | NSMutableDictionary *itemLayoutInformation = [NSMutableDictionary dictionary];
53 |
54 | for (int itemIndex = 0; itemIndex < numberOfItems; itemIndex ++) {
55 | indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:0];
56 | iSize = [self.delegate collectionView:self.collectionView itemSizeAtIndexPath:indexPath];
57 |
58 | CGRect itemRect = CGRectMake(x, y, iSize.width, iSize.height);
59 | if (x > 0 && x + iSize.width + self.minimumInteritemSpacing > self.collectionView.frame.size.width) {
60 | //...Checking if item width is greater than collection view width then set item in new row.
61 | itemRect.origin.x = 0.0f;
62 | itemRect.origin.y = y + iSize.height + self.minimumLineSpacing;
63 | }
64 |
65 | UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
66 | [attributes setFrame:itemRect];
67 | [itemLayoutInformation setObject:attributes forKey:indexPath];
68 |
69 | x = itemRect.origin.x + iSize.width + self.minimumInteritemSpacing;
70 | y = itemRect.origin.y;
71 | }
72 | y += iSize.height;
73 | x = 0.0f;
74 |
75 | self.contentSize = CGSizeMake(self.collectionView.frame.size.width, y + self.minimumLineSpacing);
76 | self.itemLayoutDictionary = [NSDictionary dictionaryWithDictionary:itemLayoutInformation];
77 | }
78 |
79 | - (CGSize)collectionViewContentSize {
80 | return self.contentSize;
81 | }
82 |
83 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
84 | NSMutableArray *attributes = [NSMutableArray array];
85 |
86 | NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:0];
87 | for (int itemIndex = 0; itemIndex < numberOfItems; itemIndex ++) {
88 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:0];
89 | UICollectionViewLayoutAttributes *itemAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];
90 | if (CGRectIntersectsRect(rect, itemAttributes.frame)) {
91 | [attributes addObject:itemAttributes];
92 | }
93 | }
94 |
95 | return attributes;
96 | }
97 |
98 | - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
99 | UICollectionViewLayoutAttributes *attributes = [self.itemLayoutDictionary objectForKey:indexPath];
100 | return attributes;
101 | }
102 |
103 | @end
104 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Class/MIMainViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // MIMainViewController.h
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MIMainViewController : UIViewController
12 |
13 | @property(nonatomic, strong) IBOutlet UICollectionView *collVData;
14 | @property(nonatomic, strong) IBOutlet UITextField *textfiledEnterDetails;
15 | @property(nonatomic, strong) IBOutlet UIButton *buttonDone;
16 | @property(nonatomic, strong) IBOutlet UIButton *buttonAddMoreData;
17 | @property(nonatomic, strong) IBOutlet UIView *viewAddMoreData;
18 |
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Class/MIMainViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MIMainViewController.m
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import "MIMainViewController.h"
10 | #import "MICollectionViewBubbleLayout.h"
11 | #import "MIBubbleCollectionViewCell.h"
12 | #define CTitlePadding 15
13 |
14 | @interface MIMainViewController ()
15 | {
16 | IBOutlet UICollectionView *collVData;
17 | NSMutableArray *arrData;
18 | NSMutableDictionary *Items;
19 | }
20 | @end
21 |
22 | @implementation MIMainViewController
23 |
24 | @synthesize collVData;
25 |
26 |
27 | - (void)viewDidLoad {
28 | [super viewDidLoad];
29 |
30 | arrData = [[NSMutableArray alloc] init];
31 |
32 | [arrData addObject:[self createDictionary:@"Glazed" isSelected:[NSNumber numberWithBool:false]]];
33 | [arrData addObject:[self createDictionary:@"Sugar" isSelected:[NSNumber numberWithBool:false]]];
34 | [arrData addObject:[self createDictionary:@"Powdered Sugar" isSelected:[NSNumber numberWithBool:false]]];
35 | [arrData addObject:[self createDictionary:@"Chocolate with Sprinkles" isSelected:[NSNumber numberWithBool:false]]];
36 | [arrData addObject:[self createDictionary:@"Chocolate" isSelected:[NSNumber numberWithBool:false]]];
37 | [arrData addObject:[self createDictionary:@"Devil's Food" isSelected:[NSNumber numberWithBool:false]]];
38 | [arrData addObject:[self createDictionary:@"Maple" isSelected:[NSNumber numberWithBool:false]]];
39 | [arrData addObject:[self createDictionary:@"Sugar" isSelected:[NSNumber numberWithBool:false]]];
40 | [arrData addObject:[self createDictionary:@"Blueberry" isSelected:[NSNumber numberWithBool:false]]];
41 | [arrData addObject:[self createDictionary:@"Regular" isSelected:[NSNumber numberWithBool:false]]];
42 | [arrData addObject:[self createDictionary:@"Powdered Sugar" isSelected:[NSNumber numberWithBool:false]]];
43 | [arrData addObject:[self createDictionary:@"Glazed" isSelected:[NSNumber numberWithBool:false]]];
44 | [arrData addObject:[self createDictionary:@"Sugar" isSelected:[NSNumber numberWithBool:false]]];
45 | [arrData addObject:[self createDictionary:@"Powdered Sugar" isSelected:[NSNumber numberWithBool:false]]];
46 | [arrData addObject:[self createDictionary:@"Chocolate with Sprinkles" isSelected:[NSNumber numberWithBool:false]]];
47 | [arrData addObject:[self createDictionary:@"Chocolate" isSelected:[NSNumber numberWithBool:false]]];
48 | [arrData addObject:[self createDictionary:@"Devil's Food" isSelected:[NSNumber numberWithBool:false]]];
49 | [arrData addObject:[self createDictionary:@"Maple" isSelected:[NSNumber numberWithBool:false]]];
50 | [arrData addObject:[self createDictionary:@"Sugar" isSelected:[NSNumber numberWithBool:false]]];
51 | [arrData addObject:[self createDictionary:@"Blueberry" isSelected:[NSNumber numberWithBool:false]]];
52 | [arrData addObject:[self createDictionary:@"Regular" isSelected:[NSNumber numberWithBool:false]]];
53 | [arrData addObject:[self createDictionary:@"Chocolate with Sprinkles" isSelected:[NSNumber numberWithBool:false]]];
54 | [arrData addObject:[self createDictionary:@"Sugar" isSelected:[NSNumber numberWithBool:false]]];
55 | [arrData addObject:[self createDictionary:@"Powdered Sugar" isSelected:[NSNumber numberWithBool:false]]];
56 | [arrData addObject:[self createDictionary:@"Blueberry" isSelected:[NSNumber numberWithBool:false]]];
57 |
58 |
59 | //...UICollectionView setup
60 | MICollectionViewBubbleLayout *layout = [[MICollectionViewBubbleLayout alloc] initWithDelegate:self];
61 | [layout setMinimumLineSpacing:6.0f];
62 | [layout setMinimumInteritemSpacing:6.0f];
63 | [collVData setCollectionViewLayout:layout];
64 | }
65 |
66 | //MARK: - Function For Adding Value in Dictionary -
67 | -(NSMutableDictionary*)createDictionary:(NSString*)itemName isSelected:(id)isSelected{
68 |
69 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
70 | [dict setValue:itemName forKey:@"name"];
71 | [dict setValue:isSelected forKey:@"isSelected"];
72 | return dict;
73 | }
74 |
75 | - (void)didReceiveMemoryWarning {
76 | [super didReceiveMemoryWarning];
77 | }
78 |
79 | //MARK: - Remove cell Method -
80 | -(IBAction)closeBtnTapped:(UIButton*)sender
81 | {
82 | NSInteger indexRow = sender.tag;
83 | [arrData removeObjectAtIndex:indexRow];
84 | [collVData reloadData];
85 | }
86 | -(IBAction)doneButtonTapped:(UIButton*)sender
87 | {
88 | if ([self.textfiledEnterDetails hasText])
89 | {
90 | [arrData addObject:[self createDictionary:self.textfiledEnterDetails.text isSelected:[NSNumber numberWithBool:false]]];
91 | [self.textfiledEnterDetails resignFirstResponder];
92 | [collVData reloadData];
93 | self.textfiledEnterDetails.text = @"";
94 | }
95 | }
96 | -(IBAction)addmoreButtonTapped:(UIButton*)sender
97 | {
98 | [self.buttonAddMoreData setHidden:YES];
99 | [self.viewAddMoreData setHidden:NO];
100 | }
101 | #pragma mark -
102 | #pragma mark - UICollectionView Delegate & Datasource
103 |
104 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
105 | return arrData.count;
106 | }
107 |
108 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
109 |
110 | NSString *indentifier = @"MIBubbleCollectionViewCell";
111 |
112 | MIBubbleCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:indentifier forIndexPath:indexPath];
113 | cell.btnClose.tag = indexPath.row;
114 | cell.layer.borderColor = [[UIColor orangeColor] CGColor];
115 | cell.layer.borderWidth = 1;
116 | [cell.btnClose addTarget:self action:@selector(closeBtnTapped:) forControlEvents:UIControlEventTouchUpInside];
117 | [cell.lblTitle setText:[arrData[indexPath.row] valueForKey:@"name"]];
118 | cell.imageRoundItem.image = [UIImage imageNamed:@"chocolate"];
119 | cell.imageRoundItem.layer.cornerRadius = 10.0;
120 | if ([arrData[indexPath.row] valueForKey:@"isSelected"] == [NSNumber numberWithBool:true]){
121 | cell.backgroundColor = [UIColor orangeColor];
122 | cell.btnClose.tintColor = [UIColor whiteColor];
123 | cell.lblTitle.textColor = [UIColor whiteColor];
124 | }else{
125 | cell.backgroundColor = [UIColor colorWithRed:1.0 green:0.5 blue:0.0 alpha:0.2];
126 | cell.btnClose.tintColor = [UIColor orangeColor];
127 | cell.lblTitle.textColor = [UIColor blackColor];
128 | }
129 | return cell;
130 | }
131 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
132 | {
133 | NSMutableDictionary *dict = arrData[indexPath.row];
134 |
135 | if ([dict valueForKey:@"isSelected"] == [NSNumber numberWithBool:false]){
136 | [dict setValue:[NSNumber numberWithBool:true] forKey:@"isSelected"];
137 | }else{
138 | [dict setValue:[NSNumber numberWithBool:false] forKey:@"isSelected"];
139 | }
140 |
141 | [arrData replaceObjectAtIndex:indexPath.row withObject:dict];
142 | [collVData reloadData];
143 |
144 | }
145 |
146 | #pragma mark -
147 | #pragma mark - MICollectionViewBubbleLayoutDelegate
148 |
149 | - (CGSize)collectionView:(UICollectionView *)collectionView itemSizeAtIndexPath:(NSIndexPath *)indexPath {
150 |
151 | NSString *title = [arrData[indexPath.row] valueForKey:@"name"];
152 | CGSize size = [title sizeWithAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Bold" size:15]}];
153 | size.width = ceilf(size.width + CTitlePadding * 5.5);
154 | size.height = 35;
155 |
156 | //...Checking if item width is greater than collection view width then set item width == collection view width.
157 | if (size.width > collectionView.frame.size.width){
158 | size.width = collectionView.frame.size.width;
159 | }
160 | return size;
161 | }
162 |
163 |
164 | @end
165 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ObjectiveCDemo/ObjectiveCDemo/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ObjectiveCDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BubbleCollectionViewLayout
2 | Used to get layout like following screens in UICollectionView using custom layout.
3 |
4 |
5 | 
6 | 
7 | 
8 |
9 | # Requirements
10 | Minimum OS 8.1 and later
11 |
12 | # Manual Installation
13 | You can directly add Below the source files from Class folder to your project.
14 |
15 | # Objective C
16 | 1) MIBubbleCollectionViewCell.h
17 | 2) MIBubbleCollectionViewCell.m
18 | 3) MICollectionViewBubbleLayout.h
19 | 4) MICollectionViewBubbleLayout.m
20 | # Swift
21 | 1) MIBubbleCollectionViewCell.swift
22 | 2) MICollectionViewBubbleLayout.swift
23 | 3) RoundImageView.swift
24 | 4) HeaderView.swift
25 |
26 | # Introduce
27 | MICollectionViewBubbleLayout is subclass of UICollectionViewFlowLayout with the custom layout.
28 |
29 | # Usage
30 |
31 | - The easy way is to use UICollectionViewFlowLayout as it is. You can also subclass it if you intend to change the default behaviour.
32 | - Either use it as a list to select the different tags and it's values or add the tags or value and show it in a list
33 |
34 |
35 | Here is the instruction of how to use UICollectionViewFlowLayout in the Storyboard.
36 |
37 | 1) Add native UICollectionView to the storyboard, establish relationships with its view controllers.
38 | 2) Add UICollectionViewCell in the UICollectionView to the storyboard.
39 | 3)Chose the MIBubbleCollectionViewCell as a custom class inside the UICollectionViewCell to the storyboard.
40 | Configuration for change DefaultInterItemSpacing & DefaultLineSpacing of collecttionview cell you just have to change the value of below two constant in MICollectionViewBubbleLayout.h
41 |
42 | #define kDefaultInterItemSpacing 5.0f
43 |
44 | #define kDefaultLineSpacing 5.0f
45 |
46 | ### Objective C -
47 | 1. Add "MICollectionViewBubbleLayout" ObjectiveC files to your project.
48 |
49 | 2. Conform delegate "MICollectionViewBubbleLayoutDelegate" to your class.
50 |
51 | 3. Set bubble layout in collectionview.
52 |
53 | MICollectionViewBubbleLayout *layout = [[MICollectionViewBubbleLayout alloc] initWithDelegate:self];
54 | [layout setMinimumLineSpacing:6.0f];
55 | [layout setMinimumInteritemSpacing:6.0f];
56 | [collVData setCollectionViewLayout:layout];
57 |
58 | 4. Implement MICollectionViewBubbleLayoutDelegate method to return size according to your text content.
59 |
60 | - (CGSize)collectionView:(UICollectionView *)collectionView itemSizeAtIndexPath:(NSIndexPath *)indexPath {
61 |
62 | NSString *title = arrData[indexPath.row];
63 | CGSize size = [title sizeWithAttributes:@{NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Bold" size:15]}];
64 | size.width = ceilf(size.width + CTitlePadding * 2);
65 | size.height = 24;
66 |
67 | //...Checking if item width is greater than collection view width then set item width == collection view width.
68 | if (size.width > collectionView.frame.size.width)
69 | size.width = collectionView.frame.size.width;
70 | return size;
71 | }
72 |
73 |
74 | ### Swift -
75 | 1. Add "MICollectionViewBubbleLayout" Swift file to your project.
76 |
77 | 2. Conform delegate "MICollectionViewBubbleLayoutDelegate" to your class.
78 |
79 | 3. Set bubble layout in collectionview.
80 |
81 | let bubbleLayout = MICollectionViewBubbleLayout()
82 | bubbleLayout.minimumLineSpacing = 6.0
83 | bubbleLayout.minimumInteritemSpacing = 0
84 | bubbleLayout.horizontalAlignment = .leading
85 | collVData.setCollectionViewLayout(bubbleLayout, animated: false)
86 | bubbleLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
87 |
88 | 4. Implement MICollectionViewBubbleLayoutDelegate method to return size according to your text content.
89 |
90 | func collectionView(_ collectionView:UICollectionView, itemSizeAt indexPath:NSIndexPath) -> CGSize
91 | {
92 | let title = arrData[indexPath.row].name
93 | var size = title.size(withAttributes: [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue-Bold", size: 15)!])
94 | let closeButtonWidth = 20.0
95 | let imageWidth = 20.0
96 | let spacing = 18.0
97 | let totalWidth = Float(size.width + closeButtonWidth + imageWidth + spacing + CGFloat(kItemPadding * 2))
98 | size.width = CGFloat(ceilf(totalWidth))
99 | size.height = 40
100 |
101 | //...Checking if item width is greater than collection view width then set item width == collection view width.
102 | if size.width > collectionView.frame.size.width {
103 | size.width = collectionView.frame.size.width
104 | }
105 |
106 | return size;
107 | }
108 |
109 |
110 | 5. If require to add header view
111 |
112 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
113 | switch kind {
114 | case UICollectionView.elementKindSectionHeader:
115 |
116 | let headerView = collVData.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderView", for: indexPath) as! HeaderView
117 | headerView.lblTitleText.text = arrData[indexPath.section].title
118 | headerView.lblTitleText.sizeToFit()
119 | return headerView
120 |
121 | default:
122 | return UICollectionReusableView()
123 |
124 | }
125 | }
126 |
127 |
128 |
129 | # LICENSE!
130 |
131 | BubbleCollectionViewLayout is [MIT-licensed](https://github.com/mindinventory/BubbleCollectionViewLayout/blob/master/LICENSE).
132 |
133 | ## Let us know!
134 | We’d be really happy if you send us links to your projects where you use our component. Just send an email to sales@mindinventory.com And do let us know if you have any questions or suggestion regarding our work.
135 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 637EFAD82863444700364FEE /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637EFAD72863444700364FEE /* Item.swift */; };
11 | 637EFADB286344AA00364FEE /* ItemResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637EFADA286344AA00364FEE /* ItemResources.swift */; };
12 | 637EFADD286344E500364FEE /* RoundImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637EFADC286344E500364FEE /* RoundImageView.swift */; };
13 | 781F56691FD6A2AB002E226A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 781F56681FD6A2AB002E226A /* AppDelegate.swift */; };
14 | 781F56701FD6A2AB002E226A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 781F566F1FD6A2AB002E226A /* Assets.xcassets */; };
15 | 781F56731FD6A2AB002E226A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 781F56711FD6A2AB002E226A /* LaunchScreen.storyboard */; };
16 | 7839D8AD1FD7CA5100B5E49F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7839D8AB1FD7CA5100B5E49F /* Main.storyboard */; };
17 | 788914431FD6D6C500FCFA4B /* MIMainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788914421FD6D6C500FCFA4B /* MIMainViewController.swift */; };
18 | 788914451FD6D6FC00FCFA4B /* MICollectionViewBubbleLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788914441FD6D6FC00FCFA4B /* MICollectionViewBubbleLayout.swift */; };
19 | 788914471FD6D71700FCFA4B /* MIBubbleCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788914461FD6D71700FCFA4B /* MIBubbleCollectionViewCell.swift */; };
20 | B80879D029C9767000F1D89E /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80879CF29C9767000F1D89E /* HeaderView.swift */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXFileReference section */
24 | 637EFAD72863444700364FEE /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; };
25 | 637EFADA286344AA00364FEE /* ItemResources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemResources.swift; sourceTree = ""; };
26 | 637EFADC286344E500364FEE /* RoundImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundImageView.swift; sourceTree = ""; };
27 | 781F56651FD6A2AB002E226A /* SwiftDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
28 | 781F56681FD6A2AB002E226A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
29 | 781F566F1FD6A2AB002E226A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
30 | 781F56721FD6A2AB002E226A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
31 | 781F56741FD6A2AB002E226A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
32 | 7839D8AC1FD7CA5100B5E49F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
33 | 788914421FD6D6C500FCFA4B /* MIMainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MIMainViewController.swift; sourceTree = ""; };
34 | 788914441FD6D6FC00FCFA4B /* MICollectionViewBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MICollectionViewBubbleLayout.swift; sourceTree = ""; };
35 | 788914461FD6D71700FCFA4B /* MIBubbleCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MIBubbleCollectionViewCell.swift; sourceTree = ""; };
36 | B80879CF29C9767000F1D89E /* HeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; };
37 | /* End PBXFileReference section */
38 |
39 | /* Begin PBXFrameworksBuildPhase section */
40 | 781F56621FD6A2AB002E226A /* Frameworks */ = {
41 | isa = PBXFrameworksBuildPhase;
42 | buildActionMask = 2147483647;
43 | files = (
44 | );
45 | runOnlyForDeploymentPostprocessing = 0;
46 | };
47 | /* End PBXFrameworksBuildPhase section */
48 |
49 | /* Begin PBXGroup section */
50 | 637EFAD62863443D00364FEE /* Model */ = {
51 | isa = PBXGroup;
52 | children = (
53 | 637EFAD72863444700364FEE /* Item.swift */,
54 | );
55 | path = Model;
56 | sourceTree = "";
57 | };
58 | 637EFAD92863449300364FEE /* Resources */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 781F566F1FD6A2AB002E226A /* Assets.xcassets */,
62 | 637EFADA286344AA00364FEE /* ItemResources.swift */,
63 | );
64 | path = Resources;
65 | sourceTree = "";
66 | };
67 | 781F565C1FD6A2AB002E226A = {
68 | isa = PBXGroup;
69 | children = (
70 | 781F56671FD6A2AB002E226A /* SwiftDemo */,
71 | 781F56661FD6A2AB002E226A /* Products */,
72 | );
73 | sourceTree = "";
74 | };
75 | 781F56661FD6A2AB002E226A /* Products */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 781F56651FD6A2AB002E226A /* SwiftDemo.app */,
79 | );
80 | name = Products;
81 | sourceTree = "";
82 | };
83 | 781F56671FD6A2AB002E226A /* SwiftDemo */ = {
84 | isa = PBXGroup;
85 | children = (
86 | 637EFAD92863449300364FEE /* Resources */,
87 | 637EFAD62863443D00364FEE /* Model */,
88 | 781F56681FD6A2AB002E226A /* AppDelegate.swift */,
89 | 781F56741FD6A2AB002E226A /* Info.plist */,
90 | 781F56711FD6A2AB002E226A /* LaunchScreen.storyboard */,
91 | 7839D8AB1FD7CA5100B5E49F /* Main.storyboard */,
92 | 788914411FD6D69600FCFA4B /* Class */,
93 | );
94 | path = SwiftDemo;
95 | sourceTree = "";
96 | };
97 | 788914411FD6D69600FCFA4B /* Class */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 788914421FD6D6C500FCFA4B /* MIMainViewController.swift */,
101 | 788914461FD6D71700FCFA4B /* MIBubbleCollectionViewCell.swift */,
102 | 788914441FD6D6FC00FCFA4B /* MICollectionViewBubbleLayout.swift */,
103 | 637EFADC286344E500364FEE /* RoundImageView.swift */,
104 | B80879CF29C9767000F1D89E /* HeaderView.swift */,
105 | );
106 | path = Class;
107 | sourceTree = "";
108 | };
109 | /* End PBXGroup section */
110 |
111 | /* Begin PBXNativeTarget section */
112 | 781F56641FD6A2AB002E226A /* SwiftDemo */ = {
113 | isa = PBXNativeTarget;
114 | buildConfigurationList = 781F56771FD6A2AB002E226A /* Build configuration list for PBXNativeTarget "SwiftDemo" */;
115 | buildPhases = (
116 | 781F56611FD6A2AB002E226A /* Sources */,
117 | 781F56621FD6A2AB002E226A /* Frameworks */,
118 | 781F56631FD6A2AB002E226A /* Resources */,
119 | );
120 | buildRules = (
121 | );
122 | dependencies = (
123 | );
124 | name = SwiftDemo;
125 | productName = SwiftDemo;
126 | productReference = 781F56651FD6A2AB002E226A /* SwiftDemo.app */;
127 | productType = "com.apple.product-type.application";
128 | };
129 | /* End PBXNativeTarget section */
130 |
131 | /* Begin PBXProject section */
132 | 781F565D1FD6A2AB002E226A /* Project object */ = {
133 | isa = PBXProject;
134 | attributes = {
135 | LastSwiftUpdateCheck = 0910;
136 | LastUpgradeCheck = 1240;
137 | ORGANIZATIONNAME = "Jignesh-0007";
138 | TargetAttributes = {
139 | 781F56641FD6A2AB002E226A = {
140 | CreatedOnToolsVersion = 9.1;
141 | LastSwiftMigration = 1240;
142 | ProvisioningStyle = Manual;
143 | };
144 | };
145 | };
146 | buildConfigurationList = 781F56601FD6A2AB002E226A /* Build configuration list for PBXProject "SwiftDemo" */;
147 | compatibilityVersion = "Xcode 8.0";
148 | developmentRegion = en;
149 | hasScannedForEncodings = 0;
150 | knownRegions = (
151 | en,
152 | Base,
153 | );
154 | mainGroup = 781F565C1FD6A2AB002E226A;
155 | productRefGroup = 781F56661FD6A2AB002E226A /* Products */;
156 | projectDirPath = "";
157 | projectRoot = "";
158 | targets = (
159 | 781F56641FD6A2AB002E226A /* SwiftDemo */,
160 | );
161 | };
162 | /* End PBXProject section */
163 |
164 | /* Begin PBXResourcesBuildPhase section */
165 | 781F56631FD6A2AB002E226A /* Resources */ = {
166 | isa = PBXResourcesBuildPhase;
167 | buildActionMask = 2147483647;
168 | files = (
169 | 7839D8AD1FD7CA5100B5E49F /* Main.storyboard in Resources */,
170 | 781F56731FD6A2AB002E226A /* LaunchScreen.storyboard in Resources */,
171 | 781F56701FD6A2AB002E226A /* Assets.xcassets in Resources */,
172 | );
173 | runOnlyForDeploymentPostprocessing = 0;
174 | };
175 | /* End PBXResourcesBuildPhase section */
176 |
177 | /* Begin PBXSourcesBuildPhase section */
178 | 781F56611FD6A2AB002E226A /* Sources */ = {
179 | isa = PBXSourcesBuildPhase;
180 | buildActionMask = 2147483647;
181 | files = (
182 | 637EFAD82863444700364FEE /* Item.swift in Sources */,
183 | 788914471FD6D71700FCFA4B /* MIBubbleCollectionViewCell.swift in Sources */,
184 | 637EFADD286344E500364FEE /* RoundImageView.swift in Sources */,
185 | 788914451FD6D6FC00FCFA4B /* MICollectionViewBubbleLayout.swift in Sources */,
186 | 781F56691FD6A2AB002E226A /* AppDelegate.swift in Sources */,
187 | 637EFADB286344AA00364FEE /* ItemResources.swift in Sources */,
188 | 788914431FD6D6C500FCFA4B /* MIMainViewController.swift in Sources */,
189 | B80879D029C9767000F1D89E /* HeaderView.swift in Sources */,
190 | );
191 | runOnlyForDeploymentPostprocessing = 0;
192 | };
193 | /* End PBXSourcesBuildPhase section */
194 |
195 | /* Begin PBXVariantGroup section */
196 | 781F56711FD6A2AB002E226A /* LaunchScreen.storyboard */ = {
197 | isa = PBXVariantGroup;
198 | children = (
199 | 781F56721FD6A2AB002E226A /* Base */,
200 | );
201 | name = LaunchScreen.storyboard;
202 | sourceTree = "";
203 | };
204 | 7839D8AB1FD7CA5100B5E49F /* Main.storyboard */ = {
205 | isa = PBXVariantGroup;
206 | children = (
207 | 7839D8AC1FD7CA5100B5E49F /* Base */,
208 | );
209 | name = Main.storyboard;
210 | sourceTree = "";
211 | };
212 | /* End PBXVariantGroup section */
213 |
214 | /* Begin XCBuildConfiguration section */
215 | 781F56751FD6A2AB002E226A /* Debug */ = {
216 | isa = XCBuildConfiguration;
217 | buildSettings = {
218 | ALWAYS_SEARCH_USER_PATHS = NO;
219 | CLANG_ANALYZER_NONNULL = YES;
220 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
221 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
222 | CLANG_CXX_LIBRARY = "libc++";
223 | CLANG_ENABLE_MODULES = YES;
224 | CLANG_ENABLE_OBJC_ARC = YES;
225 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
226 | CLANG_WARN_BOOL_CONVERSION = YES;
227 | CLANG_WARN_COMMA = YES;
228 | CLANG_WARN_CONSTANT_CONVERSION = YES;
229 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
230 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
231 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
232 | CLANG_WARN_EMPTY_BODY = YES;
233 | CLANG_WARN_ENUM_CONVERSION = YES;
234 | CLANG_WARN_INFINITE_RECURSION = YES;
235 | CLANG_WARN_INT_CONVERSION = YES;
236 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
237 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
238 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
239 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
240 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
241 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
242 | CLANG_WARN_STRICT_PROTOTYPES = YES;
243 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
244 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
245 | CLANG_WARN_UNREACHABLE_CODE = YES;
246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
247 | CODE_SIGN_IDENTITY = "iPhone Developer";
248 | COPY_PHASE_STRIP = NO;
249 | DEBUG_INFORMATION_FORMAT = dwarf;
250 | ENABLE_STRICT_OBJC_MSGSEND = YES;
251 | ENABLE_TESTABILITY = YES;
252 | GCC_C_LANGUAGE_STANDARD = gnu11;
253 | GCC_DYNAMIC_NO_PIC = NO;
254 | GCC_NO_COMMON_BLOCKS = YES;
255 | GCC_OPTIMIZATION_LEVEL = 0;
256 | GCC_PREPROCESSOR_DEFINITIONS = (
257 | "DEBUG=1",
258 | "$(inherited)",
259 | );
260 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
261 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
262 | GCC_WARN_UNDECLARED_SELECTOR = YES;
263 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
264 | GCC_WARN_UNUSED_FUNCTION = YES;
265 | GCC_WARN_UNUSED_VARIABLE = YES;
266 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
267 | MTL_ENABLE_DEBUG_INFO = YES;
268 | ONLY_ACTIVE_ARCH = YES;
269 | SDKROOT = iphoneos;
270 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
271 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
272 | };
273 | name = Debug;
274 | };
275 | 781F56761FD6A2AB002E226A /* Release */ = {
276 | isa = XCBuildConfiguration;
277 | buildSettings = {
278 | ALWAYS_SEARCH_USER_PATHS = NO;
279 | CLANG_ANALYZER_NONNULL = YES;
280 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
281 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
282 | CLANG_CXX_LIBRARY = "libc++";
283 | CLANG_ENABLE_MODULES = YES;
284 | CLANG_ENABLE_OBJC_ARC = YES;
285 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
286 | CLANG_WARN_BOOL_CONVERSION = YES;
287 | CLANG_WARN_COMMA = YES;
288 | CLANG_WARN_CONSTANT_CONVERSION = YES;
289 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
291 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
292 | CLANG_WARN_EMPTY_BODY = YES;
293 | CLANG_WARN_ENUM_CONVERSION = YES;
294 | CLANG_WARN_INFINITE_RECURSION = YES;
295 | CLANG_WARN_INT_CONVERSION = YES;
296 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
297 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
298 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
300 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
301 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
302 | CLANG_WARN_STRICT_PROTOTYPES = YES;
303 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
304 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
305 | CLANG_WARN_UNREACHABLE_CODE = YES;
306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
307 | CODE_SIGN_IDENTITY = "iPhone Developer";
308 | COPY_PHASE_STRIP = NO;
309 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
310 | ENABLE_NS_ASSERTIONS = NO;
311 | ENABLE_STRICT_OBJC_MSGSEND = YES;
312 | GCC_C_LANGUAGE_STANDARD = gnu11;
313 | GCC_NO_COMMON_BLOCKS = YES;
314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
316 | GCC_WARN_UNDECLARED_SELECTOR = YES;
317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
318 | GCC_WARN_UNUSED_FUNCTION = YES;
319 | GCC_WARN_UNUSED_VARIABLE = YES;
320 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
321 | MTL_ENABLE_DEBUG_INFO = NO;
322 | SDKROOT = iphoneos;
323 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
324 | VALIDATE_PRODUCT = YES;
325 | };
326 | name = Release;
327 | };
328 | 781F56781FD6A2AB002E226A /* Debug */ = {
329 | isa = XCBuildConfiguration;
330 | buildSettings = {
331 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
332 | CODE_SIGN_STYLE = Manual;
333 | DEVELOPMENT_TEAM = "";
334 | INFOPLIST_FILE = SwiftDemo/Info.plist;
335 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
336 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
337 | PRODUCT_BUNDLE_IDENTIFIER = com.mi.SwiftDemo;
338 | PRODUCT_NAME = "$(TARGET_NAME)";
339 | PROVISIONING_PROFILE_SPECIFIER = "";
340 | SWIFT_VERSION = 5.0;
341 | TARGETED_DEVICE_FAMILY = "1,2";
342 | };
343 | name = Debug;
344 | };
345 | 781F56791FD6A2AB002E226A /* Release */ = {
346 | isa = XCBuildConfiguration;
347 | buildSettings = {
348 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
349 | CODE_SIGN_STYLE = Manual;
350 | DEVELOPMENT_TEAM = "";
351 | INFOPLIST_FILE = SwiftDemo/Info.plist;
352 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
353 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
354 | PRODUCT_BUNDLE_IDENTIFIER = com.mi.SwiftDemo;
355 | PRODUCT_NAME = "$(TARGET_NAME)";
356 | PROVISIONING_PROFILE_SPECIFIER = "";
357 | SWIFT_VERSION = 5.0;
358 | TARGETED_DEVICE_FAMILY = "1,2";
359 | };
360 | name = Release;
361 | };
362 | /* End XCBuildConfiguration section */
363 |
364 | /* Begin XCConfigurationList section */
365 | 781F56601FD6A2AB002E226A /* Build configuration list for PBXProject "SwiftDemo" */ = {
366 | isa = XCConfigurationList;
367 | buildConfigurations = (
368 | 781F56751FD6A2AB002E226A /* Debug */,
369 | 781F56761FD6A2AB002E226A /* Release */,
370 | );
371 | defaultConfigurationIsVisible = 0;
372 | defaultConfigurationName = Release;
373 | };
374 | 781F56771FD6A2AB002E226A /* Build configuration list for PBXNativeTarget "SwiftDemo" */ = {
375 | isa = XCConfigurationList;
376 | buildConfigurations = (
377 | 781F56781FD6A2AB002E226A /* Debug */,
378 | 781F56791FD6A2AB002E226A /* Release */,
379 | );
380 | defaultConfigurationIsVisible = 0;
381 | defaultConfigurationName = Release;
382 | };
383 | /* End XCConfigurationList section */
384 | };
385 | rootObject = 781F565D1FD6A2AB002E226A /* Project object */;
386 | }
387 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcuserdata/mind-0023.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcuserdata/mind-0023.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcuserdata/mind.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/xcuserdata/mind.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/xcuserdata/mac-0007.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SwiftDemo.xcscheme
8 |
9 | orderHint
10 | 1
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 781F56641FD6A2AB002E226A
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/xcuserdata/mind-0023.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SwiftDemo.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 1
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo.xcodeproj/xcuserdata/mind.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SwiftDemo.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | HelveticaNeue-Bold
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/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 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
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 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Class/HeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HeaderView.swift
3 | // SwiftDemo
4 | //
5 | // Created by MI-161 on 14/03/23.
6 | // Copyright © 2023 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class HeaderView: UICollectionReusableView {
12 |
13 | @IBOutlet weak var lblTitleText: UILabel!
14 |
15 | override func awakeFromNib() {
16 | super.awakeFromNib()
17 | // Initialization code
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Class/MIBubbleCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIBubbleCollectionViewCell.swift
3 | // SwiftDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class MIBubbleCollectionViewCell: UICollectionViewCell {
12 |
13 | @IBOutlet var lblTitle:UILabel!
14 | @IBOutlet weak var itemImageView: RoundImageView!
15 | @IBOutlet weak var closeButton: UIButton!
16 |
17 | weak var delegate: ItemAction?
18 | var item: Item?
19 |
20 | override func awakeFromNib() {
21 | super.awakeFromNib()
22 | self.layer.borderWidth = 1
23 | }
24 |
25 | override func layoutSubviews() {
26 | super.layoutSubviews()
27 | self.layer.cornerRadius = self.frame.size.height / 2
28 | }
29 |
30 | func configure(with item: Item) {
31 |
32 | self.item = item
33 | lblTitle.text = item.name
34 | lblTitle.textColor = item.isSelected ? .white : .black
35 | itemImageView.image = item.image
36 | layer.borderColor = item.color.cgColor
37 | backgroundColor = item.color.withAlphaComponent(item.isSelected ? 1: 0.2)
38 | closeButton.tintColor = item.isSelected ? .white : item.color
39 | }
40 | }
41 |
42 | extension MIBubbleCollectionViewCell {
43 |
44 | @IBAction func onCloseButtonTapped(_ sender: UIButton) {
45 | delegate?.onCloseButtonTapped(with: item, sender: sender)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Class/MICollectionViewBubbleLayout.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MICollectionViewBubbleLayout.swift
3 | // SwiftDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol MICollectionViewBubbleLayoutDelegate {
12 | func collectionView(_ collectionView:UICollectionView, itemSizeAt indexPath:NSIndexPath) -> CGSize
13 | }
14 |
15 | protocol Alignment {}
16 |
17 | /// Defines a horizontal alignment for UI elements.
18 | public enum HorizontalAlignment: Alignment {
19 | case left
20 | case right
21 | case leading
22 | case trailing
23 | case justified
24 | }
25 |
26 | /// Defines a vertical alignment for UI elements.
27 | public enum VerticalAlignment: Alignment {
28 | case top
29 | case center
30 | case bottom
31 | }
32 |
33 | /// A horizontal alignment used internally by `AlignedCollectionViewFlowLayout`
34 | /// to layout the items, after resolving layout direction specifics.
35 | private enum EffectiveHorizontalAlignment: Alignment {
36 | case left
37 | case right
38 | case justified
39 | }
40 |
41 | /// Describes an axis with respect to which items can be aligned.
42 | private struct AlignmentAxis {
43 |
44 | /// Determines how items are aligned relative to the axis.
45 | let alignment: A
46 |
47 | /// Defines the position of the axis.
48 | /// * If the `Alignment` is horizontal, the alignment axis is vertical and this is the position on the `x` axis.
49 | /// * If the `Alignment` is vertical, the alignment axis is horizontal and this is the position on the `y` axis.
50 | let position: CGFloat
51 | }
52 |
53 |
54 |
55 | // MARK: - Flow Layout
56 |
57 | /// A `UICollectionViewFlowLayout` subclass that gives you control
58 | /// over the horizontal and vertical alignment of the cells.
59 | /// You can use it to align the cells like words in a left- or right-aligned text
60 | /// and you can specify how the cells are vertically aligned in their row.
61 | open class MICollectionViewBubbleLayout: UICollectionViewFlowLayout {
62 |
63 |
64 | // MARK: - 🔶 Properties
65 |
66 | /// Determines how the cells are horizontally aligned in a row.
67 | /// - Note: The default is `.justified`.
68 | public var horizontalAlignment: HorizontalAlignment = .justified
69 |
70 | /// Determines how the cells are vertically aligned in a row.
71 | /// - Note: The default is `.center`.
72 | public var verticalAlignment: VerticalAlignment = .center
73 |
74 | /// The `horizontalAlignment` with its layout direction specifics resolved,
75 | /// i.e. `.leading` and `.trailing` alignments are mapped to `.left` or `right`,
76 | /// depending on the current layout direction.
77 | fileprivate var effectiveHorizontalAlignment: EffectiveHorizontalAlignment {
78 |
79 | var trivialMapping: [HorizontalAlignment: EffectiveHorizontalAlignment] {
80 | return [
81 | .left: .left,
82 | .right: .right,
83 | .justified: .justified
84 | ]
85 | }
86 |
87 | let layoutDirection = UIApplication.shared.userInterfaceLayoutDirection
88 |
89 | switch layoutDirection {
90 | case .leftToRight:
91 | switch horizontalAlignment {
92 | case .leading:
93 | return .left
94 | case .trailing:
95 | return .right
96 | default:
97 | break
98 | }
99 |
100 | case .rightToLeft:
101 | switch horizontalAlignment {
102 | case .leading:
103 | return .right
104 | case .trailing:
105 | return .left
106 | default:
107 | break
108 | }
109 | @unknown default:
110 | fatalError("not set rightToLeft")
111 | }
112 |
113 | // It's safe to force-unwrap as `.leading` and `.trailing` are covered
114 | // above and the `trivialMapping` dictionary contains all other keys.
115 | return trivialMapping[horizontalAlignment]!
116 | }
117 |
118 | /// The vertical axis with respect to which the cells are horizontally aligned.
119 | /// For a `justified` alignment the alignment axis is not defined and this value is `nil`.
120 | fileprivate var alignmentAxis: AlignmentAxis? {
121 | switch effectiveHorizontalAlignment {
122 | case .left:
123 | return AlignmentAxis(alignment: HorizontalAlignment.left, position: sectionInset.left)
124 | case .right:
125 | guard let collectionViewWidth = collectionView?.frame.size.width else {
126 | return nil
127 | }
128 | return AlignmentAxis(alignment: HorizontalAlignment.right, position: collectionViewWidth - sectionInset.right)
129 | default:
130 | return nil
131 | }
132 | }
133 |
134 | /// The width of the area inside the collection view that can be filled with cells.
135 | private var contentWidth: CGFloat? {
136 | guard let collectionViewWidth = collectionView?.frame.size.width else {
137 | return nil
138 | }
139 | return collectionViewWidth - sectionInset.left - sectionInset.right
140 | }
141 |
142 |
143 | // MARK: - 👶 Initialization
144 |
145 | /// The designated initializer.
146 | ///
147 | /// - Parameters:
148 | /// - horizontalAlignment: Specifies how the cells are horizontally aligned in a row. --
149 | /// (Default: `.justified`)
150 | /// - verticalAlignment: Specified how the cells are vertically aligned in a row. --
151 | /// (Default: `.center`)
152 | public init(horizontalAlignment: HorizontalAlignment = .justified, verticalAlignment: VerticalAlignment = .center) {
153 | super.init()
154 | self.horizontalAlignment = horizontalAlignment
155 | self.verticalAlignment = verticalAlignment
156 | }
157 |
158 | required public init?(coder aDecoder: NSCoder) {
159 | super.init(coder: aDecoder)
160 | }
161 |
162 | // MARK: - 🅾️ Overrides
163 |
164 | override open func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
165 |
166 | // 💡 IDEA:
167 | // The approach for computing a cell's frame is to create a rectangle that covers the current line.
168 | // Then we check if the preceding cell's frame intersects with this rectangle.
169 | // If it does, the current item is not the first item in the line. Otherwise it is.
170 | // (Vice-versa for right-aligned cells.)
171 | //
172 | // +---------+----------------------------------------------------------------+---------+
173 | // | | | |
174 | // | | +------------+ | |
175 | // | | | | | |
176 | // | section |- - -|- - - - - - |- - - - +---------------------+ - - - - - - -| section |
177 | // | inset | |intersection| | | line rect | inset |
178 | // | |- - -|- - - - - - |- - - - +---------------------+ - - - - - - -| |
179 | // | (left) | | | current item | (right) |
180 | // | | +------------+ | |
181 | // | | previous item | |
182 | // +---------+----------------------------------------------------------------+---------+
183 | //
184 | // ℹ️ We need this rather complicated approach because the first item in a line
185 | // is not always left-aligned and the last item in a line is not always right-aligned:
186 | // If there is only one item in a line UICollectionViewFlowLayout will center it.
187 |
188 | // We may not change the original layout attributes or UICollectionViewFlowLayout might complain.
189 | guard let layoutAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes else {
190 | return nil
191 | }
192 |
193 | // For a justified layout there's nothing to do here
194 | // as UICollectionViewFlowLayout justifies the items in a line by default.
195 | if horizontalAlignment != .justified {
196 | layoutAttributes.alignHorizontally(collectionViewLayout: self)
197 | }
198 |
199 | // For a vertically centered layout there's nothing to do here
200 | // as UICollectionViewFlowLayout center-aligns the items in a line by default.
201 | if verticalAlignment != .center {
202 | layoutAttributes.alignVertically(collectionViewLayout: self)
203 | }
204 |
205 | return layoutAttributes
206 | }
207 |
208 | override open func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
209 | // We may not change the original layout attributes or UICollectionViewFlowLayout might complain.
210 | let layoutAttributesObjects = copy(super.layoutAttributesForElements(in: rect))
211 | layoutAttributesObjects?.forEach({ (layoutAttributes) in
212 | setFrame(forLayoutAttributes: layoutAttributes)
213 | })
214 | return layoutAttributesObjects
215 | }
216 |
217 |
218 | // MARK: - 👷 Private layout helpers
219 |
220 | /// Sets the frame for the passed layout attributes object by calling the `layoutAttributesForItem(at:)` function.
221 | private func setFrame(forLayoutAttributes layoutAttributes: UICollectionViewLayoutAttributes) {
222 | if layoutAttributes.representedElementCategory == .cell { // Do not modify header views etc.
223 | let indexPath = layoutAttributes.indexPath
224 | if let newFrame = layoutAttributesForItem(at: indexPath)?.frame {
225 | layoutAttributes.frame = newFrame
226 | }
227 | }
228 | }
229 |
230 | /// A function to access the `super` implementation of `layoutAttributesForItem(at:)` externally.
231 | ///
232 | /// - Parameter indexPath: The index path of the item for which to return the layout attributes.
233 | /// - Returns: The unmodified layout attributes for the item at the specified index path
234 | /// as computed by `UICollectionViewFlowLayout`.
235 | fileprivate func originalLayoutAttribute(forItemAt indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
236 | return super.layoutAttributesForItem(at: indexPath)
237 | }
238 |
239 | /// Determines if the `firstItemAttributes`' frame is in the same line
240 | /// as the `secondItemAttributes`' frame.
241 | ///
242 | /// - Parameters:
243 | /// - firstItemAttributes: The first layout attributes object to be compared.
244 | /// - secondItemAttributes: The second layout attributes object to be compared.
245 | /// - Returns: `true` if the frames of the two layout attributes are in the same line, else `false`.
246 | /// `false` is also returned when the layout's `collectionView` property is `nil`.
247 | fileprivate func isFrame(for firstItemAttributes: UICollectionViewLayoutAttributes, inSameLineAsFrameFor secondItemAttributes: UICollectionViewLayoutAttributes) -> Bool {
248 | guard let lineWidth = contentWidth else {
249 | return false
250 | }
251 | let firstItemFrame = firstItemAttributes.frame
252 | let lineFrame = CGRect(x: sectionInset.left,
253 | y: firstItemFrame.origin.y,
254 | width: lineWidth,
255 | height: firstItemFrame.size.height)
256 | return lineFrame.intersects(secondItemAttributes.frame)
257 | }
258 |
259 | /// Determines the layout attributes objects for all items displayed in the same line as the item
260 | /// represented by the passed `layoutAttributes` object.
261 | ///
262 | /// - Parameter layoutAttributes: The layout attributed that represents the reference item.
263 | /// - Returns: The layout attributes objects representing all other items in the same line.
264 | /// The passed `layoutAttributes` object itself is always contained in the returned array.
265 | fileprivate func layoutAttributes(forItemsInLineWith layoutAttributes: UICollectionViewLayoutAttributes) -> [UICollectionViewLayoutAttributes] {
266 | guard let lineWidth = contentWidth else {
267 | return [layoutAttributes]
268 | }
269 | var lineFrame = layoutAttributes.frame
270 | lineFrame.origin.x = sectionInset.left
271 | lineFrame.size.width = lineWidth
272 | return super.layoutAttributesForElements(in: lineFrame) ?? []
273 | }
274 |
275 | /// Copmutes the alignment axis with which to align the items represented by the `layoutAttributes` objects vertically.
276 | ///
277 | /// - Parameter layoutAttributes: The layout attributes objects to be vertically aligned.
278 | /// - Returns: The axis with respect to which the layout attributes can be aligned
279 | /// or `nil` if the `layoutAttributes` array is empty.
280 | private func verticalAlignmentAxisForLine(with layoutAttributes: [UICollectionViewLayoutAttributes]) -> AlignmentAxis? {
281 |
282 | guard let firstAttribute = layoutAttributes.first else {
283 | return nil
284 | }
285 |
286 | switch verticalAlignment {
287 | case .top:
288 | let minY = layoutAttributes.reduce(CGFloat.greatestFiniteMagnitude) { min($0, $1.frame.minY) }
289 | return AlignmentAxis(alignment: .top, position: minY)
290 |
291 | case .bottom:
292 | let maxY = layoutAttributes.reduce(0) { max($0, $1.frame.maxY) }
293 | return AlignmentAxis(alignment: .bottom, position: maxY)
294 |
295 | default:
296 | let centerY = firstAttribute.center.y
297 | return AlignmentAxis(alignment: .center, position: centerY)
298 | }
299 | }
300 |
301 | /// Computes the axis with which to align the item represented by the `currentLayoutAttributes` vertically.
302 | ///
303 | /// - Parameter currentLayoutAttributes: The layout attributes representing the item to be vertically aligned.
304 | /// - Returns: The axis with respect to which the item can be aligned.
305 | fileprivate func verticalAlignmentAxis(for currentLayoutAttributes: UICollectionViewLayoutAttributes) -> AlignmentAxis {
306 | let layoutAttributesInLine = layoutAttributes(forItemsInLineWith: currentLayoutAttributes)
307 | // It's okay to force-unwrap here because we pass a non-empty array.
308 | return verticalAlignmentAxisForLine(with: layoutAttributesInLine)!
309 | }
310 |
311 | /// Creates a deep copy of the passed array by copying all its items.
312 | ///
313 | /// - Parameter layoutAttributesArray: The array to be copied.
314 | /// - Returns: A deep copy of the passed array.
315 | private func copy(_ layoutAttributesArray: [UICollectionViewLayoutAttributes]?) -> [UICollectionViewLayoutAttributes]? {
316 | return layoutAttributesArray?.map{ $0.copy() } as? [UICollectionViewLayoutAttributes]
317 | }
318 |
319 | }
320 |
321 |
322 |
323 | // MARK: - 👷 Layout attributes helpers
324 |
325 | fileprivate extension UICollectionViewLayoutAttributes {
326 |
327 | private var currentSection: Int {
328 | return indexPath.section
329 | }
330 |
331 | private var currentItem: Int {
332 | return indexPath.item
333 | }
334 |
335 | /// The index path for the item preceding the item represented by this layout attributes object.
336 | private var precedingIndexPath: IndexPath {
337 | return IndexPath(item: currentItem - 1, section: currentSection)
338 | }
339 |
340 | /// The index path for the item following the item represented by this layout attributes object.
341 | private var followingIndexPath: IndexPath {
342 | return IndexPath(item: currentItem + 1, section: currentSection)
343 | }
344 |
345 | /// Checks if the item represetend by this layout attributes object is the first item in the line.
346 | ///
347 | /// - Parameter collectionViewLayout: The layout for which to perform the check.
348 | /// - Returns: `true` if the represented item is the first item in the line, else `false`.
349 | func isRepresentingFirstItemInLine(collectionViewLayout: MICollectionViewBubbleLayout) -> Bool {
350 | if currentItem <= 0 {
351 | return true
352 | }
353 | else {
354 | if let layoutAttributesForPrecedingItem = collectionViewLayout.originalLayoutAttribute(forItemAt: precedingIndexPath) {
355 | return !collectionViewLayout.isFrame(for: self, inSameLineAsFrameFor: layoutAttributesForPrecedingItem)
356 | }
357 | else {
358 | return true
359 | }
360 | }
361 | }
362 |
363 | /// Checks if the item represetend by this layout attributes object is the last item in the line.
364 | ///
365 | /// - Parameter collectionViewLayout: The layout for which to perform the check.
366 | /// - Returns: `true` if the represented item is the last item in the line, else `false`.
367 | func isRepresentingLastItemInLine(collectionViewLayout: MICollectionViewBubbleLayout) -> Bool {
368 | guard let itemCount = collectionViewLayout.collectionView?.numberOfItems(inSection: currentSection) else {
369 | return false
370 | }
371 |
372 | if currentItem >= itemCount - 1 {
373 | return true
374 | }
375 | else {
376 | if let layoutAttributesForFollowingItem = collectionViewLayout.originalLayoutAttribute(forItemAt: followingIndexPath) {
377 | return !collectionViewLayout.isFrame(for: self, inSameLineAsFrameFor: layoutAttributesForFollowingItem)
378 | }
379 | else {
380 | return true
381 | }
382 | }
383 | }
384 |
385 | /// Moves the layout attributes object's frame so that it is aligned horizontally with the alignment axis.
386 | func align(toAlignmentAxis alignmentAxis: AlignmentAxis) {
387 | switch alignmentAxis.alignment {
388 | case .left:
389 | frame.origin.x = alignmentAxis.position
390 | case .right:
391 | frame.origin.x = alignmentAxis.position - frame.size.width
392 | default:
393 | break
394 | }
395 | }
396 |
397 | /// Moves the layout attributes object's frame so that it is aligned vertically with the alignment axis.
398 | func align(toAlignmentAxis alignmentAxis: AlignmentAxis) {
399 | switch alignmentAxis.alignment {
400 | case .top:
401 | frame.origin.y = alignmentAxis.position
402 | case .bottom:
403 | frame.origin.y = alignmentAxis.position - frame.size.height
404 | default:
405 | center.y = alignmentAxis.position
406 | }
407 | }
408 |
409 | /// Positions the frame right of the preceding item's frame, leaving a spacing between the frames
410 | /// as defined by the collection view layout's `minimumInteritemSpacing`.
411 | ///
412 | /// - Parameter collectionViewLayout: The layout on which to perfom the calculations.
413 | private func alignToPrecedingItem(collectionViewLayout: MICollectionViewBubbleLayout) {
414 | let itemSpacing = collectionViewLayout.minimumInteritemSpacing
415 |
416 | if let precedingItemAttributes = collectionViewLayout.layoutAttributesForItem(at: precedingIndexPath) {
417 | frame.origin.x = precedingItemAttributes.frame.maxX + itemSpacing
418 | }
419 | }
420 |
421 | /// Positions the frame left of the following item's frame, leaving a spacing between the frames
422 | /// as defined by the collection view layout's `minimumInteritemSpacing`.
423 | ///
424 | /// - Parameter collectionViewLayout: The layout on which to perfom the calculations.
425 | private func alignToFollowingItem(collectionViewLayout: MICollectionViewBubbleLayout) {
426 | let itemSpacing = collectionViewLayout.minimumInteritemSpacing
427 |
428 | if let followingItemAttributes = collectionViewLayout.layoutAttributesForItem(at: followingIndexPath) {
429 | frame.origin.x = followingItemAttributes.frame.minX - itemSpacing - frame.size.width
430 | }
431 | }
432 |
433 | /// Aligns the frame horizontally as specified by the collection view layout's `horizontalAlignment`.
434 | ///
435 | /// - Parameters:
436 | /// - collectionViewLayout: The layout providing the alignment information.
437 | func alignHorizontally(collectionViewLayout: MICollectionViewBubbleLayout) {
438 |
439 | guard let alignmentAxis = collectionViewLayout.alignmentAxis else {
440 | return
441 | }
442 |
443 | switch collectionViewLayout.effectiveHorizontalAlignment {
444 |
445 | case .left:
446 | if isRepresentingFirstItemInLine(collectionViewLayout: collectionViewLayout) {
447 | align(toAlignmentAxis: alignmentAxis)
448 | } else {
449 | alignToPrecedingItem(collectionViewLayout: collectionViewLayout)
450 | }
451 |
452 | case .right:
453 | if isRepresentingLastItemInLine(collectionViewLayout: collectionViewLayout) {
454 | align(toAlignmentAxis: alignmentAxis)
455 | } else {
456 | alignToFollowingItem(collectionViewLayout: collectionViewLayout)
457 | }
458 |
459 | default:
460 | return
461 | }
462 | }
463 |
464 | /// Aligns the frame vertically as specified by the collection view layout's `verticalAlignment`.
465 | ///
466 | /// - Parameter collectionViewLayout: The layout providing the alignment information.
467 | func alignVertically(collectionViewLayout: MICollectionViewBubbleLayout) {
468 | let alignmentAxis = collectionViewLayout.verticalAlignmentAxis(for: self)
469 | align(toAlignmentAxis: alignmentAxis)
470 | }
471 |
472 | }
473 |
474 | extension UICollectionView {
475 |
476 | func indexPathForView(view: AnyObject) -> IndexPath? {
477 | let originInCollectioView = self.convert(CGPoint.zero, from: (view as! UIView))
478 | return self.indexPathForItem(at: originInCollectioView) as IndexPath?
479 | }
480 | }
481 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Class/MIMainViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIMainViewController.swift
3 | // SwiftDemo
4 | //
5 | // Created by mac-0007 on 05/12/17.
6 | // Copyright © 2017 Jignesh-0007. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol ItemAction: AnyObject {
12 | func onCloseButtonTapped(with item: Item? ,sender: UIButton)
13 | }
14 |
15 | final class MIMainViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate,MICollectionViewBubbleLayoutDelegate {
16 |
17 | @IBOutlet private var collVData: UICollectionView!
18 | @IBOutlet private var buttonDone: UIButton!
19 | @IBOutlet private var buttonAddMoreData: UIButton!
20 | @IBOutlet private var viewAddMoreData: UIView!
21 | @IBOutlet private var textfiledEnterDetails: UITextField!
22 |
23 | private let kItemPadding = 10
24 | private var arrData: [DataCollection] = DataCollection.sectionItems {
25 | didSet {
26 | collVData.reloadData()
27 | }
28 | }
29 |
30 | override func viewDidLoad() {
31 | super.viewDidLoad()
32 |
33 | //...UICollectionView setup
34 |
35 | let bubbleLayout = MICollectionViewBubbleLayout()
36 | bubbleLayout.minimumLineSpacing = 6.0
37 | bubbleLayout.minimumInteritemSpacing = 0
38 | bubbleLayout.horizontalAlignment = .leading
39 | collVData.setCollectionViewLayout(bubbleLayout, animated: false)
40 | bubbleLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
41 |
42 | }
43 | // MARK: -
44 | // MARK: - IBACTION METHODS
45 | @IBAction func addmoreButtonTapped(_ sender: Any) {
46 | buttonAddMoreData.isHidden = true
47 | viewAddMoreData.isHidden = false
48 | }
49 | @IBAction func doneButtonTapped(_ sender: UIButton) {
50 |
51 | if(self.textfiledEnterDetails.text?.isEmpty == false){
52 | arrData[sender.tag].add(newItem: Item(id: UUID(), name: self.textfiledEnterDetails.text ?? "",image: ItemResource.chocolate.image,
53 | color: .orange,
54 | isSelected: false))
55 | }
56 | collVData.reloadData()
57 | self.textfiledEnterDetails.text = ""
58 | self.textfiledEnterDetails.resignFirstResponder()
59 | }
60 |
61 | // MARK: -
62 | // MARK: - UICollectionView Delegate & Datasource
63 | func numberOfSections(in collectionView: UICollectionView) -> Int {
64 | arrData.count
65 | }
66 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
67 | return arrData[section].item.count
68 | }
69 |
70 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
71 |
72 | let indentifier = "MIBubbleCollectionViewCell"
73 |
74 | if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: indentifier, for: indexPath) as? MIBubbleCollectionViewCell {
75 | cell.configure(with: arrData[indexPath.section].item[indexPath.row])
76 | cell.delegate = self
77 | return cell
78 | }
79 | return UICollectionViewCell()
80 | }
81 |
82 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
83 | arrData[indexPath.section].item[indexPath.row].isSelected.toggle()
84 | }
85 |
86 | // MARK: -
87 | // MARK: - MICollectionViewBubbleLayoutDelegate
88 |
89 | func collectionView(_ collectionView:UICollectionView, itemSizeAt indexPath:NSIndexPath) -> CGSize {
90 |
91 | let title = arrData[indexPath.section].item[indexPath.row].name
92 | var size = title.size(withAttributes: [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue-Bold", size: 15)!])
93 | let closeButtonWidth = 20.0
94 | let imageWidth = 20.0
95 | let spacing = 18.0
96 | let totalWidth = Float(size.width + closeButtonWidth + imageWidth + spacing + CGFloat(kItemPadding * 2))
97 | size.width = CGFloat(ceilf(totalWidth))
98 | size.height = 40
99 |
100 | //...Checking if item width is greater than collection view width then set item width == collection view width.
101 | if size.width > collectionView.frame.size.width {
102 | size.width = collectionView.frame.size.width
103 | }
104 | return size
105 | }
106 |
107 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
108 |
109 | switch kind {
110 |
111 | case UICollectionView.elementKindSectionHeader:
112 |
113 | let headerView = collVData.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "HeaderView", for: indexPath) as! HeaderView
114 | headerView.lblTitleText.text = arrData[indexPath.section].title
115 | headerView.lblTitleText.sizeToFit()
116 | return headerView
117 |
118 |
119 | default:
120 | return UICollectionReusableView()
121 |
122 | }
123 | }
124 | }
125 |
126 | extension MIMainViewController: ItemAction {
127 |
128 | func onCloseButtonTapped(with item: Item?,sender:UIButton) {
129 |
130 | guard item != nil else { return }
131 | guard let indexPath = self.collVData.indexPathForView(view: sender) else { return }
132 | arrData[(indexPath.section)].remove(newItem: item!)
133 | }
134 | }
135 | extension MIMainViewController: UICollectionViewDelegateFlowLayout {
136 |
137 | // MARK: - Collection View Delegate Flow Layout Methods
138 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
139 | return CGSize(width: collectionView.bounds.width, height: 44.0)
140 | }
141 |
142 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
143 | return UIEdgeInsets.zero
144 | }
145 |
146 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
147 | return 6.0
148 | }
149 |
150 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
151 | return 2.0
152 | }
153 |
154 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
155 | if arrData[section].item.count == 0 {
156 | return CGSize(width: collectionView.bounds.width, height: 0)
157 | } else {
158 | return CGSize(width: collectionView.bounds.width, height: 80.0)
159 | }
160 | }
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Class/RoundImageView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RoundImageView.swift
3 | // SwiftDemo
4 | //
5 | // Created by Parth Gohel on 22/06/22.
6 | // Copyright © 2022 Parth Gohel. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class RoundImageView: UIImageView {
12 |
13 | override func layoutSubviews() {
14 | super.layoutSubviews()
15 | layer.cornerRadius = frame.size.height/2
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Model/Item.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Item.swift
3 | // SwiftDemo
4 | //
5 | // Created by Parth Gohel on 22/06/22.
6 | // Copyright © 2022 Parth Gohel. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | struct DataCollection {
12 | let id: Int
13 | let title:String
14 | var item: [Item]
15 |
16 | mutating func add(newItem: Item) {
17 | item.append(newItem)
18 | }
19 | mutating func remove(newItem: Item) {
20 | item = item.filter({$0.id != newItem.id})
21 | }
22 | }
23 | struct Item {
24 | let id: UUID
25 | let name: String
26 | let image: UIImage
27 | let color: UIColor
28 | var isSelected: Bool
29 | }
30 |
31 | extension DataCollection {
32 | static var sectionItems: [Self] {
33 | return [
34 | DataCollection(id: 0, title: "Items name", item: [
35 | Item(id: UUID(),
36 | name: "None",
37 | image: ItemResource.chocolate.image,
38 | color: .orange,
39 | isSelected: false),
40 | Item(id: UUID(),
41 | name: "Glazed",
42 | image: ItemResource.chocolate.image,
43 | color: .orange,
44 | isSelected: false),
45 | Item(id: UUID(),
46 | name: "Sugar",
47 | image: ItemResource.chocolate.image,
48 | color: .orange,
49 | isSelected: false),
50 | Item(id: UUID(),
51 | name: "Powdered Sugar",
52 | image: ItemResource.chocolate.image,
53 | color: .orange,
54 | isSelected: false),
55 | Item(id: UUID(),
56 | name: "Chocolate with Sprinkles",
57 | image: ItemResource.chocolate.image,
58 | color: .orange,
59 | isSelected: false),
60 | Item(id: UUID(),
61 | name: "Chocolate",
62 | image: ItemResource.chocolate.image,
63 | color: .orange,
64 | isSelected: false),
65 | Item(id: UUID(),
66 | name: "Maple",
67 | image: ItemResource.chocolate.image,
68 | color: .orange,
69 | isSelected: false),
70 | Item(id: UUID(),
71 | name: "Regular",
72 | image: ItemResource.chocolate.image,
73 | color: .orange,
74 | isSelected: false),
75 | Item(id: UUID(),
76 | name: "Chocolate",
77 | image: ItemResource.chocolate.image,
78 | color: .orange,
79 | isSelected: false),
80 | Item(id: UUID(),
81 | name: "Blueberry",
82 | image: ItemResource.chocolate.image,
83 | color: .orange,
84 | isSelected: false),
85 | ]),
86 | DataCollection(id: 1, title: "Items name", item: [
87 | Item(id: UUID(),
88 | name: "Nothing",
89 | image: ItemResource.chocolate.image,
90 | color: .orange,
91 | isSelected: false),
92 | Item(id: UUID(),
93 | name: "Glazeded",
94 | image: ItemResource.chocolate.image,
95 | color: .orange,
96 | isSelected: false),
97 | Item(id: UUID(),
98 | name: "Sugars",
99 | image: ItemResource.chocolate.image,
100 | color: .orange,
101 | isSelected: false),
102 | Item(id: UUID(),
103 | name: "Powdered Sugars",
104 | image: ItemResource.chocolate.image,
105 | color: .orange,
106 | isSelected: false),
107 | Item(id: UUID(),
108 | name: "Chocolates with Sprinkles",
109 | image: ItemResource.chocolate.image,
110 | color: .orange,
111 | isSelected: false),
112 | Item(id: UUID(),
113 | name: "Chocolates",
114 | image: ItemResource.chocolate.image,
115 | color: .orange,
116 | isSelected: false),
117 | Item(id: UUID(),
118 | name: "Maples",
119 | image: ItemResource.chocolate.image,
120 | color: .orange,
121 | isSelected: false),
122 | Item(id: UUID(),
123 | name: "Regulars",
124 | image: ItemResource.chocolate.image,
125 | color: .orange,
126 | isSelected: false),
127 | Item(id: UUID(),
128 | name: "Chocolates",
129 | image: ItemResource.chocolate.image,
130 | color: .orange,
131 | isSelected: false),
132 | Item(id: UUID(),
133 | name: "Blueberrys",
134 | image: ItemResource.chocolate.image,
135 | color: .orange,
136 | isSelected: false),
137 | ]),
138 | DataCollection(id: 2, title: "Items name", item: [
139 | Item(id: UUID(),
140 | name: "Nothing",
141 | image: ItemResource.chocolate.image,
142 | color: .orange,
143 | isSelected: false),
144 | Item(id: UUID(),
145 | name: "Glazeded",
146 | image: ItemResource.chocolate.image,
147 | color: .orange,
148 | isSelected: false),
149 | Item(id: UUID(),
150 | name: "Sugars",
151 | image: ItemResource.chocolate.image,
152 | color: .orange,
153 | isSelected: false),
154 | Item(id: UUID(),
155 | name: "Powdered Sugars",
156 | image: ItemResource.chocolate.image,
157 | color: .orange,
158 | isSelected: false),
159 | Item(id: UUID(),
160 | name: "Chocolates with Sprinkles",
161 | image: ItemResource.chocolate.image,
162 | color: .orange,
163 | isSelected: false),
164 | Item(id: UUID(),
165 | name: "Chocolates",
166 | image: ItemResource.chocolate.image,
167 | color: .orange,
168 | isSelected: false),
169 | Item(id: UUID(),
170 | name: "Maples",
171 | image: ItemResource.chocolate.image,
172 | color: .orange,
173 | isSelected: false),
174 | Item(id: UUID(),
175 | name: "Regulars",
176 | image: ItemResource.chocolate.image,
177 | color: .orange,
178 | isSelected: false),
179 | Item(id: UUID(),
180 | name: "Chocolates",
181 | image: ItemResource.chocolate.image,
182 | color: .orange,
183 | isSelected: false),
184 | Item(id: UUID(),
185 | name: "Blueberrys",
186 | image: ItemResource.chocolate.image,
187 | color: .orange,
188 | isSelected: false),
189 | ])
190 | ]
191 | }
192 | }
193 |
194 |
195 | extension Item {
196 | static var mockItems: [Self] {
197 | return [
198 | Item(id: UUID(),
199 | name: "None",
200 | image: ItemResource.chocolate.image,
201 | color: .orange,
202 | isSelected: false),
203 | Item(id: UUID(),
204 | name: "Glazed",
205 | image: ItemResource.chocolate.image,
206 | color: .orange,
207 | isSelected: false),
208 | Item(id: UUID(),
209 | name: "Sugar",
210 | image: ItemResource.chocolate.image,
211 | color: .orange,
212 | isSelected: false),
213 | Item(id: UUID(),
214 | name: "Powdered Sugar",
215 | image: ItemResource.chocolate.image,
216 | color: .orange,
217 | isSelected: false),
218 | Item(id: UUID(),
219 | name: "Chocolate with Sprinkles",
220 | image: ItemResource.chocolate.image,
221 | color: .orange,
222 | isSelected: false),
223 | Item(id: UUID(),
224 | name: "Chocolate",
225 | image: ItemResource.chocolate.image,
226 | color: .orange,
227 | isSelected: false),
228 | Item(id: UUID(),
229 | name: "Maple",
230 | image: ItemResource.chocolate.image,
231 | color: .orange,
232 | isSelected: false),
233 | Item(id: UUID(),
234 | name: "Regular",
235 | image: ItemResource.chocolate.image,
236 | color: .orange,
237 | isSelected: false),
238 | Item(id: UUID(),
239 | name: "Chocolate",
240 | image: ItemResource.chocolate.image,
241 | color: .orange,
242 | isSelected: false),
243 | Item(id: UUID(),
244 | name: "Blueberry",
245 | image: ItemResource.chocolate.image,
246 | color: .orange,
247 | isSelected: false)
248 | ]
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/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 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/Images/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/Images/chocolate.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "chocolate.jpg",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/Images/chocolate.imageset/chocolate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/Images/chocolate.imageset/chocolate.jpg
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/close_circle.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "close_circle.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | },
21 | "properties" : {
22 | "template-rendering-intent" : "template"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/close_circle.imageset/close_circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/close_circle.imageset/close_circle.png
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/close_circle_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "close_circle_selected.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/close_circle_selected.imageset/close_circle_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mindinventory/BubbleCollectionViewLayout/af879244f8aaf6dafb46c88f7a542df9e77326ee/SwiftDemo/SwiftDemo/Resources/Assets.xcassets/close_circle_selected.imageset/close_circle_selected.png
--------------------------------------------------------------------------------
/SwiftDemo/SwiftDemo/Resources/ItemResources.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ItemResources.swift
3 | // SwiftDemo
4 | //
5 | // Created by Parth Gohel on 22/06/22.
6 | // Copyright © 2022 Parth Gohel. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | enum ItemResource {
12 |
13 | case chocolate
14 |
15 | var image: UIImage {
16 | switch self {
17 | case .chocolate:
18 | return UIImage(named: "chocolate") ?? UIImage()
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------