├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── Example-iOS-SwiftUI ├── Example-iOS-SwiftUI.xcodeproj │ └── project.pbxproj └── Example-iOS-SwiftUI │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── test_images │ │ ├── 0.imageset │ │ ├── Contents.json │ │ └── zelda.png │ │ ├── 1.imageset │ │ ├── Contents.json │ │ └── arctichare.png │ │ ├── 10.imageset │ │ ├── Contents.json │ │ └── monarch.png │ │ ├── 11.imageset │ │ ├── Contents.json │ │ └── mountain.png │ │ ├── 12.imageset │ │ ├── Contents.json │ │ └── peppers.png │ │ ├── 13.imageset │ │ ├── Contents.json │ │ └── pool.png │ │ ├── 14.imageset │ │ ├── Contents.json │ │ └── sails.png │ │ ├── 15.imageset │ │ ├── Contents.json │ │ └── serrano.png │ │ ├── 16.imageset │ │ ├── Contents.json │ │ └── tulips.png │ │ ├── 17.imageset │ │ ├── Contents.json │ │ └── watch.png │ │ ├── 2.imageset │ │ ├── Contents.json │ │ └── baboon.png │ │ ├── 3.imageset │ │ ├── Contents.json │ │ └── barbara.png │ │ ├── 4.imageset │ │ ├── Contents.json │ │ └── boat.png │ │ ├── 5.imageset │ │ ├── Contents.json │ │ └── cat.png │ │ ├── 6.imageset │ │ ├── Contents.json │ │ └── fruits.png │ │ ├── 7.imageset │ │ ├── Contents.json │ │ └── frymire.png │ │ ├── 8.imageset │ │ ├── Contents.json │ │ └── goldhill.png │ │ ├── 9.imageset │ │ ├── Contents.json │ │ └── lena.png │ │ └── Contents.json │ ├── Example_iOS_SwiftUIApp.swift │ ├── ImagesView.swift │ ├── Info.plist │ └── Preview Content │ └── Preview Assets.xcassets │ └── Contents.json ├── Example-iOS ├── Example-iOS.xcodeproj │ └── project.pbxproj └── Example-iOS │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── test_images │ │ ├── 0.imageset │ │ ├── Contents.json │ │ └── zelda.png │ │ ├── 1.imageset │ │ ├── Contents.json │ │ └── arctichare.png │ │ ├── 10.imageset │ │ ├── Contents.json │ │ └── monarch.png │ │ ├── 11.imageset │ │ ├── Contents.json │ │ └── mountain.png │ │ ├── 12.imageset │ │ ├── Contents.json │ │ └── peppers.png │ │ ├── 13.imageset │ │ ├── Contents.json │ │ └── pool.png │ │ ├── 14.imageset │ │ ├── Contents.json │ │ └── sails.png │ │ ├── 15.imageset │ │ ├── Contents.json │ │ └── serrano.png │ │ ├── 16.imageset │ │ ├── Contents.json │ │ └── tulips.png │ │ ├── 17.imageset │ │ ├── Contents.json │ │ └── watch.png │ │ ├── 2.imageset │ │ ├── Contents.json │ │ └── baboon.png │ │ ├── 3.imageset │ │ ├── Contents.json │ │ └── barbara.png │ │ ├── 4.imageset │ │ ├── Contents.json │ │ └── boat.png │ │ ├── 5.imageset │ │ ├── Contents.json │ │ └── cat.png │ │ ├── 6.imageset │ │ ├── Contents.json │ │ └── fruits.png │ │ ├── 7.imageset │ │ ├── Contents.json │ │ └── frymire.png │ │ ├── 8.imageset │ │ ├── Contents.json │ │ └── goldhill.png │ │ ├── 9.imageset │ │ ├── Contents.json │ │ └── lena.png │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── CollectionViewCell.swift │ ├── ImageCollectionViewCell.swift │ ├── ImagesViewController.swift │ ├── Info.plist │ ├── SceneDelegate.swift │ └── ViewController.swift ├── LICENSE ├── Package.swift ├── README.md ├── Screenshots ├── positioning.gif ├── screenshot_01.png ├── screenshot_02.png └── scrolling.gif ├── Source ├── Info.plist └── WatchLayout.swift ├── SwiftUI ├── Info.plist ├── WatchLayoutAttributes.swift ├── WatchLayoutUIPresentable.swift └── WatchLayoutView.swift ├── WatchLayout-SwiftUI.podspec ├── WatchLayout.podspec ├── WatchLayout.xcodeproj └── project.pbxproj └── WatchLayout.xcworkspace ├── contents.xcworkspacedata └── xcshareddata └── IDEWorkspaceChecks.plist /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | 6 | 7 | # Xcode 8 | # 9 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 10 | 11 | ## User settings 12 | xcuserdata/ 13 | 14 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 15 | *.xcscmblueprint 16 | *.xccheckout 17 | 18 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 19 | build/ 20 | DerivedData/ 21 | *.moved-aside 22 | *.pbxuser 23 | !default.pbxuser 24 | *.mode1v3 25 | !default.mode1v3 26 | *.mode2v3 27 | !default.mode2v3 28 | *.perspectivev3 29 | !default.perspectivev3 30 | 31 | ## Obj-C/Swift specific 32 | *.hmap 33 | 34 | ## App packaging 35 | *.ipa 36 | *.dSYM.zip 37 | *.dSYM 38 | 39 | ## Playgrounds 40 | timeline.xctimeline 41 | playground.xcworkspace 42 | 43 | # Swift Package Manager 44 | # 45 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 46 | # Packages/ 47 | # Package.pins 48 | # Package.resolved 49 | # *.xcodeproj 50 | # 51 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 52 | # hence it is not needed unless you have added a package configuration file to your project 53 | # .swiftpm 54 | 55 | .build/ 56 | 57 | # CocoaPods 58 | # 59 | # We recommend against adding the Pods directory to your .gitignore. However 60 | # you should judge for yourself, the pros and cons are mentioned at: 61 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 62 | # 63 | # Pods/ 64 | # 65 | # Add this line if you want to avoid checking in source code from the Xcode workspace 66 | # *.xcworkspace 67 | 68 | # Carthage 69 | # 70 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 71 | # Carthage/Checkouts 72 | 73 | Carthage/Build/ 74 | 75 | # Accio dependency management 76 | Dependencies/ 77 | .accio/ 78 | 79 | # fastlane 80 | # 81 | # It is recommended to not store the screenshots in the git repo. 82 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 83 | # For more information about the recommended setup visit: 84 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 85 | 86 | fastlane/report.xml 87 | fastlane/Preview.html 88 | fastlane/screenshots/**/*.png 89 | fastlane/test_output 90 | 91 | # Code Injection 92 | # 93 | # After new code Injection tools there's a generated folder /iOSInjectionProject 94 | # https://github.com/johnno1962/injectionforxcode 95 | 96 | iOSInjectionProject/ 97 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 156311B5261037D60033FFF8 /* Example_iOS_SwiftUIApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156311B4261037D60033FFF8 /* Example_iOS_SwiftUIApp.swift */; }; 11 | 156311B9261037D70033FFF8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 156311B8261037D70033FFF8 /* Assets.xcassets */; }; 12 | 156311BC261037D70033FFF8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 156311BB261037D70033FFF8 /* Preview Assets.xcassets */; }; 13 | 4B02529128F414FE00EC67AA /* WatchLayout_SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B02528D28F3DEBF00EC67AA /* WatchLayout_SwiftUI.framework */; }; 14 | 4B02529228F414FE00EC67AA /* WatchLayout_SwiftUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B02528D28F3DEBF00EC67AA /* WatchLayout_SwiftUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 4B0BF09F28F93F21007CFB54 /* ImagesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0BF09E28F93F21007CFB54 /* ImagesView.swift */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 156311CD261038750033FFF8 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 156311C8261038740033FFF8 /* WatchLayout.xcodeproj */; 22 | proxyType = 2; 23 | remoteGlobalIDString = 156311632610331E0033FFF8; 24 | remoteInfo = WatchLayout; 25 | }; 26 | 4B02528C28F3DEBF00EC67AA /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 156311C8261038740033FFF8 /* WatchLayout.xcodeproj */; 29 | proxyType = 2; 30 | remoteGlobalIDString = 4B02527E28F3DE8700EC67AA; 31 | remoteInfo = "WatchLayout-SwiftUI"; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXCopyFilesBuildPhase section */ 36 | 4B02529328F414FE00EC67AA /* Embed Frameworks */ = { 37 | isa = PBXCopyFilesBuildPhase; 38 | buildActionMask = 2147483647; 39 | dstPath = ""; 40 | dstSubfolderSpec = 10; 41 | files = ( 42 | 4B02529228F414FE00EC67AA /* WatchLayout_SwiftUI.framework in Embed Frameworks */, 43 | ); 44 | name = "Embed Frameworks"; 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXCopyFilesBuildPhase section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | 156311B1261037D60033FFF8 /* Example-iOS-SwiftUI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-iOS-SwiftUI.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 156311B4261037D60033FFF8 /* Example_iOS_SwiftUIApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Example_iOS_SwiftUIApp.swift; sourceTree = ""; }; 52 | 156311B8261037D70033FFF8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 53 | 156311BB261037D70033FFF8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 54 | 156311BD261037D70033FFF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | 156311C8261038740033FFF8 /* WatchLayout.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = WatchLayout.xcodeproj; path = ../WatchLayout.xcodeproj; sourceTree = ""; }; 56 | 4B0BF09E28F93F21007CFB54 /* ImagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesView.swift; sourceTree = ""; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 156311AE261037D60033FFF8 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | 4B02529128F414FE00EC67AA /* WatchLayout_SwiftUI.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 156311A8261037D60033FFF8 = { 72 | isa = PBXGroup; 73 | children = ( 74 | 156311C8261038740033FFF8 /* WatchLayout.xcodeproj */, 75 | 156311B3261037D60033FFF8 /* Example-iOS-SwiftUI */, 76 | 156311B2261037D60033FFF8 /* Products */, 77 | 156311D2261038930033FFF8 /* Frameworks */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | 156311B2261037D60033FFF8 /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 156311B1261037D60033FFF8 /* Example-iOS-SwiftUI.app */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | 156311B3261037D60033FFF8 /* Example-iOS-SwiftUI */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 156311B4261037D60033FFF8 /* Example_iOS_SwiftUIApp.swift */, 93 | 4B0BF09E28F93F21007CFB54 /* ImagesView.swift */, 94 | 156311B8261037D70033FFF8 /* Assets.xcassets */, 95 | 156311BD261037D70033FFF8 /* Info.plist */, 96 | 156311BA261037D70033FFF8 /* Preview Content */, 97 | ); 98 | path = "Example-iOS-SwiftUI"; 99 | sourceTree = ""; 100 | }; 101 | 156311BA261037D70033FFF8 /* Preview Content */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 156311BB261037D70033FFF8 /* Preview Assets.xcassets */, 105 | ); 106 | path = "Preview Content"; 107 | sourceTree = ""; 108 | }; 109 | 156311C9261038740033FFF8 /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 156311CE261038750033FFF8 /* WatchLayout.framework */, 113 | 4B02528D28F3DEBF00EC67AA /* WatchLayout_SwiftUI.framework */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 156311D2261038930033FFF8 /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | ); 122 | name = Frameworks; 123 | sourceTree = ""; 124 | }; 125 | /* End PBXGroup section */ 126 | 127 | /* Begin PBXNativeTarget section */ 128 | 156311B0261037D60033FFF8 /* Example-iOS-SwiftUI */ = { 129 | isa = PBXNativeTarget; 130 | buildConfigurationList = 156311C0261037D70033FFF8 /* Build configuration list for PBXNativeTarget "Example-iOS-SwiftUI" */; 131 | buildPhases = ( 132 | 156311AD261037D60033FFF8 /* Sources */, 133 | 156311AE261037D60033FFF8 /* Frameworks */, 134 | 156311AF261037D60033FFF8 /* Resources */, 135 | 4B02529328F414FE00EC67AA /* Embed Frameworks */, 136 | ); 137 | buildRules = ( 138 | ); 139 | dependencies = ( 140 | ); 141 | name = "Example-iOS-SwiftUI"; 142 | productName = "Example-iOS-SwiftUI"; 143 | productReference = 156311B1261037D60033FFF8 /* Example-iOS-SwiftUI.app */; 144 | productType = "com.apple.product-type.application"; 145 | }; 146 | /* End PBXNativeTarget section */ 147 | 148 | /* Begin PBXProject section */ 149 | 156311A9261037D60033FFF8 /* Project object */ = { 150 | isa = PBXProject; 151 | attributes = { 152 | LastSwiftUpdateCheck = 1240; 153 | LastUpgradeCheck = 1240; 154 | TargetAttributes = { 155 | 156311B0261037D60033FFF8 = { 156 | CreatedOnToolsVersion = 12.4; 157 | }; 158 | }; 159 | }; 160 | buildConfigurationList = 156311AC261037D60033FFF8 /* Build configuration list for PBXProject "Example-iOS-SwiftUI" */; 161 | compatibilityVersion = "Xcode 9.3"; 162 | developmentRegion = en; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | Base, 167 | ); 168 | mainGroup = 156311A8261037D60033FFF8; 169 | productRefGroup = 156311B2261037D60033FFF8 /* Products */; 170 | projectDirPath = ""; 171 | projectReferences = ( 172 | { 173 | ProductGroup = 156311C9261038740033FFF8 /* Products */; 174 | ProjectRef = 156311C8261038740033FFF8 /* WatchLayout.xcodeproj */; 175 | }, 176 | ); 177 | projectRoot = ""; 178 | targets = ( 179 | 156311B0261037D60033FFF8 /* Example-iOS-SwiftUI */, 180 | ); 181 | }; 182 | /* End PBXProject section */ 183 | 184 | /* Begin PBXReferenceProxy section */ 185 | 156311CE261038750033FFF8 /* WatchLayout.framework */ = { 186 | isa = PBXReferenceProxy; 187 | fileType = wrapper.framework; 188 | path = WatchLayout.framework; 189 | remoteRef = 156311CD261038750033FFF8 /* PBXContainerItemProxy */; 190 | sourceTree = BUILT_PRODUCTS_DIR; 191 | }; 192 | 4B02528D28F3DEBF00EC67AA /* WatchLayout_SwiftUI.framework */ = { 193 | isa = PBXReferenceProxy; 194 | fileType = wrapper.framework; 195 | path = WatchLayout_SwiftUI.framework; 196 | remoteRef = 4B02528C28F3DEBF00EC67AA /* PBXContainerItemProxy */; 197 | sourceTree = BUILT_PRODUCTS_DIR; 198 | }; 199 | /* End PBXReferenceProxy section */ 200 | 201 | /* Begin PBXResourcesBuildPhase section */ 202 | 156311AF261037D60033FFF8 /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | 156311BC261037D70033FFF8 /* Preview Assets.xcassets in Resources */, 207 | 156311B9261037D70033FFF8 /* Assets.xcassets in Resources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXResourcesBuildPhase section */ 212 | 213 | /* Begin PBXSourcesBuildPhase section */ 214 | 156311AD261037D60033FFF8 /* Sources */ = { 215 | isa = PBXSourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | 4B0BF09F28F93F21007CFB54 /* ImagesView.swift in Sources */, 219 | 156311B5261037D60033FFF8 /* Example_iOS_SwiftUIApp.swift in Sources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXSourcesBuildPhase section */ 224 | 225 | /* Begin XCBuildConfiguration section */ 226 | 156311BE261037D70033FFF8 /* Debug */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | ALWAYS_SEARCH_USER_PATHS = NO; 230 | CLANG_ANALYZER_NONNULL = YES; 231 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 232 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 233 | CLANG_CXX_LIBRARY = "libc++"; 234 | CLANG_ENABLE_MODULES = YES; 235 | CLANG_ENABLE_OBJC_ARC = YES; 236 | CLANG_ENABLE_OBJC_WEAK = YES; 237 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 238 | CLANG_WARN_BOOL_CONVERSION = YES; 239 | CLANG_WARN_COMMA = YES; 240 | CLANG_WARN_CONSTANT_CONVERSION = YES; 241 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 242 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 243 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 244 | CLANG_WARN_EMPTY_BODY = YES; 245 | CLANG_WARN_ENUM_CONVERSION = YES; 246 | CLANG_WARN_INFINITE_RECURSION = YES; 247 | CLANG_WARN_INT_CONVERSION = YES; 248 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 249 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 250 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 251 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 252 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 253 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 254 | CLANG_WARN_STRICT_PROTOTYPES = YES; 255 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 256 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 257 | CLANG_WARN_UNREACHABLE_CODE = YES; 258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 259 | COPY_PHASE_STRIP = NO; 260 | DEBUG_INFORMATION_FORMAT = dwarf; 261 | ENABLE_STRICT_OBJC_MSGSEND = YES; 262 | ENABLE_TESTABILITY = YES; 263 | GCC_C_LANGUAGE_STANDARD = gnu11; 264 | GCC_DYNAMIC_NO_PIC = NO; 265 | GCC_NO_COMMON_BLOCKS = YES; 266 | GCC_OPTIMIZATION_LEVEL = 0; 267 | GCC_PREPROCESSOR_DEFINITIONS = ( 268 | "DEBUG=1", 269 | "$(inherited)", 270 | ); 271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 273 | GCC_WARN_UNDECLARED_SELECTOR = YES; 274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 275 | GCC_WARN_UNUSED_FUNCTION = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 278 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 279 | MTL_FAST_MATH = YES; 280 | ONLY_ACTIVE_ARCH = YES; 281 | SDKROOT = iphoneos; 282 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 283 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 284 | }; 285 | name = Debug; 286 | }; 287 | 156311BF261037D70033FFF8 /* Release */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ALWAYS_SEARCH_USER_PATHS = NO; 291 | CLANG_ANALYZER_NONNULL = YES; 292 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 293 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 294 | CLANG_CXX_LIBRARY = "libc++"; 295 | CLANG_ENABLE_MODULES = YES; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_ENABLE_OBJC_WEAK = YES; 298 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 299 | CLANG_WARN_BOOL_CONVERSION = YES; 300 | CLANG_WARN_COMMA = YES; 301 | CLANG_WARN_CONSTANT_CONVERSION = YES; 302 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 303 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 304 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 305 | CLANG_WARN_EMPTY_BODY = YES; 306 | CLANG_WARN_ENUM_CONVERSION = YES; 307 | CLANG_WARN_INFINITE_RECURSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 310 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 311 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 312 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 313 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 314 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 315 | CLANG_WARN_STRICT_PROTOTYPES = YES; 316 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 317 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 318 | CLANG_WARN_UNREACHABLE_CODE = YES; 319 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 320 | COPY_PHASE_STRIP = NO; 321 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 322 | ENABLE_NS_ASSERTIONS = NO; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu11; 325 | GCC_NO_COMMON_BLOCKS = YES; 326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | GCC_WARN_UNUSED_VARIABLE = YES; 332 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 333 | MTL_ENABLE_DEBUG_INFO = NO; 334 | MTL_FAST_MATH = YES; 335 | SDKROOT = iphoneos; 336 | SWIFT_COMPILATION_MODE = wholemodule; 337 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 338 | VALIDATE_PRODUCT = YES; 339 | }; 340 | name = Release; 341 | }; 342 | 156311C1261037D70033FFF8 /* Debug */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 346 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 347 | CODE_SIGN_STYLE = Automatic; 348 | DEVELOPMENT_ASSET_PATHS = "\"Example-iOS-SwiftUI/Preview Content\""; 349 | ENABLE_PREVIEWS = YES; 350 | INFOPLIST_FILE = "Example-iOS-SwiftUI/Info.plist"; 351 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 352 | LD_RUNPATH_SEARCH_PATHS = ( 353 | "$(inherited)", 354 | "@executable_path/Frameworks", 355 | ); 356 | PRODUCT_BUNDLE_IDENTIFIER = "Hoc-Tran.Example-iOS-SwiftUI"; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | SWIFT_VERSION = 5.0; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Debug; 362 | }; 363 | 156311C2261037D70033FFF8 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 367 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 368 | CODE_SIGN_STYLE = Automatic; 369 | DEVELOPMENT_ASSET_PATHS = "\"Example-iOS-SwiftUI/Preview Content\""; 370 | ENABLE_PREVIEWS = YES; 371 | INFOPLIST_FILE = "Example-iOS-SwiftUI/Info.plist"; 372 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 373 | LD_RUNPATH_SEARCH_PATHS = ( 374 | "$(inherited)", 375 | "@executable_path/Frameworks", 376 | ); 377 | PRODUCT_BUNDLE_IDENTIFIER = "Hoc-Tran.Example-iOS-SwiftUI"; 378 | PRODUCT_NAME = "$(TARGET_NAME)"; 379 | SWIFT_VERSION = 5.0; 380 | TARGETED_DEVICE_FAMILY = "1,2"; 381 | }; 382 | name = Release; 383 | }; 384 | /* End XCBuildConfiguration section */ 385 | 386 | /* Begin XCConfigurationList section */ 387 | 156311AC261037D60033FFF8 /* Build configuration list for PBXProject "Example-iOS-SwiftUI" */ = { 388 | isa = XCConfigurationList; 389 | buildConfigurations = ( 390 | 156311BE261037D70033FFF8 /* Debug */, 391 | 156311BF261037D70033FFF8 /* Release */, 392 | ); 393 | defaultConfigurationIsVisible = 0; 394 | defaultConfigurationName = Release; 395 | }; 396 | 156311C0261037D70033FFF8 /* Build configuration list for PBXNativeTarget "Example-iOS-SwiftUI" */ = { 397 | isa = XCConfigurationList; 398 | buildConfigurations = ( 399 | 156311C1261037D70033FFF8 /* Debug */, 400 | 156311C2261037D70033FFF8 /* Release */, 401 | ); 402 | defaultConfigurationIsVisible = 0; 403 | defaultConfigurationName = Release; 404 | }; 405 | /* End XCConfigurationList section */ 406 | }; 407 | rootObject = 156311A9261037D60033FFF8 /* Project object */; 408 | } 409 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "zelda.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/0.imageset/zelda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/0.imageset/zelda.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "arctichare.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/1.imageset/arctichare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/1.imageset/arctichare.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "monarch.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/10.imageset/monarch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/10.imageset/monarch.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/11.imageset/mountain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/11.imageset/mountain.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "peppers.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/12.imageset/peppers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/12.imageset/peppers.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "pool.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/13.imageset/pool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/13.imageset/pool.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "sails.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/14.imageset/sails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/14.imageset/sails.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "serrano.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/15.imageset/serrano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/15.imageset/serrano.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/16.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tulips.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/16.imageset/tulips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/16.imageset/tulips.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/17.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "watch.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/17.imageset/watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/17.imageset/watch.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "baboon.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/2.imageset/baboon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/2.imageset/baboon.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "barbara.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/3.imageset/barbara.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/3.imageset/barbara.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "boat.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/4.imageset/boat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/4.imageset/boat.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "cat.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/5.imageset/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/5.imageset/cat.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "fruits.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/6.imageset/fruits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/6.imageset/fruits.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "frymire.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/7.imageset/frymire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/7.imageset/frymire.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "goldhill.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/8.imageset/goldhill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/8.imageset/goldhill.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "lena.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 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/9.imageset/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/9.imageset/lena.png -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Assets.xcassets/test_images/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Example_iOS_SwiftUIApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import SwiftUI 24 | import WatchLayout_SwiftUI 25 | 26 | @main 27 | struct Example_iOS_SwiftUIApp: App { 28 | @State var layout = WatchLayoutAttributes( 29 | itemSize: 120, 30 | spacing: 16, 31 | minScale: 0.2, 32 | nextItemScale: 0.6 33 | ) 34 | 35 | @State var centeredIndex: Int? = 0 36 | 37 | @State var data = (0..<1000).map { CellItem(id: $0) } 38 | 39 | var body: some Scene { 40 | WindowGroup { 41 | NavigationView { 42 | VStack { 43 | 44 | WatchLayoutView(layoutAttributes: layout, data: data, centeredIndex: $centeredIndex) { i in 45 | Text("\(i.id)") 46 | .frame(maxWidth: .infinity, maxHeight: .infinity) 47 | .background(i.color) 48 | .clipShape(Circle()) 49 | } 50 | .ignoresSafeArea() 51 | .onChange(of: centeredIndex) { newValue in 52 | print(newValue) 53 | } 54 | 55 | 56 | VStack(spacing: 16) { 57 | 58 | Text("Selected item: \(centeredIndex ?? -1)") 59 | 60 | Button("Change data") { 61 | data = (0..<(1000..<1500).randomElement()!).map { CellItem(id: $0) } 62 | } 63 | 64 | Button("Change center") { 65 | centeredIndex = (0.. 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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | 28 | UIApplicationSupportsIndirectInputEvents 29 | 30 | UILaunchScreen 31 | 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Example-iOS-SwiftUI/Example-iOS-SwiftUI/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 151C593A25D04C39002CF5BE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 151C593925D04C39002CF5BE /* AppDelegate.swift */; }; 11 | 151C593C25D04C39002CF5BE /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 151C593B25D04C39002CF5BE /* SceneDelegate.swift */; }; 12 | 151C593E25D04C39002CF5BE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 151C593D25D04C39002CF5BE /* ViewController.swift */; }; 13 | 151C594125D04C39002CF5BE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 151C593F25D04C39002CF5BE /* Main.storyboard */; }; 14 | 151C594325D04C3B002CF5BE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 151C594225D04C3B002CF5BE /* Assets.xcassets */; }; 15 | 151C594625D04C3B002CF5BE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 151C594425D04C3B002CF5BE /* LaunchScreen.storyboard */; }; 16 | 151C595825D04CAA002CF5BE /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 151C595725D04CAA002CF5BE /* CollectionViewCell.swift */; }; 17 | 156311772610341D0033FFF8 /* WatchLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15F3A3DB25D0D5AB00637820 /* WatchLayout.framework */; }; 18 | 156311782610341D0033FFF8 /* WatchLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 15F3A3DB25D0D5AB00637820 /* WatchLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 19 | 15F3A3E625D0E4FE00637820 /* ImagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F3A3E525D0E4FE00637820 /* ImagesViewController.swift */; }; 20 | 15F3A3EA25D0E5F100637820 /* ImageCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F3A3E925D0E5F100637820 /* ImageCollectionViewCell.swift */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 1563120526105ED70033FFF8 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 1563120126105ED70033FFF8 /* WatchLayout.xcodeproj */; 27 | proxyType = 2; 28 | remoteGlobalIDString = 156311E626105E710033FFF8; 29 | remoteInfo = WatchLayout; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXCopyFilesBuildPhase section */ 34 | 156311792610341D0033FFF8 /* Embed Frameworks */ = { 35 | isa = PBXCopyFilesBuildPhase; 36 | buildActionMask = 2147483647; 37 | dstPath = ""; 38 | dstSubfolderSpec = 10; 39 | files = ( 40 | 156311782610341D0033FFF8 /* WatchLayout.framework in Embed Frameworks */, 41 | ); 42 | name = "Embed Frameworks"; 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXCopyFilesBuildPhase section */ 46 | 47 | /* Begin PBXFileReference section */ 48 | 151C593625D04C39002CF5BE /* Example-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 151C593925D04C39002CF5BE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 50 | 151C593B25D04C39002CF5BE /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 51 | 151C593D25D04C39002CF5BE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 52 | 151C594025D04C39002CF5BE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | 151C594225D04C3B002CF5BE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | 151C594525D04C3B002CF5BE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | 151C594725D04C3B002CF5BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 151C595725D04CAA002CF5BE /* CollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; 57 | 1563120126105ED70033FFF8 /* WatchLayout.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = WatchLayout.xcodeproj; path = ../WatchLayout.xcodeproj; sourceTree = ""; }; 58 | 15F3A3E525D0E4FE00637820 /* ImagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesViewController.swift; sourceTree = ""; }; 59 | 15F3A3E925D0E5F100637820 /* ImageCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCollectionViewCell.swift; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 151C593325D04C39002CF5BE /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 156311772610341D0033FFF8 /* WatchLayout.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXFrameworksBuildPhase section */ 72 | 73 | /* Begin PBXGroup section */ 74 | 151C592D25D04C39002CF5BE = { 75 | isa = PBXGroup; 76 | children = ( 77 | 1563120126105ED70033FFF8 /* WatchLayout.xcodeproj */, 78 | 151C593825D04C39002CF5BE /* Example-iOS */, 79 | 151C593725D04C39002CF5BE /* Products */, 80 | 15F3A3D625D0D5AB00637820 /* WatchLayout.xcodeproj */, 81 | 156311752610341D0033FFF8 /* Frameworks */, 82 | ); 83 | sourceTree = ""; 84 | }; 85 | 151C593725D04C39002CF5BE /* Products */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 151C593625D04C39002CF5BE /* Example-iOS.app */, 89 | ); 90 | name = Products; 91 | sourceTree = ""; 92 | }; 93 | 151C593825D04C39002CF5BE /* Example-iOS */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 151C593925D04C39002CF5BE /* AppDelegate.swift */, 97 | 151C593B25D04C39002CF5BE /* SceneDelegate.swift */, 98 | 151C593D25D04C39002CF5BE /* ViewController.swift */, 99 | 15F3A3E525D0E4FE00637820 /* ImagesViewController.swift */, 100 | 151C595725D04CAA002CF5BE /* CollectionViewCell.swift */, 101 | 15F3A3E925D0E5F100637820 /* ImageCollectionViewCell.swift */, 102 | 151C593F25D04C39002CF5BE /* Main.storyboard */, 103 | 151C594225D04C3B002CF5BE /* Assets.xcassets */, 104 | 151C594425D04C3B002CF5BE /* LaunchScreen.storyboard */, 105 | 151C594725D04C3B002CF5BE /* Info.plist */, 106 | ); 107 | path = "Example-iOS"; 108 | sourceTree = ""; 109 | }; 110 | 156311752610341D0033FFF8 /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | ); 114 | name = Frameworks; 115 | sourceTree = ""; 116 | }; 117 | 15F3A3D725D0D5AB00637820 /* Products */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 1563120626105ED70033FFF8 /* WatchLayout.framework */, 121 | ); 122 | name = Products; 123 | sourceTree = ""; 124 | }; 125 | 1563120926105EED0033FFF8 /* Frameworks */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXNativeTarget section */ 135 | 151C593525D04C39002CF5BE /* Example-iOS */ = { 136 | isa = PBXNativeTarget; 137 | buildConfigurationList = 151C594A25D04C3B002CF5BE /* Build configuration list for PBXNativeTarget "Example-iOS" */; 138 | buildPhases = ( 139 | 151C593225D04C39002CF5BE /* Sources */, 140 | 151C593325D04C39002CF5BE /* Frameworks */, 141 | 151C593425D04C39002CF5BE /* Resources */, 142 | 156311792610341D0033FFF8 /* Embed Frameworks */, 143 | ); 144 | buildRules = ( 145 | ); 146 | dependencies = ( 147 | ); 148 | name = "Example-iOS"; 149 | productName = "Example-iOS"; 150 | productReference = 151C593625D04C39002CF5BE /* Example-iOS.app */; 151 | productType = "com.apple.product-type.application"; 152 | }; 153 | /* End PBXNativeTarget section */ 154 | 155 | /* Begin PBXProject section */ 156 | 151C592E25D04C39002CF5BE /* Project object */ = { 157 | isa = PBXProject; 158 | attributes = { 159 | LastSwiftUpdateCheck = 1240; 160 | LastUpgradeCheck = 1240; 161 | TargetAttributes = { 162 | 151C593525D04C39002CF5BE = { 163 | CreatedOnToolsVersion = 12.4; 164 | }; 165 | }; 166 | }; 167 | buildConfigurationList = 151C593125D04C39002CF5BE /* Build configuration list for PBXProject "Example-iOS" */; 168 | compatibilityVersion = "Xcode 9.3"; 169 | developmentRegion = en; 170 | hasScannedForEncodings = 0; 171 | knownRegions = ( 172 | en, 173 | Base, 174 | ); 175 | mainGroup = 151C592D25D04C39002CF5BE; 176 | productRefGroup = 151C593725D04C39002CF5BE /* Products */; 177 | projectDirPath = ""; 178 | projectReferences = ( 179 | { 180 | ProductGroup = 1563120226105ED70033FFF8 /* Products */; 181 | ProjectRef = 1563120126105ED70033FFF8 /* WatchLayout.xcodeproj */; 182 | }, 183 | ); 184 | projectRoot = ""; 185 | targets = ( 186 | 151C593525D04C39002CF5BE /* Example-iOS */, 187 | ); 188 | }; 189 | /* End PBXProject section */ 190 | 191 | /* Begin PBXReferenceProxy section */ 192 | 1563120626105ED70033FFF8 /* WatchLayout.framework */ = { 193 | isa = PBXReferenceProxy; 194 | fileType = wrapper.framework; 195 | path = WatchLayout.framework; 196 | remoteRef = 1563120526105ED70033FFF8 /* PBXContainerItemProxy */; 197 | sourceTree = BUILT_PRODUCTS_DIR; 198 | }; 199 | /* End PBXReferenceProxy section */ 200 | 201 | /* Begin PBXResourcesBuildPhase section */ 202 | 151C593425D04C39002CF5BE /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | 151C594625D04C3B002CF5BE /* LaunchScreen.storyboard in Resources */, 207 | 151C594325D04C3B002CF5BE /* Assets.xcassets in Resources */, 208 | 151C594125D04C39002CF5BE /* Main.storyboard in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXResourcesBuildPhase section */ 213 | 214 | /* Begin PBXSourcesBuildPhase section */ 215 | 151C593225D04C39002CF5BE /* Sources */ = { 216 | isa = PBXSourcesBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | 151C593E25D04C39002CF5BE /* ViewController.swift in Sources */, 220 | 151C593A25D04C39002CF5BE /* AppDelegate.swift in Sources */, 221 | 15F3A3EA25D0E5F100637820 /* ImageCollectionViewCell.swift in Sources */, 222 | 15F3A3E625D0E4FE00637820 /* ImagesViewController.swift in Sources */, 223 | 151C595825D04CAA002CF5BE /* CollectionViewCell.swift in Sources */, 224 | 151C593C25D04C39002CF5BE /* SceneDelegate.swift in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXSourcesBuildPhase section */ 229 | 230 | /* Begin PBXVariantGroup section */ 231 | 151C593F25D04C39002CF5BE /* Main.storyboard */ = { 232 | isa = PBXVariantGroup; 233 | children = ( 234 | 151C594025D04C39002CF5BE /* Base */, 235 | ); 236 | name = Main.storyboard; 237 | sourceTree = ""; 238 | }; 239 | 151C594425D04C3B002CF5BE /* LaunchScreen.storyboard */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | 151C594525D04C3B002CF5BE /* Base */, 243 | ); 244 | name = LaunchScreen.storyboard; 245 | sourceTree = ""; 246 | }; 247 | /* End PBXVariantGroup section */ 248 | 249 | /* Begin XCBuildConfiguration section */ 250 | 151C594825D04C3B002CF5BE /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_ANALYZER_NONNULL = YES; 255 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 256 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 257 | CLANG_CXX_LIBRARY = "libc++"; 258 | CLANG_ENABLE_MODULES = YES; 259 | CLANG_ENABLE_OBJC_ARC = YES; 260 | CLANG_ENABLE_OBJC_WEAK = 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 | COPY_PHASE_STRIP = NO; 284 | DEBUG_INFORMATION_FORMAT = dwarf; 285 | ENABLE_STRICT_OBJC_MSGSEND = YES; 286 | ENABLE_TESTABILITY = YES; 287 | GCC_C_LANGUAGE_STANDARD = gnu11; 288 | GCC_DYNAMIC_NO_PIC = NO; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_OPTIMIZATION_LEVEL = 0; 291 | GCC_PREPROCESSOR_DEFINITIONS = ( 292 | "DEBUG=1", 293 | "$(inherited)", 294 | ); 295 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 296 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 297 | GCC_WARN_UNDECLARED_SELECTOR = YES; 298 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 299 | GCC_WARN_UNUSED_FUNCTION = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 302 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 303 | MTL_FAST_MATH = YES; 304 | ONLY_ACTIVE_ARCH = YES; 305 | SDKROOT = iphoneos; 306 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 307 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 308 | }; 309 | name = Debug; 310 | }; 311 | 151C594925D04C3B002CF5BE /* Release */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | ALWAYS_SEARCH_USER_PATHS = NO; 315 | CLANG_ANALYZER_NONNULL = YES; 316 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 317 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 318 | CLANG_CXX_LIBRARY = "libc++"; 319 | CLANG_ENABLE_MODULES = YES; 320 | CLANG_ENABLE_OBJC_ARC = YES; 321 | CLANG_ENABLE_OBJC_WEAK = YES; 322 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 323 | CLANG_WARN_BOOL_CONVERSION = YES; 324 | CLANG_WARN_COMMA = YES; 325 | CLANG_WARN_CONSTANT_CONVERSION = YES; 326 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 327 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 328 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 329 | CLANG_WARN_EMPTY_BODY = YES; 330 | CLANG_WARN_ENUM_CONVERSION = YES; 331 | CLANG_WARN_INFINITE_RECURSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 334 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 335 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 336 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 337 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 338 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 339 | CLANG_WARN_STRICT_PROTOTYPES = YES; 340 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 341 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 342 | CLANG_WARN_UNREACHABLE_CODE = YES; 343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 344 | COPY_PHASE_STRIP = NO; 345 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 346 | ENABLE_NS_ASSERTIONS = NO; 347 | ENABLE_STRICT_OBJC_MSGSEND = YES; 348 | GCC_C_LANGUAGE_STANDARD = gnu11; 349 | GCC_NO_COMMON_BLOCKS = YES; 350 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 351 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 352 | GCC_WARN_UNDECLARED_SELECTOR = YES; 353 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 354 | GCC_WARN_UNUSED_FUNCTION = YES; 355 | GCC_WARN_UNUSED_VARIABLE = YES; 356 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 357 | MTL_ENABLE_DEBUG_INFO = NO; 358 | MTL_FAST_MATH = YES; 359 | SDKROOT = iphoneos; 360 | SWIFT_COMPILATION_MODE = wholemodule; 361 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 362 | VALIDATE_PRODUCT = YES; 363 | }; 364 | name = Release; 365 | }; 366 | 151C594B25D04C3B002CF5BE /* Debug */ = { 367 | isa = XCBuildConfiguration; 368 | buildSettings = { 369 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 370 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 371 | CODE_SIGN_STYLE = Automatic; 372 | INFOPLIST_FILE = "Example-iOS/Info.plist"; 373 | LD_RUNPATH_SEARCH_PATHS = ( 374 | "$(inherited)", 375 | "@executable_path/Frameworks", 376 | ); 377 | PRODUCT_BUNDLE_IDENTIFIER = "Hoc-Tran.Example-iOS"; 378 | PRODUCT_NAME = "$(TARGET_NAME)"; 379 | SWIFT_VERSION = 5.0; 380 | TARGETED_DEVICE_FAMILY = "1,2"; 381 | }; 382 | name = Debug; 383 | }; 384 | 151C594C25D04C3B002CF5BE /* Release */ = { 385 | isa = XCBuildConfiguration; 386 | buildSettings = { 387 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 388 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 389 | CODE_SIGN_STYLE = Automatic; 390 | INFOPLIST_FILE = "Example-iOS/Info.plist"; 391 | LD_RUNPATH_SEARCH_PATHS = ( 392 | "$(inherited)", 393 | "@executable_path/Frameworks", 394 | ); 395 | PRODUCT_BUNDLE_IDENTIFIER = "Hoc-Tran.Example-iOS"; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | SWIFT_VERSION = 5.0; 398 | TARGETED_DEVICE_FAMILY = "1,2"; 399 | }; 400 | name = Release; 401 | }; 402 | /* End XCBuildConfiguration section */ 403 | 404 | /* Begin XCConfigurationList section */ 405 | 151C593125D04C39002CF5BE /* Build configuration list for PBXProject "Example-iOS" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | 151C594825D04C3B002CF5BE /* Debug */, 409 | 151C594925D04C3B002CF5BE /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | 151C594A25D04C3B002CF5BE /* Build configuration list for PBXNativeTarget "Example-iOS" */ = { 415 | isa = XCConfigurationList; 416 | buildConfigurations = ( 417 | 151C594B25D04C3B002CF5BE /* Debug */, 418 | 151C594C25D04C3B002CF5BE /* Release */, 419 | ); 420 | defaultConfigurationIsVisible = 0; 421 | defaultConfigurationName = Release; 422 | }; 423 | /* End XCConfigurationList section */ 424 | }; 425 | rootObject = 151C592E25D04C39002CF5BE /* Project object */; 426 | } 427 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | 25 | @main 26 | class AppDelegate: UIResponder, UIApplicationDelegate { 27 | 28 | 29 | 30 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 31 | // Override point for customization after application launch. 32 | return true 33 | } 34 | 35 | // MARK: UISceneSession Lifecycle 36 | 37 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 38 | // Called when a new scene session is being created. 39 | // Use this method to select a configuration to create the new scene with. 40 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 41 | } 42 | 43 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 44 | // Called when the user discards a scene session. 45 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 46 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 47 | } 48 | 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "zelda.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/0.imageset/zelda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/0.imageset/zelda.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "arctichare.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/1.imageset/arctichare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/1.imageset/arctichare.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "monarch.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/10.imageset/monarch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/10.imageset/monarch.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountain.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/11.imageset/mountain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/11.imageset/mountain.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "peppers.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/12.imageset/peppers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/12.imageset/peppers.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "pool.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/13.imageset/pool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/13.imageset/pool.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "sails.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/14.imageset/sails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/14.imageset/sails.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "serrano.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/15.imageset/serrano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/15.imageset/serrano.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/16.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tulips.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/16.imageset/tulips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/16.imageset/tulips.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/17.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "watch.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/17.imageset/watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/17.imageset/watch.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "baboon.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/2.imageset/baboon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/2.imageset/baboon.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "barbara.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/3.imageset/barbara.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/3.imageset/barbara.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "boat.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/4.imageset/boat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/4.imageset/boat.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "cat.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/5.imageset/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/5.imageset/cat.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "fruits.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/6.imageset/fruits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/6.imageset/fruits.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "frymire.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/7.imageset/frymire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/7.imageset/frymire.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "goldhill.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/8.imageset/goldhill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/8.imageset/goldhill.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "lena.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 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/9.imageset/lena.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Example-iOS/Example-iOS/Assets.xcassets/test_images/9.imageset/lena.png -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Assets.xcassets/test_images/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/CollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | 25 | class CollectionViewCell: UICollectionViewCell { 26 | @IBOutlet var label: UILabel! 27 | 28 | override func layoutSubviews() { 29 | super.layoutSubviews() 30 | clipsToBounds = true 31 | layer.cornerRadius = bounds.height * 0.5 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/ImageCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | 25 | class ImageCollectionViewCell: UICollectionViewCell { 26 | @IBOutlet var imgView: UIImageView! 27 | 28 | override func prepareForReuse() { 29 | super.prepareForReuse() 30 | imgView.image = nil 31 | } 32 | 33 | override func layoutSubviews() { 34 | super.layoutSubviews() 35 | clipsToBounds = true 36 | layer.cornerRadius = bounds.height * 0.5 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/ImagesViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | import WatchLayout 25 | 26 | class ImagesViewController: UIViewController, UICollectionViewDataSource { 27 | 28 | @IBOutlet var collectionView: UICollectionView! 29 | private var items = [String]() 30 | 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | items = (0...17).map { "\($0)"} 36 | 37 | let layout = WatchLayout() 38 | layout.itemSize = 200 39 | layout.spacing = -40 40 | layout.minScale = 0.2 41 | layout.nextItemScale = 0.4 42 | 43 | collectionView.collectionViewLayout = layout 44 | 45 | DispatchQueue.main.async { 46 | self.collectionView.setContentOffset(layout.centeredOffsetForItem(indexPath: IndexPath(item: 0, section: 0)), animated: true) 47 | } 48 | } 49 | 50 | override func didReceiveMemoryWarning() { 51 | super.didReceiveMemoryWarning() 52 | // Dispose of any resources that can be recreated. 53 | } 54 | 55 | func numberOfSections(in collectionView: UICollectionView) -> Int { 56 | return 1 57 | } 58 | 59 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 60 | return items.count 61 | } 62 | 63 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 64 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ImageCollectionViewCell 65 | cell.imgView.image = UIImage(named: items[indexPath.item]) 66 | return cell 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UIApplicationSupportsIndirectInputEvents 43 | 44 | UILaunchStoryboardName 45 | LaunchScreen 46 | UIMainStoryboardFile 47 | Main 48 | UIRequiredDeviceCapabilities 49 | 50 | armv7 51 | 52 | UISupportedInterfaceOrientations 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | UISupportedInterfaceOrientations~ipad 59 | 60 | UIInterfaceOrientationPortrait 61 | UIInterfaceOrientationPortraitUpsideDown 62 | UIInterfaceOrientationLandscapeLeft 63 | UIInterfaceOrientationLandscapeRight 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | 25 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 26 | 27 | var window: UIWindow? 28 | 29 | 30 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 31 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 32 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 33 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 34 | guard let _ = (scene as? UIWindowScene) else { return } 35 | } 36 | 37 | func sceneDidDisconnect(_ scene: UIScene) { 38 | // Called as the scene is being released by the system. 39 | // This occurs shortly after the scene enters the background, or when its session is discarded. 40 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 41 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 42 | } 43 | 44 | func sceneDidBecomeActive(_ scene: UIScene) { 45 | // Called when the scene has moved from an inactive state to an active state. 46 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 47 | } 48 | 49 | func sceneWillResignActive(_ scene: UIScene) { 50 | // Called when the scene will move from an active state to an inactive state. 51 | // This may occur due to temporary interruptions (ex. an incoming phone call). 52 | } 53 | 54 | func sceneWillEnterForeground(_ scene: UIScene) { 55 | // Called as the scene transitions from the background to the foreground. 56 | // Use this method to undo the changes made on entering the background. 57 | } 58 | 59 | func sceneDidEnterBackground(_ scene: UIScene) { 60 | // Called as the scene transitions from the foreground to the background. 61 | // Use this method to save data, release shared resources, and store enough scene-specific state information 62 | // to restore the scene back to its current state. 63 | } 64 | 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /Example-iOS/Example-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | import WatchLayout 25 | 26 | class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { 27 | 28 | @IBOutlet var collectionView: UICollectionView! 29 | private var items = [UIColor]() 30 | 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | let r: Range = 0..<1 36 | items = (0..<100).map { i -> UIColor in 37 | UIColor( 38 | red: CGFloat.random(in: r), 39 | green: CGFloat.random(in: r), 40 | blue: CGFloat.random(in: r), 41 | alpha: 1) 42 | } 43 | 44 | let layout = WatchLayout() 45 | layout.itemSize = 129 46 | layout.spacing = 16 47 | layout.minScale = 0.2 48 | layout.nextItemScale = 0.6 49 | 50 | collectionView.collectionViewLayout = layout 51 | collectionView.delegate = self 52 | 53 | DispatchQueue.main.async { 54 | self.collectionView.setContentOffset(layout.centeredOffsetForItem(indexPath: IndexPath(item: 0, section: 0)), animated: true) 55 | } 56 | } 57 | 58 | override func didReceiveMemoryWarning() { 59 | super.didReceiveMemoryWarning() 60 | // Dispose of any resources that can be recreated. 61 | } 62 | 63 | func numberOfSections(in collectionView: UICollectionView) -> Int { 64 | return 1 65 | } 66 | 67 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 68 | return items.count 69 | } 70 | 71 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 72 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell 73 | cell.backgroundColor = items[indexPath.item] 74 | cell.label.text = "\(indexPath.item)" 75 | return cell 76 | } 77 | 78 | func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 79 | print((collectionView.collectionViewLayout as! WatchLayout).centeredIndexPath) 80 | } 81 | } 82 | 83 | extension ViewController { 84 | 85 | } 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Hoc Tran 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // 3 | // Package.swift 4 | // 5 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import PackageDescription 27 | 28 | let package = Package( 29 | name: "WatchLayout", 30 | platforms: [.iOS(.v13)], 31 | products: [ 32 | .library( 33 | name: "WatchLayout", 34 | targets: ["WatchLayout"] 35 | ), 36 | .library( 37 | name: "WatchLayout-SwiftUI", 38 | targets: ["WatchLayout-SwiftUI"] 39 | ) 40 | ], 41 | targets: [ 42 | .target( 43 | name: "WatchLayout", 44 | path: "Source" 45 | ), 46 | .target( 47 | name: "WatchLayout-SwiftUI", 48 | dependencies: ["WatchLayout"], 49 | path: "SwiftUI" 50 | ) 51 | ], 52 | swiftLanguageVersions: [.v5] 53 | ) 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WatchLayout 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/WatchLayout.svg?style=flat)](https://cocoapods.org/pods/WatchLayout) 4 | [![License](https://img.shields.io/cocoapods/l/WatchLayout.svg?style=flat)](https://cocoapods.org/pods/WatchLayout) 5 | [![Platform](https://img.shields.io/cocoapods/p/WatchLayout.svg?style=flat)](https://cocoapods.org/pods/WatchLayout) 6 | 7 | ## Requirements 8 | 9 | iOS 13+ 10 | 11 | ## Installation 12 | 13 | ### Cocoapods 14 | WatchLayout is available through [CocoaPods](https://cocoapods.org). To install 15 | it, simply add the following line to your Podfile: 16 | 17 | UIKit | SwiftUI 18 | :-------------:|:-------------: 19 | | `pod 'WatchLayout'` | `pod 'WatchLayout-SwiftUI'` | 20 | 21 | 22 | ### Swift Package Manager 23 | 24 | ```swift 25 | dependencies: [ 26 | .package(url: "https://github.com/HocTran/WatchLayout.git", .upToNextMajor(from: "1.1.0")) 27 | ] 28 | ``` 29 | 30 | ## Usage 31 | 32 | ### UIKit 33 | 34 | ```swift 35 | let layout = WatchLayout() 36 | ``` 37 | 38 | **Support configurations** 39 | 40 | Set the item size for collection view cell. 41 | ```swift 42 | layout.itemSize = 200 43 | ``` 44 | 45 | Set the cell item spacing. Minus means the items can be overlapped. Default value 0. 46 | ```swift 47 | layout.spacing = -40 48 | ``` 49 | 50 | Set the scaling for item next to the item in the center. Default value 0.4 51 | ```swift 52 | layout.nextItemScale = 0.4 53 | ``` 54 | 55 | Set the minimum scaling for item depending on the distance to the center. Default value 0.2 56 | ```swift 57 | layout.minScale = 0.2 58 | ``` 59 | 60 | Assign the custom layout to UICollectionView 61 | ```swift 62 | collectionView.collectionViewLayout = layout 63 | ``` 64 | 65 | Scroll to an item at the index path 66 | ```swift 67 | self.collectionView.setContentOffset(layout.centeredOffsetForItem(indexPath: IndexPath(item: 0, section: 0)), animated: true) 68 | ``` 69 | 70 | Get the current centered index 71 | ```swift 72 | layout.centeredIndexPath 73 | ``` 74 | 75 | ### SwiftUI 76 | 77 | SwiftUI version is built on top of `UIViewRepresentable` of `WatchLayout`. 78 | 79 | Declare a layout attributes (See the detail of each param in the UIKit usage above). 80 | 81 | ```swift 82 | @State var layout = WatchLayoutAttributes( 83 | itemSize: 120, 84 | spacing: 16, 85 | minScale: 0.2, 86 | nextItemScale: 0.6 87 | ) 88 | ``` 89 | 90 | Create and assign layout attributes to the view 91 | 92 | * data: *RandomAccessCollection* (or *Binding*) for computing the collection. 93 | 94 | * centeredIndex: **(Optional)** A binding to indentify the centered index of the collection. 95 | 96 | ```swift 97 | WatchLayoutView( 98 | layoutAttributes: layout, 99 | data: data, 100 | centeredIndex: $centeredIndex, 101 | cellContent: ({ dataElement in 102 | // Build up your cell content here 103 | Text(dataElement.description) 104 | .frame(maxWidth: .infinity, maxHeight: .infinity) 105 | .background(dataElement.color) 106 | .clipShape(Circle()) 107 | }) 108 | ``` 109 | 110 | If **data** element is *hashable*, the centered binding can be a data element. 111 | 112 | ```swift 113 | WatchLayoutView( 114 | layoutAttributes: layout, 115 | data: data, 116 | centeredItem: $centeredItem, 117 | cellContent: ({ dataElement in 118 | // Build up your cell content here 119 | Text(dataElement.description) 120 | .frame(maxWidth: .infinity, maxHeight: .infinity) 121 | .background(dataElement.color) 122 | .clipShape(Circle()) 123 | }) 124 | ``` 125 | 126 | ## Screenshots 127 | 128 | Positioning | Scrolling 129 | :-------------:|:-------------: 130 | ![](https://raw.githubusercontent.com/HocTran/WatchLayout/SwiftUI/Screenshots/positioning.gif) | ![](https://raw.githubusercontent.com/HocTran/WatchLayout/SwiftUI/Screenshots/scrolling.gif) 131 | 132 | 133 | Example 01 | Example 02 134 | :-------------:|:-------------: 135 | ![](https://raw.githubusercontent.com/HocTran/WatchLayout/SwiftUI/Screenshots/screenshot_01.png) | ![](https://raw.githubusercontent.com/HocTran/WatchLayout/SwiftUI/Screenshots/screenshot_02.png) 136 | 137 | 138 | ## Example 139 | 140 | To run the example project, clone the repo, open `WatchLayout.xcworkspace`. 141 | 142 | ### UIKit 143 | 144 | * Select scheme `WatchLayout`, **Cmd+B** to build the framework. 145 | 146 | * Select scheme `Example-iOS`, and run the example. 147 | 148 | ### SwiftUI 149 | 150 | * Select scheme `WatchLayout`, **Cmd+B** to build the framework. 151 | 152 | * Select scheme `WatchLayout-SwiftUI`, **Cmd+B** to build the framework. 153 | 154 | * Select scheme `Example-iOS`, and run the example. 155 | 156 | 157 | ## Author 158 | 159 | HocTran, tranhoc78@gmail.com 160 | 161 | ## License 162 | 163 | WatchLayout is available under the MIT license. See the [LICENSE file](LICENSE) for more info. 164 | -------------------------------------------------------------------------------- /Screenshots/positioning.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Screenshots/positioning.gif -------------------------------------------------------------------------------- /Screenshots/screenshot_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Screenshots/screenshot_01.png -------------------------------------------------------------------------------- /Screenshots/screenshot_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Screenshots/screenshot_02.png -------------------------------------------------------------------------------- /Screenshots/scrolling.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HocTran/WatchLayout/1eee90826452e1f3d3d8c4488ed65de63f0e90bc/Screenshots/scrolling.gif -------------------------------------------------------------------------------- /Source/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /Source/WatchLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | 25 | final public class WatchLayout: UICollectionViewLayout { 26 | 27 | @objc public var itemSize: CGFloat = 100 { 28 | didSet { 29 | invalidateLayout() 30 | } 31 | } 32 | 33 | @objc public var spacing: CGFloat = 0 { 34 | didSet { 35 | invalidateLayout() 36 | } 37 | } 38 | 39 | private var _minScale: CGFloat = 0.2 { 40 | didSet { 41 | invalidateLayout() 42 | } 43 | } 44 | 45 | @objc public var minScale: CGFloat { 46 | get { 47 | return _minScale 48 | } 49 | set { 50 | _minScale = min(max(newValue, 0), 1) 51 | } 52 | } 53 | 54 | private var _nextItemScale: CGFloat = 0.4 { 55 | didSet { 56 | invalidateLayout() 57 | } 58 | } 59 | 60 | @objc public var nextItemScale: CGFloat { 61 | get { 62 | return _nextItemScale 63 | } 64 | set { 65 | _nextItemScale = min(max(newValue, 0), 1) 66 | } 67 | } 68 | 69 | @objc public func centeredOffsetForItem(indexPath: IndexPath) -> CGPoint { 70 | guard let collectionView = self.collectionView else { 71 | return .zero 72 | } 73 | 74 | guard attributes.indices.contains(indexPath.item) else { 75 | return .zero 76 | } 77 | 78 | let attr = attributes[indexPath.item] 79 | return CGPoint( 80 | x: attr.center.x - collectionView.bounds.width * 0.5, 81 | y: attr.center.y - collectionView.bounds.height * 0.5 82 | ) 83 | } 84 | 85 | @objc public private(set) var centeredIndexPath: IndexPath? 86 | 87 | private var attributes = [UICollectionViewLayoutAttributes]() 88 | private var layers = 1 89 | 90 | public override var collectionViewContentSize: CGSize { 91 | guard let collectionView = self.collectionView else { 92 | return .zero 93 | } 94 | 95 | let size = CGFloat(layers) * (itemSize + spacing) * 2 - (itemSize + spacing) 96 | let inset = collectionView.contentInset 97 | return CGSize(width: size + collectionView.bounds.width + inset.left + inset.right, 98 | height: size + collectionView.bounds.height + inset.top + inset.bottom) 99 | } 100 | 101 | public override class var layoutAttributesClass: AnyClass { 102 | return UICollectionViewLayoutAttributes.self 103 | } 104 | 105 | public override func prepare() { 106 | 107 | super.prepare() 108 | 109 | guard let collectionView = self.collectionView else { 110 | return 111 | } 112 | 113 | let N = collectionView.numberOfItems(inSection: 0) 114 | 115 | if attributes.count == N { 116 | return 117 | } 118 | 119 | if N == 0 { 120 | attributes.removeAll() 121 | centeredIndexPath = nil 122 | return 123 | } 124 | 125 | let center = CGPoint.zero 126 | 127 | var i = 0 128 | var layer = 0 129 | 130 | attributes.removeAll() 131 | centeredIndexPath = nil//IndexPath(item: 0, section: 0) 132 | 133 | while i < N { 134 | 135 | if layer == 0 { 136 | let attr = UICollectionViewLayoutAttributes(forCellWith: IndexPath(item: i, section: 0)) 137 | attr.size = CGSize(width: itemSize, height: itemSize) 138 | attr.center = center 139 | attributes.append(attr) 140 | 141 | i += 1 142 | } else { 143 | 144 | let radius = CGFloat(layer) * (itemSize + spacing) 145 | let hexagon = Multagon(6, center: center, radius: radius) 146 | 147 | for j in 0 ..< layer { 148 | 149 | let vertexes = hexagon.midVertex(slice: layer, slideIndex: j) 150 | for vertex in vertexes { 151 | let attr = UICollectionViewLayoutAttributes(forCellWith: IndexPath(item: i, section: 0)) 152 | attr.size = CGSize(width: itemSize, height: itemSize) 153 | attr.center = vertex 154 | 155 | attributes.append(attr) 156 | i += 1 157 | if i >= N { 158 | break 159 | } 160 | } 161 | 162 | if i >= N { 163 | break 164 | } 165 | } 166 | } 167 | 168 | layer += 1 169 | } 170 | 171 | layers = max(layer, 1) 172 | 173 | // move all to center 174 | let size = CGFloat(layers) * (itemSize + spacing) * 2 - (itemSize + spacing) 175 | let inset = collectionView.contentInset 176 | 177 | attributes.forEach { attr in 178 | attr.center = CGPoint( 179 | x: attr.center.x + size * 0.5 + inset.left + collectionView.bounds.width * 0.5, 180 | y: attr.center.y + size * 0.5 + inset.top + collectionView.bounds.height * 0.5 181 | ) 182 | } 183 | } 184 | 185 | public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 186 | 187 | guard let collectionView = self.collectionView else { 188 | return nil 189 | } 190 | 191 | let center = CGPoint(x: collectionView.bounds.midX, y: collectionView.bounds.midY) 192 | let result = attributes.filter { rect.intersects($0.frame) } 193 | result.forEach { attr in 194 | let distance = CGPoint.distance(center, attr.center) 195 | 196 | var scale = 1 - (1 - nextItemScale) * distance / itemSize // 0.8 is scale at 1 itemsize distance 197 | scale = min(max(scale, minScale), 1) 198 | attr.transform = CGAffineTransform(scaleX: scale, y: scale) 199 | } 200 | return result 201 | } 202 | 203 | // public override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 204 | // guard let collectionView = self.collectionView else { 205 | // return nil 206 | // } 207 | // } 208 | 209 | public override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { 210 | return true 211 | } 212 | 213 | //auto snap to center of item 214 | public override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { 215 | guard let collectionView = self.collectionView else { 216 | return proposedContentOffset 217 | } 218 | 219 | let proposedCenter = CGPoint(x: proposedContentOffset.x + collectionView.bounds.width * 0.5, 220 | y: proposedContentOffset.y + collectionView.bounds.height * 0.5) 221 | 222 | let closestAttr = attributes.min { (attr1, attr2) -> Bool in 223 | return CGPoint.distance(attr1.center, proposedCenter) < CGPoint.distance(attr2.center, proposedCenter) 224 | 225 | } 226 | 227 | if let attr = closestAttr { 228 | centeredIndexPath = attr.indexPath 229 | 230 | let expectedOffset = CGPoint(x: attr.center.x - proposedCenter.x + proposedContentOffset.x, 231 | y: attr.center.y - proposedCenter.y + proposedContentOffset.y) 232 | return expectedOffset 233 | } else { 234 | return proposedContentOffset 235 | } 236 | } 237 | } 238 | 239 | // Helper 240 | private extension CGPoint { 241 | static func distance(_ p1: CGPoint, _ p2: CGPoint) -> CGFloat { 242 | return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)) 243 | } 244 | } 245 | 246 | private struct Multagon { 247 | 248 | let vertexes: [CGPoint] 249 | 250 | init(_ numberOfVertex: Int, center: CGPoint, radius: CGFloat) { 251 | let step = CGFloat.pi / (CGFloat(numberOfVertex) * 0.5) 252 | vertexes = (0.. [CGPoint] { 261 | if slice == 0 { 262 | return [] 263 | } 264 | if slice == 1 || slideIndex == 0 || slideIndex == slice { 265 | return vertexes 266 | } 267 | 268 | let i = CGFloat(slideIndex) 269 | let s = CGFloat(slice) 270 | 271 | var shifted = vertexes 272 | let first = shifted.remove(at: 0) 273 | shifted.append(first) 274 | 275 | return zip(vertexes, shifted).map { (a, b) -> CGPoint in 276 | CGPoint(x: a.x + (b.x - a.x) / s * i, y: a.y + (b.y - a.y) / s * i) 277 | } 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /SwiftUI/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftUI/WatchLayoutAttributes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import UIKit 24 | import WatchLayout 25 | 26 | public struct WatchLayoutAttributes: Equatable { 27 | public let itemSize: CGFloat 28 | public let spacing: CGFloat 29 | public let minScale: CGFloat 30 | public let nextItemScale: CGFloat 31 | 32 | public init( 33 | itemSize: CGFloat = 100, 34 | spacing: CGFloat = 0, 35 | minScale: CGFloat = 0.2, 36 | nextItemScale: CGFloat = 0.4 37 | ) { 38 | self.itemSize = itemSize 39 | self.spacing = spacing 40 | self.minScale = min(max(minScale, 0), 1) 41 | self.nextItemScale = min(max(nextItemScale, 0), 1) 42 | } 43 | } 44 | 45 | public extension WatchLayout { 46 | func withAttributes(_ layoutAttributes: WatchLayoutAttributes) -> WatchLayout { 47 | let r = WatchLayout() 48 | r.itemSize = layoutAttributes.itemSize 49 | r.spacing = layoutAttributes.spacing 50 | r.minScale = layoutAttributes.minScale 51 | r.nextItemScale = layoutAttributes.nextItemScale 52 | return r 53 | } 54 | 55 | var layoutAttributes: WatchLayoutAttributes { 56 | WatchLayoutAttributes(itemSize: itemSize, 57 | spacing: spacing, 58 | minScale: minScale, 59 | nextItemScale: nextItemScale) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SwiftUI/WatchLayoutUIPresentable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import SwiftUI 24 | import UIKit 25 | import WatchLayout 26 | 27 | class WatchLayoutItemCell: UICollectionViewCell { 28 | 29 | private var hostingViewController: UIHostingController? 30 | 31 | func updateContent(_ content: AnyView) { 32 | if let hostingViewController = hostingViewController { 33 | hostingViewController.view.removeFromSuperview() 34 | hostingViewController.rootView = content 35 | } else { 36 | hostingViewController = UIHostingController(rootView: content) 37 | } 38 | 39 | fitting() 40 | } 41 | 42 | private func fitting() { 43 | guard let view = hostingViewController?.view else { 44 | return 45 | } 46 | 47 | view.backgroundColor = .clear 48 | view.translatesAutoresizingMaskIntoConstraints = false 49 | contentView.addSubview(view) 50 | 51 | NSLayoutConstraint.activate([ 52 | view.topAnchor.constraint(equalTo: contentView.topAnchor), 53 | view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), 54 | view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), 55 | view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), 56 | ]) 57 | } 58 | } 59 | 60 | public class WatchLayoutCoordinator: NSObject, UICollectionViewDataSource, UICollectionViewDelegate { 61 | 62 | let collectionView: UICollectionView 63 | private let cellId = "cell" 64 | private var items: [T] = [] 65 | private let cellContent: (T) -> Content 66 | 67 | init(layoutAtributes: WatchLayoutAttributes, @ViewBuilder cellContent: @escaping (T) -> Content) { 68 | 69 | self.collectionView = UICollectionView(frame: .zero, collectionViewLayout: WatchLayout().withAttributes(layoutAtributes)) 70 | self.cellContent = cellContent 71 | 72 | super.init() 73 | 74 | self.collectionView.register(WatchLayoutItemCell.self, forCellWithReuseIdentifier: cellId) 75 | self.collectionView.dataSource = self 76 | self.collectionView.delegate = self 77 | } 78 | 79 | 80 | func reloadData(_ data: [T], layoutAttributes: WatchLayoutAttributes) { 81 | 82 | let shouldReCenter = items.isEmpty && !data.isEmpty 83 | 84 | items = data 85 | 86 | if let layout = self.collectionView.collectionViewLayout as? WatchLayout, 87 | layout.layoutAttributes != layoutAttributes { 88 | collectionView.collectionViewLayout = WatchLayout().withAttributes(layoutAttributes) 89 | } 90 | collectionView.reloadData() 91 | 92 | if shouldReCenter { 93 | centerToIndexPath(IndexPath(item: 0, section: 0)) 94 | } 95 | } 96 | 97 | func centerToIndexPath(_ idx: IndexPath) { 98 | 99 | guard !items.isEmpty else { 100 | return 101 | } 102 | 103 | let indexPath: IndexPath 104 | 105 | if (0.. Int { 123 | return items.count 124 | } 125 | 126 | public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 127 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! WatchLayoutItemCell 128 | 129 | let ct = cellContent(items[indexPath.item]) 130 | if #available(iOS 14, *) { 131 | cell.updateContent(AnyView(ct.ignoresSafeArea())) 132 | } else { 133 | cell.updateContent(AnyView(ct)) 134 | } 135 | 136 | return cell 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /SwiftUI/WatchLayoutView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2021 Hoc Tran (https://hoctran.com/) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | // 22 | 23 | import SwiftUI 24 | import WatchLayout 25 | 26 | public struct WatchLayoutView: UIViewRepresentable 27 | where Data: RandomAccessCollection, Content: View { 28 | 29 | private let layoutAttributes: WatchLayoutAttributes 30 | 31 | private let data: Binding 32 | private let centeredIndex: Binding? 33 | 34 | private let cellContent: (Data.Element) -> Content 35 | 36 | public func updateUIView(_ uiView: UICollectionView, context: Context) { 37 | context.coordinator.reloadData(Array(data.wrappedValue), layoutAttributes: layoutAttributes) 38 | if let centeredIndex = centeredIndex?.wrappedValue { 39 | context.coordinator.centerToIndexPath(IndexPath(item: data.wrappedValue.distance(from: data.wrappedValue.startIndex, to: centeredIndex), section: 0)) 40 | } 41 | } 42 | 43 | public func makeCoordinator() -> WatchLayoutCoordinator { 44 | WatchLayoutCoordinator(layoutAtributes: layoutAttributes, cellContent: cellContent) 45 | } 46 | 47 | public func makeUIView(context: Context) -> UICollectionView { 48 | context.coordinator.collectionView 49 | } 50 | 51 | /// Creates a view that computes its cells on demand from an underlying 52 | /// collection of data, optionally allowing users to select centered index. 53 | /// 54 | /// - Parameters: 55 | /// - layoutAttributes: WatchLayout configuration. 56 | /// - data: The data for computing the collection. 57 | /// - centeredIndex: A binding to indentify the centered index of the collection 58 | /// - cellContent: A view builder that creates the view for a single cell of the collection. 59 | public init(layoutAttributes: WatchLayoutAttributes = WatchLayoutAttributes(), 60 | data: Binding, 61 | centeredIndex: Binding = .constant(nil), 62 | @ViewBuilder cellContent: @escaping (Data.Element) -> Content) { 63 | self.layoutAttributes = layoutAttributes 64 | self.centeredIndex = centeredIndex 65 | self.data = data 66 | self.cellContent = cellContent 67 | } 68 | } 69 | 70 | 71 | // MARK: - Listing bound Data 72 | 73 | extension WatchLayoutView where Data.Element: Hashable { 74 | 75 | /// Creates a view that computes its cells on demand from an underlying 76 | /// collection of hashable data, optionally allowing users to select centered item. 77 | /// 78 | /// - Parameters: 79 | /// - layoutAttributes: WatchLayout configuration. 80 | /// - data: The data for computing the collection. 81 | /// - centeredItem: A binding to indentify the centered item of the collection 82 | /// - cellContent: A view builder that creates the view for a single cell of the collection. 83 | public init(layoutAttributes: WatchLayoutAttributes = WatchLayoutAttributes(), 84 | data: Binding, 85 | centeredItem: Binding = .constant(nil), 86 | @ViewBuilder cellContent: @escaping (Data.Element) -> Content) { 87 | let centeredIndex: Binding 88 | if let center = centeredItem.wrappedValue, let idx = data.wrappedValue.firstIndex(of: center) { 89 | centeredIndex = .constant(idx) 90 | } else { 91 | centeredIndex = .constant(nil) 92 | } 93 | 94 | self = .init(layoutAttributes: layoutAttributes, data: data, centeredIndex: centeredIndex, cellContent: cellContent) 95 | } 96 | } 97 | 98 | 99 | // MARK: - Listing Data 100 | 101 | extension WatchLayoutView { 102 | 103 | /// Creates a view that computes its cells on demand from an underlying 104 | /// collection of data, optionally allowing users to select centered item. 105 | /// 106 | /// - Parameters: 107 | /// - layoutAttributes: WatchLayout configuration. 108 | /// - data: The data for computing the collection. 109 | /// - centeredItem: A binding to indentify the centered item of the collection 110 | /// - cellContent: A view builder that creates the view for a single cell of the collection. 111 | public init(layoutAttributes: WatchLayoutAttributes = WatchLayoutAttributes(), 112 | data: Data, 113 | centeredIndex: Binding = .constant(nil), 114 | @ViewBuilder cellContent: @escaping (Data.Element) -> Content) { 115 | self = .init(layoutAttributes: layoutAttributes, data: .constant(data), centeredIndex: centeredIndex, cellContent: cellContent) 116 | } 117 | } 118 | 119 | extension WatchLayoutView where Data.Element: Hashable { 120 | 121 | /// Creates a view that computes its cells on demand from an underlying 122 | /// collection of hashable data, optionally allowing users to select centered item. 123 | /// 124 | /// - Parameters: 125 | /// - layoutAttributes: WatchLayout configuration. 126 | /// - data: The data for computing the collection. 127 | /// - centeredItem: A binding to indentify the centered item of the collection 128 | /// - cellContent: A view builder that creates the view for a single cell of the collection. 129 | public init(layoutAttributes: WatchLayoutAttributes = WatchLayoutAttributes(), 130 | data: Data, 131 | centeredItem: Binding, 132 | @ViewBuilder cellContent: @escaping (Data.Element) -> Content) { 133 | self = .init(layoutAttributes: layoutAttributes, data: .constant(data), centeredItem: centeredItem, cellContent: cellContent) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /WatchLayout-SwiftUI.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'WatchLayout-SwiftUI' 3 | s.version = '1.1.0' 4 | s.license = { :type => 'MIT', :file => 'LICENSE' } 5 | s.summary = 'A bubble watch-like like out for UICollectionView' 6 | s.homepage = 'https://github.com/HocTran/WatchLayout' 7 | s.author = { 'Hoc Tran' => 'tranhoc78@gmail.com' } 8 | s.source = { :git => 'https://github.com/HocTran/WatchLayout.git', :tag => s.version.to_s } 9 | 10 | s.ios.deployment_target = '13.0' 11 | 12 | s.source_files = 'SwiftUI/*.swift' 13 | 14 | s.swift_versions = ['5'] 15 | 16 | s.dependency 'WatchLayout', '1.1.0' 17 | end 18 | -------------------------------------------------------------------------------- /WatchLayout.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'WatchLayout' 3 | s.version = '1.1.0' 4 | s.license = { :type => 'MIT', :file => 'LICENSE' } 5 | s.summary = 'A bubble watch-like like out for UICollectionView' 6 | s.homepage = 'https://github.com/HocTran/WatchLayout' 7 | s.author = { 'Hoc Tran' => 'tranhoc78@gmail.com' } 8 | s.source = { :git => 'https://github.com/HocTran/WatchLayout.git', :tag => s.version.to_s } 9 | 10 | s.ios.deployment_target = '13.0' 11 | 12 | s.source_files = 'Source/*.swift' 13 | 14 | s.swift_versions = ['5'] 15 | 16 | end 17 | -------------------------------------------------------------------------------- /WatchLayout.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 156311F826105E9E0033FFF8 /* WatchLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156311F626105E9E0033FFF8 /* WatchLayout.swift */; }; 11 | 4B02528828F3DE9800EC67AA /* WatchLayoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B02528628F3DE9800EC67AA /* WatchLayoutView.swift */; }; 12 | 4B02528A28F3DE9D00EC67AA /* WatchLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156311F626105E9E0033FFF8 /* WatchLayout.swift */; }; 13 | 4BD9DAB3290A5E4300023B17 /* WatchLayoutAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD9DAB2290A5E4300023B17 /* WatchLayoutAttributes.swift */; }; 14 | 4BD9DAB5290A5EA000023B17 /* WatchLayoutUIPresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD9DAB4290A5EA000023B17 /* WatchLayoutUIPresentable.swift */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 156311E626105E710033FFF8 /* WatchLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WatchLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 156311F626105E9E0033FFF8 /* WatchLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchLayout.swift; sourceTree = ""; }; 20 | 156311F726105E9E0033FFF8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 21 | 156311FB26105EB10033FFF8 /* WatchLayout.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = WatchLayout.podspec; sourceTree = ""; }; 22 | 156311FC26105EB10033FFF8 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 23 | 156311FD26105EB10033FFF8 /* Screenshots */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Screenshots; sourceTree = ""; }; 24 | 156311FE26105EB10033FFF8 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 25 | 156311FF26105EB10033FFF8 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 26 | 4B02527E28F3DE8700EC67AA /* WatchLayout_SwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WatchLayout_SwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 4B02528628F3DE9800EC67AA /* WatchLayoutView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchLayoutView.swift; sourceTree = ""; }; 28 | 4B02528728F3DE9800EC67AA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 4B0BF0A228F951A9007CFB54 /* WatchLayout-SwiftUI.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = "WatchLayout-SwiftUI.podspec"; sourceTree = ""; }; 30 | 4BD9DAB2290A5E4300023B17 /* WatchLayoutAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchLayoutAttributes.swift; sourceTree = ""; }; 31 | 4BD9DAB4290A5EA000023B17 /* WatchLayoutUIPresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchLayoutUIPresentable.swift; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 156311E326105E710033FFF8 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | 4B02527B28F3DE8700EC67AA /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | ); 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | /* End PBXFrameworksBuildPhase section */ 50 | 51 | /* Begin PBXGroup section */ 52 | 156311DC26105E710033FFF8 = { 53 | isa = PBXGroup; 54 | children = ( 55 | 156311FC26105EB10033FFF8 /* LICENSE */, 56 | 156311FE26105EB10033FFF8 /* Package.swift */, 57 | 156311FF26105EB10033FFF8 /* README.md */, 58 | 156311FD26105EB10033FFF8 /* Screenshots */, 59 | 156311FB26105EB10033FFF8 /* WatchLayout.podspec */, 60 | 4B0BF0A228F951A9007CFB54 /* WatchLayout-SwiftUI.podspec */, 61 | 156311F526105E9E0033FFF8 /* Source */, 62 | 4B02528528F3DE9800EC67AA /* SwiftUI */, 63 | 156311E726105E710033FFF8 /* Products */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | 156311E726105E710033FFF8 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 156311E626105E710033FFF8 /* WatchLayout.framework */, 71 | 4B02527E28F3DE8700EC67AA /* WatchLayout_SwiftUI.framework */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 156311F526105E9E0033FFF8 /* Source */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 156311F626105E9E0033FFF8 /* WatchLayout.swift */, 80 | 156311F726105E9E0033FFF8 /* Info.plist */, 81 | ); 82 | path = Source; 83 | sourceTree = ""; 84 | }; 85 | 4B02528528F3DE9800EC67AA /* SwiftUI */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 4BD9DAB2290A5E4300023B17 /* WatchLayoutAttributes.swift */, 89 | 4BD9DAB4290A5EA000023B17 /* WatchLayoutUIPresentable.swift */, 90 | 4B02528628F3DE9800EC67AA /* WatchLayoutView.swift */, 91 | 4B02528728F3DE9800EC67AA /* Info.plist */, 92 | ); 93 | path = SwiftUI; 94 | sourceTree = ""; 95 | }; 96 | /* End PBXGroup section */ 97 | 98 | /* Begin PBXHeadersBuildPhase section */ 99 | 156311E126105E710033FFF8 /* Headers */ = { 100 | isa = PBXHeadersBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | 4B02527928F3DE8700EC67AA /* Headers */ = { 107 | isa = PBXHeadersBuildPhase; 108 | buildActionMask = 2147483647; 109 | files = ( 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | /* End PBXHeadersBuildPhase section */ 114 | 115 | /* Begin PBXNativeTarget section */ 116 | 156311E526105E710033FFF8 /* WatchLayout */ = { 117 | isa = PBXNativeTarget; 118 | buildConfigurationList = 156311EE26105E710033FFF8 /* Build configuration list for PBXNativeTarget "WatchLayout" */; 119 | buildPhases = ( 120 | 156311E126105E710033FFF8 /* Headers */, 121 | 156311E226105E710033FFF8 /* Sources */, 122 | 156311E326105E710033FFF8 /* Frameworks */, 123 | 156311E426105E710033FFF8 /* Resources */, 124 | ); 125 | buildRules = ( 126 | ); 127 | dependencies = ( 128 | ); 129 | name = WatchLayout; 130 | productName = WatchLayout; 131 | productReference = 156311E626105E710033FFF8 /* WatchLayout.framework */; 132 | productType = "com.apple.product-type.framework"; 133 | }; 134 | 4B02527D28F3DE8700EC67AA /* WatchLayout-SwiftUI */ = { 135 | isa = PBXNativeTarget; 136 | buildConfigurationList = 4B02528428F3DE8700EC67AA /* Build configuration list for PBXNativeTarget "WatchLayout-SwiftUI" */; 137 | buildPhases = ( 138 | 4B02527928F3DE8700EC67AA /* Headers */, 139 | 4B02527A28F3DE8700EC67AA /* Sources */, 140 | 4B02527B28F3DE8700EC67AA /* Frameworks */, 141 | 4B02527C28F3DE8700EC67AA /* Resources */, 142 | ); 143 | buildRules = ( 144 | ); 145 | dependencies = ( 146 | ); 147 | name = "WatchLayout-SwiftUI"; 148 | productName = "WatchLayout-SwiftUI"; 149 | productReference = 4B02527E28F3DE8700EC67AA /* WatchLayout_SwiftUI.framework */; 150 | productType = "com.apple.product-type.framework"; 151 | }; 152 | /* End PBXNativeTarget section */ 153 | 154 | /* Begin PBXProject section */ 155 | 156311DD26105E710033FFF8 /* Project object */ = { 156 | isa = PBXProject; 157 | attributes = { 158 | LastUpgradeCheck = 1240; 159 | TargetAttributes = { 160 | 156311E526105E710033FFF8 = { 161 | CreatedOnToolsVersion = 12.4; 162 | }; 163 | 4B02527D28F3DE8700EC67AA = { 164 | CreatedOnToolsVersion = 13.4.1; 165 | }; 166 | }; 167 | }; 168 | buildConfigurationList = 156311E026105E710033FFF8 /* Build configuration list for PBXProject "WatchLayout" */; 169 | compatibilityVersion = "Xcode 9.3"; 170 | developmentRegion = en; 171 | hasScannedForEncodings = 0; 172 | knownRegions = ( 173 | en, 174 | Base, 175 | ); 176 | mainGroup = 156311DC26105E710033FFF8; 177 | productRefGroup = 156311E726105E710033FFF8 /* Products */; 178 | projectDirPath = ""; 179 | projectRoot = ""; 180 | targets = ( 181 | 156311E526105E710033FFF8 /* WatchLayout */, 182 | 4B02527D28F3DE8700EC67AA /* WatchLayout-SwiftUI */, 183 | ); 184 | }; 185 | /* End PBXProject section */ 186 | 187 | /* Begin PBXResourcesBuildPhase section */ 188 | 156311E426105E710033FFF8 /* Resources */ = { 189 | isa = PBXResourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | }; 195 | 4B02527C28F3DE8700EC67AA /* Resources */ = { 196 | isa = PBXResourcesBuildPhase; 197 | buildActionMask = 2147483647; 198 | files = ( 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | /* End PBXResourcesBuildPhase section */ 203 | 204 | /* Begin PBXSourcesBuildPhase section */ 205 | 156311E226105E710033FFF8 /* Sources */ = { 206 | isa = PBXSourcesBuildPhase; 207 | buildActionMask = 2147483647; 208 | files = ( 209 | 156311F826105E9E0033FFF8 /* WatchLayout.swift in Sources */, 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | }; 213 | 4B02527A28F3DE8700EC67AA /* Sources */ = { 214 | isa = PBXSourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 4B02528828F3DE9800EC67AA /* WatchLayoutView.swift in Sources */, 218 | 4BD9DAB5290A5EA000023B17 /* WatchLayoutUIPresentable.swift in Sources */, 219 | 4BD9DAB3290A5E4300023B17 /* WatchLayoutAttributes.swift in Sources */, 220 | 4B02528A28F3DE9D00EC67AA /* WatchLayout.swift in Sources */, 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXSourcesBuildPhase section */ 225 | 226 | /* Begin XCBuildConfiguration section */ 227 | 156311EC26105E710033FFF8 /* Debug */ = { 228 | isa = XCBuildConfiguration; 229 | buildSettings = { 230 | ALWAYS_SEARCH_USER_PATHS = NO; 231 | CLANG_ANALYZER_NONNULL = YES; 232 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 233 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 234 | CLANG_CXX_LIBRARY = "libc++"; 235 | CLANG_ENABLE_MODULES = YES; 236 | CLANG_ENABLE_OBJC_ARC = YES; 237 | CLANG_ENABLE_OBJC_WEAK = YES; 238 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 239 | CLANG_WARN_BOOL_CONVERSION = YES; 240 | CLANG_WARN_COMMA = YES; 241 | CLANG_WARN_CONSTANT_CONVERSION = YES; 242 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INFINITE_RECURSION = YES; 248 | CLANG_WARN_INT_CONVERSION = YES; 249 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 250 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 251 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 253 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 254 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 255 | CLANG_WARN_STRICT_PROTOTYPES = YES; 256 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 257 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | COPY_PHASE_STRIP = NO; 261 | CURRENT_PROJECT_VERSION = 1; 262 | DEBUG_INFORMATION_FORMAT = dwarf; 263 | ENABLE_STRICT_OBJC_MSGSEND = YES; 264 | ENABLE_TESTABILITY = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu11; 266 | GCC_DYNAMIC_NO_PIC = NO; 267 | GCC_NO_COMMON_BLOCKS = YES; 268 | GCC_OPTIMIZATION_LEVEL = 0; 269 | GCC_PREPROCESSOR_DEFINITIONS = ( 270 | "DEBUG=1", 271 | "$(inherited)", 272 | ); 273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 274 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 275 | GCC_WARN_UNDECLARED_SELECTOR = YES; 276 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 277 | GCC_WARN_UNUSED_FUNCTION = YES; 278 | GCC_WARN_UNUSED_VARIABLE = YES; 279 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 280 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 281 | MTL_FAST_MATH = YES; 282 | ONLY_ACTIVE_ARCH = YES; 283 | SDKROOT = iphoneos; 284 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 285 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 286 | VERSIONING_SYSTEM = "apple-generic"; 287 | VERSION_INFO_PREFIX = ""; 288 | }; 289 | name = Debug; 290 | }; 291 | 156311ED26105E710033FFF8 /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ALWAYS_SEARCH_USER_PATHS = NO; 295 | CLANG_ANALYZER_NONNULL = YES; 296 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 297 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 298 | CLANG_CXX_LIBRARY = "libc++"; 299 | CLANG_ENABLE_MODULES = YES; 300 | CLANG_ENABLE_OBJC_ARC = YES; 301 | CLANG_ENABLE_OBJC_WEAK = YES; 302 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 303 | CLANG_WARN_BOOL_CONVERSION = YES; 304 | CLANG_WARN_COMMA = YES; 305 | CLANG_WARN_CONSTANT_CONVERSION = YES; 306 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 307 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 308 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 309 | CLANG_WARN_EMPTY_BODY = YES; 310 | CLANG_WARN_ENUM_CONVERSION = YES; 311 | CLANG_WARN_INFINITE_RECURSION = YES; 312 | CLANG_WARN_INT_CONVERSION = YES; 313 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 314 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 315 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 316 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 317 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 318 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 319 | CLANG_WARN_STRICT_PROTOTYPES = YES; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 322 | CLANG_WARN_UNREACHABLE_CODE = YES; 323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 324 | COPY_PHASE_STRIP = NO; 325 | CURRENT_PROJECT_VERSION = 1; 326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 327 | ENABLE_NS_ASSERTIONS = NO; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | GCC_C_LANGUAGE_STANDARD = gnu11; 330 | GCC_NO_COMMON_BLOCKS = YES; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | IPHONEOS_DEPLOYMENT_TARGET = 14.4; 338 | MTL_ENABLE_DEBUG_INFO = NO; 339 | MTL_FAST_MATH = YES; 340 | SDKROOT = iphoneos; 341 | SWIFT_COMPILATION_MODE = wholemodule; 342 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 343 | VALIDATE_PRODUCT = YES; 344 | VERSIONING_SYSTEM = "apple-generic"; 345 | VERSION_INFO_PREFIX = ""; 346 | }; 347 | name = Release; 348 | }; 349 | 156311EF26105E710033FFF8 /* Debug */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | CODE_SIGN_STYLE = Automatic; 353 | DEFINES_MODULE = YES; 354 | DYLIB_COMPATIBILITY_VERSION = 1; 355 | DYLIB_CURRENT_VERSION = 1; 356 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 357 | INFOPLIST_FILE = Source/Info.plist; 358 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 359 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 360 | LD_RUNPATH_SEARCH_PATHS = ( 361 | "$(inherited)", 362 | "@executable_path/Frameworks", 363 | "@loader_path/Frameworks", 364 | ); 365 | PRODUCT_BUNDLE_IDENTIFIER = "Hoc-Tran.WatchLayout"; 366 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 367 | SKIP_INSTALL = YES; 368 | SWIFT_VERSION = 5.0; 369 | TARGETED_DEVICE_FAMILY = "1,2"; 370 | }; 371 | name = Debug; 372 | }; 373 | 156311F026105E710033FFF8 /* Release */ = { 374 | isa = XCBuildConfiguration; 375 | buildSettings = { 376 | CODE_SIGN_STYLE = Automatic; 377 | DEFINES_MODULE = YES; 378 | DYLIB_COMPATIBILITY_VERSION = 1; 379 | DYLIB_CURRENT_VERSION = 1; 380 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 381 | INFOPLIST_FILE = Source/Info.plist; 382 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 383 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 384 | LD_RUNPATH_SEARCH_PATHS = ( 385 | "$(inherited)", 386 | "@executable_path/Frameworks", 387 | "@loader_path/Frameworks", 388 | ); 389 | PRODUCT_BUNDLE_IDENTIFIER = "Hoc-Tran.WatchLayout"; 390 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 391 | SKIP_INSTALL = YES; 392 | SWIFT_VERSION = 5.0; 393 | TARGETED_DEVICE_FAMILY = "1,2"; 394 | }; 395 | name = Release; 396 | }; 397 | 4B02528228F3DE8700EC67AA /* Debug */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 401 | CODE_SIGN_STYLE = Automatic; 402 | CURRENT_PROJECT_VERSION = 1; 403 | DEFINES_MODULE = YES; 404 | DYLIB_COMPATIBILITY_VERSION = 1; 405 | DYLIB_CURRENT_VERSION = 1; 406 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 407 | GENERATE_INFOPLIST_FILE = YES; 408 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 409 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 410 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 411 | LD_RUNPATH_SEARCH_PATHS = ( 412 | "$(inherited)", 413 | "@executable_path/Frameworks", 414 | "@loader_path/Frameworks", 415 | ); 416 | MARKETING_VERSION = 1.0; 417 | PRODUCT_BUNDLE_IDENTIFIER = "dev.ht.WatchLayout-SwiftUI"; 418 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 419 | SKIP_INSTALL = YES; 420 | SWIFT_EMIT_LOC_STRINGS = YES; 421 | SWIFT_VERSION = 5.0; 422 | TARGETED_DEVICE_FAMILY = "1,2"; 423 | }; 424 | name = Debug; 425 | }; 426 | 4B02528328F3DE8700EC67AA /* Release */ = { 427 | isa = XCBuildConfiguration; 428 | buildSettings = { 429 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 430 | CODE_SIGN_STYLE = Automatic; 431 | CURRENT_PROJECT_VERSION = 1; 432 | DEFINES_MODULE = YES; 433 | DYLIB_COMPATIBILITY_VERSION = 1; 434 | DYLIB_CURRENT_VERSION = 1; 435 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 436 | GENERATE_INFOPLIST_FILE = YES; 437 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 438 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 439 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 440 | LD_RUNPATH_SEARCH_PATHS = ( 441 | "$(inherited)", 442 | "@executable_path/Frameworks", 443 | "@loader_path/Frameworks", 444 | ); 445 | MARKETING_VERSION = 1.0; 446 | PRODUCT_BUNDLE_IDENTIFIER = "dev.ht.WatchLayout-SwiftUI"; 447 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 448 | SKIP_INSTALL = YES; 449 | SWIFT_EMIT_LOC_STRINGS = YES; 450 | SWIFT_VERSION = 5.0; 451 | TARGETED_DEVICE_FAMILY = "1,2"; 452 | }; 453 | name = Release; 454 | }; 455 | /* End XCBuildConfiguration section */ 456 | 457 | /* Begin XCConfigurationList section */ 458 | 156311E026105E710033FFF8 /* Build configuration list for PBXProject "WatchLayout" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 156311EC26105E710033FFF8 /* Debug */, 462 | 156311ED26105E710033FFF8 /* Release */, 463 | ); 464 | defaultConfigurationIsVisible = 0; 465 | defaultConfigurationName = Release; 466 | }; 467 | 156311EE26105E710033FFF8 /* Build configuration list for PBXNativeTarget "WatchLayout" */ = { 468 | isa = XCConfigurationList; 469 | buildConfigurations = ( 470 | 156311EF26105E710033FFF8 /* Debug */, 471 | 156311F026105E710033FFF8 /* Release */, 472 | ); 473 | defaultConfigurationIsVisible = 0; 474 | defaultConfigurationName = Release; 475 | }; 476 | 4B02528428F3DE8700EC67AA /* Build configuration list for PBXNativeTarget "WatchLayout-SwiftUI" */ = { 477 | isa = XCConfigurationList; 478 | buildConfigurations = ( 479 | 4B02528228F3DE8700EC67AA /* Debug */, 480 | 4B02528328F3DE8700EC67AA /* Release */, 481 | ); 482 | defaultConfigurationIsVisible = 0; 483 | defaultConfigurationName = Release; 484 | }; 485 | /* End XCConfigurationList section */ 486 | }; 487 | rootObject = 156311DD26105E710033FFF8 /* Project object */; 488 | } 489 | -------------------------------------------------------------------------------- /WatchLayout.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /WatchLayout.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------