├── .gitignore ├── .swift-version ├── FloatingActionSheetController-Demo ├── FloatingActionSheetController-Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── FloatingActionSheetController-Demo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── HeaderView.swift │ ├── Info.plist │ ├── TableViewCell.swift │ ├── TableViewCell.xib │ └── ViewController.swift ├── FloatingActionSheetController.podspec ├── FloatingActionSheetController.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── FloatingActionSheetController.xcscheme ├── FloatingActionSheetController ├── FloatingAction.swift ├── FloatingActionGroup.swift ├── FloatingActionSheetController.h ├── FloatingActionSheetController.swift └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | #CocoaPods 20 | Pods 21 | Tests/Pods 22 | Tests/Podfile.lock 23 | Examples/Objective-C/Podfile.lock 24 | Examples/Swift/Podfile.lock 25 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2A2B1B051BE0D00F00445855 /* TableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2A2B1B041BE0D00F00445855 /* TableViewCell.xib */; }; 11 | 2A4B956B1BDC323400148B08 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A4B956A1BDC323400148B08 /* AppDelegate.swift */; }; 12 | 2A4B956D1BDC323400148B08 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A4B956C1BDC323400148B08 /* ViewController.swift */; }; 13 | 2A4B95721BDC323400148B08 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2A4B95711BDC323400148B08 /* Assets.xcassets */; }; 14 | 2A4B95751BDC323400148B08 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2A4B95731BDC323400148B08 /* LaunchScreen.storyboard */; }; 15 | 2A5C433E1BE0D2AB0041B69B /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C433D1BE0D2AB0041B69B /* TableViewCell.swift */; }; 16 | 2A754A8D1BE0EC21004ADAC8 /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A754A8C1BE0EC21004ADAC8 /* HeaderView.swift */; }; 17 | 2A8281401BDC492200F06E1F /* FloatingActionSheetController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A8281381BDC333E00F06E1F /* FloatingActionSheetController.framework */; }; 18 | 2A8281411BDC492200F06E1F /* FloatingActionSheetController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2A8281381BDC333E00F06E1F /* FloatingActionSheetController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 2A8281371BDC333E00F06E1F /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 2A8281331BDC333E00F06E1F /* FloatingActionSheetController.xcodeproj */; 25 | proxyType = 2; 26 | remoteGlobalIDString = 2A4B95531BDC31FA00148B08; 27 | remoteInfo = FloatingActionSheetController; 28 | }; 29 | 2A8281421BDC492200F06E1F /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 2A8281331BDC333E00F06E1F /* FloatingActionSheetController.xcodeproj */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 2A4B95521BDC31FA00148B08; 34 | remoteInfo = FloatingActionSheetController; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXCopyFilesBuildPhase section */ 39 | 2A8281441BDC492200F06E1F /* Embed Frameworks */ = { 40 | isa = PBXCopyFilesBuildPhase; 41 | buildActionMask = 2147483647; 42 | dstPath = ""; 43 | dstSubfolderSpec = 10; 44 | files = ( 45 | 2A8281411BDC492200F06E1F /* FloatingActionSheetController.framework in Embed Frameworks */, 46 | ); 47 | name = "Embed Frameworks"; 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | /* End PBXCopyFilesBuildPhase section */ 51 | 52 | /* Begin PBXFileReference section */ 53 | 2A2B1B041BE0D00F00445855 /* TableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TableViewCell.xib; sourceTree = ""; }; 54 | 2A4B95671BDC323400148B08 /* FloatingActionSheetController-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "FloatingActionSheetController-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 2A4B956A1BDC323400148B08 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 56 | 2A4B956C1BDC323400148B08 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 57 | 2A4B95711BDC323400148B08 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 2A4B95741BDC323400148B08 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | 2A4B95761BDC323400148B08 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 2A5C433D1BE0D2AB0041B69B /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = ""; }; 61 | 2A754A8C1BE0EC21004ADAC8 /* HeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; }; 62 | 2A8281331BDC333E00F06E1F /* FloatingActionSheetController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FloatingActionSheetController.xcodeproj; path = ../FloatingActionSheetController.xcodeproj; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | 2A4B95641BDC323400148B08 /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | 2A8281401BDC492200F06E1F /* FloatingActionSheetController.framework in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | 2A4B955E1BDC323400148B08 = { 78 | isa = PBXGroup; 79 | children = ( 80 | 2A8281331BDC333E00F06E1F /* FloatingActionSheetController.xcodeproj */, 81 | 2A4B95691BDC323400148B08 /* FloatingActionSheetController-Demo */, 82 | 2A4B95681BDC323400148B08 /* Products */, 83 | ); 84 | sourceTree = ""; 85 | }; 86 | 2A4B95681BDC323400148B08 /* Products */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 2A4B95671BDC323400148B08 /* FloatingActionSheetController-Demo.app */, 90 | ); 91 | name = Products; 92 | sourceTree = ""; 93 | }; 94 | 2A4B95691BDC323400148B08 /* FloatingActionSheetController-Demo */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 2A4B956A1BDC323400148B08 /* AppDelegate.swift */, 98 | 2A4B956C1BDC323400148B08 /* ViewController.swift */, 99 | 2A5C433D1BE0D2AB0041B69B /* TableViewCell.swift */, 100 | 2A2B1B041BE0D00F00445855 /* TableViewCell.xib */, 101 | 2A754A8C1BE0EC21004ADAC8 /* HeaderView.swift */, 102 | 2A4B95711BDC323400148B08 /* Assets.xcassets */, 103 | 2A4B95731BDC323400148B08 /* LaunchScreen.storyboard */, 104 | 2A4B95761BDC323400148B08 /* Info.plist */, 105 | ); 106 | path = "FloatingActionSheetController-Demo"; 107 | sourceTree = ""; 108 | }; 109 | 2A8281341BDC333E00F06E1F /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 2A8281381BDC333E00F06E1F /* FloatingActionSheetController.framework */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | /* End PBXGroup section */ 118 | 119 | /* Begin PBXNativeTarget section */ 120 | 2A4B95661BDC323400148B08 /* FloatingActionSheetController-Demo */ = { 121 | isa = PBXNativeTarget; 122 | buildConfigurationList = 2A4B95791BDC323400148B08 /* Build configuration list for PBXNativeTarget "FloatingActionSheetController-Demo" */; 123 | buildPhases = ( 124 | 2A4B95631BDC323400148B08 /* Sources */, 125 | 2A4B95641BDC323400148B08 /* Frameworks */, 126 | 2A4B95651BDC323400148B08 /* Resources */, 127 | 2A8281441BDC492200F06E1F /* Embed Frameworks */, 128 | ); 129 | buildRules = ( 130 | ); 131 | dependencies = ( 132 | 2A8281431BDC492200F06E1F /* PBXTargetDependency */, 133 | ); 134 | name = "FloatingActionSheetController-Demo"; 135 | productName = "FloatingActionSheetController-Demo"; 136 | productReference = 2A4B95671BDC323400148B08 /* FloatingActionSheetController-Demo.app */; 137 | productType = "com.apple.product-type.application"; 138 | }; 139 | /* End PBXNativeTarget section */ 140 | 141 | /* Begin PBXProject section */ 142 | 2A4B955F1BDC323400148B08 /* Project object */ = { 143 | isa = PBXProject; 144 | attributes = { 145 | LastUpgradeCheck = 0900; 146 | ORGANIZATIONNAME = "Ryo Aoyama"; 147 | TargetAttributes = { 148 | 2A4B95661BDC323400148B08 = { 149 | CreatedOnToolsVersion = 7.0; 150 | LastSwiftMigration = 0900; 151 | ProvisioningStyle = Manual; 152 | }; 153 | }; 154 | }; 155 | buildConfigurationList = 2A4B95621BDC323400148B08 /* Build configuration list for PBXProject "FloatingActionSheetController-Demo" */; 156 | compatibilityVersion = "Xcode 3.2"; 157 | developmentRegion = English; 158 | hasScannedForEncodings = 0; 159 | knownRegions = ( 160 | en, 161 | Base, 162 | ); 163 | mainGroup = 2A4B955E1BDC323400148B08; 164 | productRefGroup = 2A4B95681BDC323400148B08 /* Products */; 165 | projectDirPath = ""; 166 | projectReferences = ( 167 | { 168 | ProductGroup = 2A8281341BDC333E00F06E1F /* Products */; 169 | ProjectRef = 2A8281331BDC333E00F06E1F /* FloatingActionSheetController.xcodeproj */; 170 | }, 171 | ); 172 | projectRoot = ""; 173 | targets = ( 174 | 2A4B95661BDC323400148B08 /* FloatingActionSheetController-Demo */, 175 | ); 176 | }; 177 | /* End PBXProject section */ 178 | 179 | /* Begin PBXReferenceProxy section */ 180 | 2A8281381BDC333E00F06E1F /* FloatingActionSheetController.framework */ = { 181 | isa = PBXReferenceProxy; 182 | fileType = wrapper.framework; 183 | path = FloatingActionSheetController.framework; 184 | remoteRef = 2A8281371BDC333E00F06E1F /* PBXContainerItemProxy */; 185 | sourceTree = BUILT_PRODUCTS_DIR; 186 | }; 187 | /* End PBXReferenceProxy section */ 188 | 189 | /* Begin PBXResourcesBuildPhase section */ 190 | 2A4B95651BDC323400148B08 /* Resources */ = { 191 | isa = PBXResourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | 2A4B95751BDC323400148B08 /* LaunchScreen.storyboard in Resources */, 195 | 2A2B1B051BE0D00F00445855 /* TableViewCell.xib in Resources */, 196 | 2A4B95721BDC323400148B08 /* Assets.xcassets in Resources */, 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | }; 200 | /* End PBXResourcesBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 2A4B95631BDC323400148B08 /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 2A5C433E1BE0D2AB0041B69B /* TableViewCell.swift in Sources */, 208 | 2A4B956D1BDC323400148B08 /* ViewController.swift in Sources */, 209 | 2A4B956B1BDC323400148B08 /* AppDelegate.swift in Sources */, 210 | 2A754A8D1BE0EC21004ADAC8 /* HeaderView.swift in Sources */, 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | /* End PBXSourcesBuildPhase section */ 215 | 216 | /* Begin PBXTargetDependency section */ 217 | 2A8281431BDC492200F06E1F /* PBXTargetDependency */ = { 218 | isa = PBXTargetDependency; 219 | name = FloatingActionSheetController; 220 | targetProxy = 2A8281421BDC492200F06E1F /* PBXContainerItemProxy */; 221 | }; 222 | /* End PBXTargetDependency section */ 223 | 224 | /* Begin PBXVariantGroup section */ 225 | 2A4B95731BDC323400148B08 /* LaunchScreen.storyboard */ = { 226 | isa = PBXVariantGroup; 227 | children = ( 228 | 2A4B95741BDC323400148B08 /* Base */, 229 | ); 230 | name = LaunchScreen.storyboard; 231 | sourceTree = ""; 232 | }; 233 | /* End PBXVariantGroup section */ 234 | 235 | /* Begin XCBuildConfiguration section */ 236 | 2A4B95771BDC323400148B08 /* Debug */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | ALWAYS_SEARCH_USER_PATHS = NO; 240 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 241 | CLANG_CXX_LIBRARY = "libc++"; 242 | CLANG_ENABLE_MODULES = YES; 243 | CLANG_ENABLE_OBJC_ARC = YES; 244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 245 | CLANG_WARN_BOOL_CONVERSION = YES; 246 | CLANG_WARN_COMMA = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 256 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 257 | CLANG_WARN_STRICT_PROTOTYPES = YES; 258 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 259 | CLANG_WARN_UNREACHABLE_CODE = YES; 260 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 261 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 262 | COPY_PHASE_STRIP = NO; 263 | DEBUG_INFORMATION_FORMAT = dwarf; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | ENABLE_TESTABILITY = YES; 266 | GCC_C_LANGUAGE_STANDARD = gnu99; 267 | GCC_DYNAMIC_NO_PIC = NO; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_OPTIMIZATION_LEVEL = 0; 270 | GCC_PREPROCESSOR_DEFINITIONS = ( 271 | "DEBUG=1", 272 | "$(inherited)", 273 | ); 274 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 275 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 276 | GCC_WARN_UNDECLARED_SELECTOR = YES; 277 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 278 | GCC_WARN_UNUSED_FUNCTION = YES; 279 | GCC_WARN_UNUSED_VARIABLE = YES; 280 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 281 | MTL_ENABLE_DEBUG_INFO = YES; 282 | ONLY_ACTIVE_ARCH = YES; 283 | SDKROOT = iphoneos; 284 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 285 | }; 286 | name = Debug; 287 | }; 288 | 2A4B95781BDC323400148B08 /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 293 | CLANG_CXX_LIBRARY = "libc++"; 294 | CLANG_ENABLE_MODULES = YES; 295 | CLANG_ENABLE_OBJC_ARC = YES; 296 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 297 | CLANG_WARN_BOOL_CONVERSION = YES; 298 | CLANG_WARN_COMMA = YES; 299 | CLANG_WARN_CONSTANT_CONVERSION = YES; 300 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 301 | CLANG_WARN_EMPTY_BODY = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INFINITE_RECURSION = YES; 304 | CLANG_WARN_INT_CONVERSION = YES; 305 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 306 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 307 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 308 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 309 | CLANG_WARN_STRICT_PROTOTYPES = YES; 310 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 311 | CLANG_WARN_UNREACHABLE_CODE = YES; 312 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 313 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 314 | COPY_PHASE_STRIP = NO; 315 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 316 | ENABLE_NS_ASSERTIONS = NO; 317 | ENABLE_STRICT_OBJC_MSGSEND = YES; 318 | GCC_C_LANGUAGE_STANDARD = gnu99; 319 | GCC_NO_COMMON_BLOCKS = YES; 320 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 322 | GCC_WARN_UNDECLARED_SELECTOR = YES; 323 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 324 | GCC_WARN_UNUSED_FUNCTION = YES; 325 | GCC_WARN_UNUSED_VARIABLE = YES; 326 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 327 | MTL_ENABLE_DEBUG_INFO = NO; 328 | SDKROOT = iphoneos; 329 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 330 | VALIDATE_PRODUCT = YES; 331 | }; 332 | name = Release; 333 | }; 334 | 2A4B957A1BDC323400148B08 /* Debug */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 338 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 339 | DEVELOPMENT_TEAM = ""; 340 | INFOPLIST_FILE = "FloatingActionSheetController-Demo/Info.plist"; 341 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 342 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 343 | PRODUCT_BUNDLE_IDENTIFIER = "com.ryo.FloatingActionSheetController-Demo"; 344 | PRODUCT_NAME = "$(TARGET_NAME)"; 345 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 346 | SWIFT_VERSION = 4.0; 347 | }; 348 | name = Debug; 349 | }; 350 | 2A4B957B1BDC323400148B08 /* Release */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 354 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 355 | DEVELOPMENT_TEAM = ""; 356 | INFOPLIST_FILE = "FloatingActionSheetController-Demo/Info.plist"; 357 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 358 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 359 | PRODUCT_BUNDLE_IDENTIFIER = "com.ryo.FloatingActionSheetController-Demo"; 360 | PRODUCT_NAME = "$(TARGET_NAME)"; 361 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 362 | SWIFT_VERSION = 4.0; 363 | }; 364 | name = Release; 365 | }; 366 | /* End XCBuildConfiguration section */ 367 | 368 | /* Begin XCConfigurationList section */ 369 | 2A4B95621BDC323400148B08 /* Build configuration list for PBXProject "FloatingActionSheetController-Demo" */ = { 370 | isa = XCConfigurationList; 371 | buildConfigurations = ( 372 | 2A4B95771BDC323400148B08 /* Debug */, 373 | 2A4B95781BDC323400148B08 /* Release */, 374 | ); 375 | defaultConfigurationIsVisible = 0; 376 | defaultConfigurationName = Release; 377 | }; 378 | 2A4B95791BDC323400148B08 /* Build configuration list for PBXNativeTarget "FloatingActionSheetController-Demo" */ = { 379 | isa = XCConfigurationList; 380 | buildConfigurations = ( 381 | 2A4B957A1BDC323400148B08 /* Debug */, 382 | 2A4B957B1BDC323400148B08 /* Release */, 383 | ); 384 | defaultConfigurationIsVisible = 0; 385 | defaultConfigurationName = Release; 386 | }; 387 | /* End XCConfigurationList section */ 388 | }; 389 | rootObject = 2A4B955F1BDC323400148B08 /* Project object */; 390 | } 391 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FloatingActionSheetController-Demo 4 | // 5 | // Created by Ryo Aoyama on 10/25/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 17 | configure() 18 | return true 19 | } 20 | 21 | fileprivate func configure() { 22 | UIApplication.shared.statusBarStyle = .lightContent 23 | let nav = UINavigationController(rootViewController: ViewController()) 24 | let navBar = nav.navigationBar 25 | navBar.tintColor = .white 26 | navBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white] 27 | navBar.isTranslucent = false 28 | navBar.shadowImage = UIImage() 29 | navBar.barTintColor = UIColor(red:0.09, green:0.11, blue:0.13, alpha:1) 30 | let window = UIWindow(frame: UIScreen.main.bounds) 31 | window.rootViewController = nav 32 | window.makeKeyAndVisible() 33 | self.window = window 34 | } 35 | 36 | func applicationWillResignActive(_ application: UIApplication) { 37 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 38 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 39 | } 40 | 41 | func applicationDidEnterBackground(_ application: UIApplication) { 42 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 43 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 44 | } 45 | 46 | func applicationWillEnterForeground(_ application: UIApplication) { 47 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 48 | } 49 | 50 | func applicationDidBecomeActive(_ application: UIApplication) { 51 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 52 | } 53 | 54 | func applicationWillTerminate(_ application: UIApplication) { 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 38 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/HeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeaderView.swift 3 | // FloatingActionSheetController-Demo 4 | // 5 | // Created by Ryo Aoyama on 10/28/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class HeaderView: UITableViewHeaderFooterView { 12 | 13 | // MARK: Public 14 | 15 | var title: String? { 16 | get { 17 | return titleLabel.text 18 | } 19 | set { 20 | titleLabel.text = newValue 21 | } 22 | } 23 | 24 | override init(reuseIdentifier: String?) { 25 | super.init(reuseIdentifier: reuseIdentifier) 26 | configure() 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:) has not been implemented") 31 | } 32 | 33 | // MARK: Private 34 | 35 | fileprivate weak var titleLabel: UILabel! 36 | 37 | fileprivate func configure() { 38 | contentView.backgroundColor = UIColor(red:0.11, green:0.12, blue:0.15, alpha:1) 39 | 40 | let titleLabel = UILabel() 41 | titleLabel.textAlignment = .center 42 | titleLabel.textColor = UIColor(white: 1, alpha: 0.8) 43 | titleLabel.font = .systemFont(ofSize: 16) 44 | titleLabel.translatesAutoresizingMaskIntoConstraints = false 45 | contentView.addSubview(titleLabel) 46 | self.titleLabel = titleLabel 47 | 48 | contentView.addConstraints( 49 | NSLayoutConstraint.constraints( 50 | withVisualFormat: "V:|-0-[label]-0-|", 51 | options: [], 52 | metrics: nil, 53 | views: ["label": titleLabel] 54 | ) 55 | + NSLayoutConstraint.constraints( 56 | withVisualFormat: "H:|-0-[label]-0-|", 57 | options: [], 58 | metrics: nil, 59 | views: ["label": titleLabel] 60 | ) 61 | ) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UIViewControllerBasedStatusBarAppearance 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/TableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.swift 3 | // FloatingActionSheetController-Demo 4 | // 5 | // Created by Ryo Aoyama on 10/28/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class TableViewCell: UITableViewCell { 12 | 13 | // MARK: Public 14 | 15 | var title: String? { 16 | get { 17 | return titleLabel.text 18 | } 19 | set { 20 | titleLabel.text = newValue 21 | } 22 | } 23 | 24 | override func awakeFromNib() { 25 | super.awakeFromNib() 26 | contentView.backgroundColor = UIColor(red:0.14, green:0.16, blue:0.2, alpha:1) 27 | let selectedBackgroundView = UIView() 28 | selectedBackgroundView.backgroundColor = UIColor(red:0.11, green:0.12, blue:0.15, alpha:1) 29 | self.selectedBackgroundView = selectedBackgroundView 30 | } 31 | 32 | // MARK: Private 33 | 34 | @IBOutlet fileprivate weak var titleLabel: UILabel! 35 | } 36 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/TableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /FloatingActionSheetController-Demo/FloatingActionSheetController-Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // FloatingActionSheetController-Demo 4 | // 5 | // Created by Ryo Aoyama on 10/25/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import FloatingActionSheetController 11 | 12 | class ViewController: UIViewController { 13 | 14 | // MARK: Public 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | configure() 19 | configureDataSources() 20 | } 21 | 22 | // MARK: Private 23 | 24 | fileprivate class PaddingLabel: UILabel { 25 | fileprivate override func drawText(in rect: CGRect) { 26 | let insets = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) 27 | super.drawText(in: UIEdgeInsetsInsetRect(rect, insets)) 28 | } 29 | } 30 | 31 | fileprivate struct RowData { 32 | var title: String? 33 | var handler: (() -> Void)? 34 | } 35 | fileprivate struct DataSource { 36 | var sectionTitle: String? 37 | var rowDatas = [RowData]() 38 | } 39 | 40 | fileprivate var dataSources = [DataSource]() 41 | fileprivate weak var displayLabel: UILabel! 42 | 43 | fileprivate func configure() { 44 | title = "Examples" 45 | view.backgroundColor = UIColor(red:0.14, green:0.16, blue:0.2, alpha:1) 46 | 47 | let displayLabel = PaddingLabel(frame: CGRect(x: 0, y: 0, width: 0, height: 50)) 48 | displayLabel.backgroundColor = UIColor(red:0.93, green:0.95, blue:0.96, alpha:1) 49 | displayLabel.text = "Select example from below." 50 | displayLabel.textColor = UIColor(red:0.48, green:0.52, blue:0.58, alpha:1) 51 | displayLabel.font = .boldSystemFont(ofSize: 14) 52 | 53 | let tableView = UITableView(frame: .zero, style: .grouped) 54 | tableView.tableHeaderView = displayLabel 55 | tableView.backgroundColor = .clear 56 | tableView.showsHorizontalScrollIndicator = false 57 | tableView.showsVerticalScrollIndicator = false 58 | tableView.delaysContentTouches = false 59 | tableView.separatorStyle = .none 60 | tableView.delegate = self 61 | tableView.dataSource = self 62 | tableView.register(HeaderView.self, forHeaderFooterViewReuseIdentifier: "HeaderView") 63 | tableView.register(UINib(nibName: "TableViewCell", bundle: Bundle.main), forCellReuseIdentifier: "TableViewCell") 64 | tableView.translatesAutoresizingMaskIntoConstraints = false 65 | view.addSubview(tableView) 66 | self.displayLabel = displayLabel 67 | 68 | view.addConstraints( 69 | NSLayoutConstraint.constraints( 70 | withVisualFormat: "V:|-0-[tableView]-0-|", 71 | options: [], 72 | metrics: nil, 73 | views: ["tableView": tableView] 74 | ) 75 | + NSLayoutConstraint.constraints( 76 | withVisualFormat: "H:|-0-[tableView]-0-|", 77 | options: [], 78 | metrics: nil, 79 | views: ["tableView": tableView] 80 | ) 81 | ) 82 | } 83 | 84 | fileprivate func configureDataSources() { 85 | var standardRows = [RowData]() 86 | standardRows.append( 87 | RowData(title: "2 : 1") { [weak self] in 88 | if let sSelf = self { 89 | let group1 = FloatingActionGroup(actions: 90 | (1...2).map { 91 | FloatingAction(title: "Action\($0)") { 92 | sSelf.display($0) 93 | } 94 | } 95 | ) 96 | let group2 = FloatingActionGroup(action: 97 | FloatingAction(title: "Action3") { 98 | sSelf.display($0) 99 | } 100 | ) 101 | FloatingActionSheetController(actionGroup: group1, group2) 102 | .present(in: sSelf) 103 | } 104 | } 105 | ) 106 | standardRows.append( 107 | RowData(title: "1 : 4") { [weak self] in 108 | if let sSelf = self { 109 | let group1 = FloatingActionGroup(action: 110 | FloatingAction(title: "Action1") { 111 | sSelf.display($0) 112 | } 113 | ) 114 | let group2 = FloatingActionGroup(actions: 115 | (2...5).map { 116 | FloatingAction(title: "Action\($0)") { 117 | sSelf.display($0) 118 | } 119 | } 120 | ) 121 | FloatingActionSheetController(actionGroup: group1, group2) 122 | .present(in: sSelf) 123 | } 124 | } 125 | ) 126 | standardRows.append( 127 | RowData(title: "1 : 3 : 1") { [weak self] in 128 | if let sSelf = self { 129 | let group1 = FloatingActionGroup(action: 130 | FloatingAction(title: "Action1") { 131 | sSelf.display($0) 132 | } 133 | ) 134 | let group2 = FloatingActionGroup(actions: 135 | (2...4).map { 136 | FloatingAction(title: "Action\($0)") { 137 | sSelf.display($0) 138 | } 139 | } 140 | ) 141 | let group3 = FloatingActionGroup(action: 142 | FloatingAction(title: "Action5") { 143 | sSelf.display($0) 144 | } 145 | ) 146 | FloatingActionSheetController(actionGroup: group1, group2, group3) 147 | .present(in: sSelf) 148 | } 149 | } 150 | ) 151 | standardRows.append( 152 | RowData(title: "2 : 2 : 2") { [weak self] in 153 | if let sSelf = self { 154 | let group1 = FloatingActionGroup(actions: 155 | (1...2).map { 156 | FloatingAction(title: "Action\($0)") { 157 | sSelf.display($0) 158 | } 159 | } 160 | ) 161 | let group2 = FloatingActionGroup(actions: 162 | (3...4).map { 163 | FloatingAction(title: "Action\($0)") { 164 | sSelf.display($0) 165 | } 166 | } 167 | ) 168 | let group3 = FloatingActionGroup(actions: 169 | (5...6).map { 170 | FloatingAction(title: "Action\($0)") { 171 | sSelf.display($0) 172 | } 173 | } 174 | ) 175 | FloatingActionSheetController(actionGroup: group1, group2, group3) 176 | .present(in: sSelf) 177 | } 178 | } 179 | ) 180 | dataSources.append( 181 | DataSource(sectionTitle: "Standard", rowDatas: standardRows) 182 | ) 183 | 184 | typealias Component = (String, FloatingActionSheetController.AnimationStyle) 185 | let components: [Component] = [ 186 | ("SlideUp", .slideUp), 187 | ("SlideDown", .slideDown), 188 | ("SlideLeft", .slideLeft), 189 | ("SlideRight", .slideRight), 190 | ("Pop", .pop) 191 | ] 192 | 193 | let animationRows: [RowData] = components.map { title, style in 194 | RowData(title: title) { [weak self] in 195 | if let sSelf = self { 196 | let vc = FloatingActionSheetController( 197 | actionGroups: sSelf.exampleActionGroups(), 198 | animationStyle: style 199 | ) 200 | vc.present(in: sSelf) 201 | } 202 | } 203 | } 204 | 205 | dataSources.append( 206 | DataSource(sectionTitle: "Animation", rowDatas: animationRows) 207 | ) 208 | 209 | let tintRow = RowData(title: "Tint color") { [weak self] in 210 | if let sSelf = self { 211 | let actionSheet = FloatingActionSheetController(actionGroups: sSelf.exampleActionGroups()) 212 | actionSheet.itemTintColor = UIColor(red:0.93, green:0.95, blue:0.96, alpha:1) 213 | actionSheet.textColor = UIColor(red:0.48, green:0.52, blue:0.58, alpha:1) 214 | actionSheet.present(in: sSelf) 215 | } 216 | } 217 | let textColorRow = RowData(title: "Text color") { [weak self] in 218 | if let sSelf = self { 219 | let actionSheet = FloatingActionSheetController(actionGroups: sSelf.exampleActionGroups()) 220 | actionSheet.textColor = UIColor(red: 0.9, green: 0.55, blue: 0.08, alpha: 1) 221 | actionSheet.present(in: sSelf) 222 | } 223 | } 224 | let fontRow = RowData(title: "Text font") { [weak self] in 225 | if let sSelf = self { 226 | let actionSheet = FloatingActionSheetController(actionGroups: sSelf.exampleActionGroups()) 227 | actionSheet.font = .systemFont(ofSize: 18) 228 | actionSheet.present(in: sSelf) 229 | } 230 | } 231 | let dimmingColorRow = RowData(title: "Dimming color") { [weak self] in 232 | if let sSelf = self { 233 | let actionSheet = FloatingActionSheetController(actionGroups: sSelf.exampleActionGroups()) 234 | actionSheet.dimmingColor = UIColor.white.withAlphaComponent(0.7) 235 | actionSheet.present(in: sSelf) 236 | } 237 | } 238 | let pushBackScaleRow = RowData(title: "Push back scale") { [weak self] in 239 | if let sSelf = self { 240 | let actionSheet = FloatingActionSheetController(actionGroups: sSelf.exampleActionGroups()) 241 | actionSheet.pushBackScale = 0.7 242 | actionSheet.present(in: sSelf) 243 | } 244 | } 245 | let individualCustomRow = RowData(title: "Individual custom") { [weak self] in 246 | if let sSelf = self { 247 | let actions = (1...2).map { 248 | FloatingAction(title: "Action\($0)") { 249 | sSelf.display($0) 250 | } 251 | } 252 | let cancelAction = FloatingAction(title: "Cancel") { 253 | sSelf.display($0) 254 | } 255 | cancelAction.tintColor = UIColor(red:0.93, green:0.95, blue:0.96, alpha:1) 256 | cancelAction.textColor = UIColor(red:0.87, green:0.42, blue:0.35, alpha:1) 257 | FloatingActionSheetController(actionGroup: .init(actions: actions)) 258 | .add(action: cancelAction, newGroup: true) 259 | .present(in: sSelf) 260 | } 261 | } 262 | dataSources.append( 263 | DataSource( 264 | sectionTitle: "Custom Appearance", 265 | rowDatas: [ 266 | tintRow, 267 | textColorRow, 268 | fontRow, 269 | dimmingColorRow, 270 | pushBackScaleRow, 271 | individualCustomRow 272 | ] 273 | ) 274 | ) 275 | } 276 | 277 | fileprivate func display(_ action: FloatingAction) { 278 | if let title = action.title { 279 | displayLabel.text = "\(title) Selected." 280 | } 281 | } 282 | 283 | fileprivate func exampleActionGroups() -> [FloatingActionGroup] { 284 | let action1 = FloatingAction(title: "Action1") { [weak self] in 285 | self?.display($0) 286 | } 287 | let action2 = FloatingAction(title: "Action2") { [weak self] in 288 | self?.display($0) 289 | } 290 | let action3 = FloatingAction(title: "Action3") { [weak self] in 291 | self?.display($0) 292 | } 293 | let actionGroup1 = FloatingActionGroup(action: action1) 294 | let actionGroup2 = FloatingActionGroup(action: action2, action3) 295 | return [actionGroup1, actionGroup2] 296 | } 297 | } 298 | 299 | extension ViewController: UITableViewDelegate, UITableViewDataSource { 300 | 301 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 302 | tableView.deselectRow(at: indexPath, animated: true) 303 | dataSources[(indexPath as NSIndexPath).section].rowDatas[(indexPath as NSIndexPath).row].handler?() 304 | } 305 | 306 | func numberOfSections(in tableView: UITableView) -> Int { 307 | return dataSources.count 308 | } 309 | 310 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 311 | return dataSources[section].rowDatas.count 312 | } 313 | 314 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 315 | let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell 316 | cell.title = dataSources[(indexPath as NSIndexPath).section].rowDatas[(indexPath as NSIndexPath).row].title 317 | return cell 318 | } 319 | 320 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 321 | return 44 322 | } 323 | 324 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 325 | let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderView") as! HeaderView 326 | view.title = dataSources[section].sectionTitle 327 | return view 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /FloatingActionSheetController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "FloatingActionSheetController" 3 | spec.version = "2.1.0" 4 | spec.author = { "ra1028" => "r.fe51028.r@gmail.com" } 5 | spec.homepage = "https://github.com/ra1028" 6 | spec.summary = "FloatingActionSheetController is a cool design ActionSheetController library written in Swift" 7 | spec.source = { :git => "https://github.com/ra1028/FloatingActionSheetController.git", :tag => spec.version } 8 | spec.license = { :type => "MIT", :file => "LICENSE" } 9 | spec.platform = :ios, '8.0' 10 | spec.source_files = "FloatingActionSheetController/*.swift" 11 | spec.requires_arc = true 12 | spec.ios.deployment_target = '8.0' 13 | spec.ios.frameworks = ['UIKit', 'Foundation'] 14 | end 15 | -------------------------------------------------------------------------------- /FloatingActionSheetController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2A4B95571BDC31FA00148B08 /* FloatingActionSheetController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4B95561BDC31FA00148B08 /* FloatingActionSheetController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 2A82813A1BDC347F00F06E1F /* FloatingActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A8281391BDC347F00F06E1F /* FloatingActionSheetController.swift */; }; 12 | 2A82813C1BDC3B2E00F06E1F /* FloatingAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A82813B1BDC3B2E00F06E1F /* FloatingAction.swift */; }; 13 | 2A82813E1BDC458500F06E1F /* FloatingActionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A82813D1BDC458500F06E1F /* FloatingActionGroup.swift */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXFileReference section */ 17 | 2A4B95531BDC31FA00148B08 /* FloatingActionSheetController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FloatingActionSheetController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 2A4B95561BDC31FA00148B08 /* FloatingActionSheetController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatingActionSheetController.h; sourceTree = ""; }; 19 | 2A4B95581BDC31FA00148B08 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 20 | 2A8281391BDC347F00F06E1F /* FloatingActionSheetController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingActionSheetController.swift; sourceTree = ""; }; 21 | 2A82813B1BDC3B2E00F06E1F /* FloatingAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingAction.swift; sourceTree = ""; }; 22 | 2A82813D1BDC458500F06E1F /* FloatingActionGroup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingActionGroup.swift; sourceTree = ""; }; 23 | /* End PBXFileReference section */ 24 | 25 | /* Begin PBXFrameworksBuildPhase section */ 26 | 2A4B954F1BDC31FA00148B08 /* Frameworks */ = { 27 | isa = PBXFrameworksBuildPhase; 28 | buildActionMask = 2147483647; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 0; 32 | }; 33 | /* End PBXFrameworksBuildPhase section */ 34 | 35 | /* Begin PBXGroup section */ 36 | 2A4B95491BDC31FA00148B08 = { 37 | isa = PBXGroup; 38 | children = ( 39 | 2A4B95551BDC31FA00148B08 /* FloatingActionSheetController */, 40 | 2A4B95541BDC31FA00148B08 /* Products */, 41 | ); 42 | sourceTree = ""; 43 | }; 44 | 2A4B95541BDC31FA00148B08 /* Products */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 2A4B95531BDC31FA00148B08 /* FloatingActionSheetController.framework */, 48 | ); 49 | name = Products; 50 | sourceTree = ""; 51 | }; 52 | 2A4B95551BDC31FA00148B08 /* FloatingActionSheetController */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 2A8281391BDC347F00F06E1F /* FloatingActionSheetController.swift */, 56 | 2A82813D1BDC458500F06E1F /* FloatingActionGroup.swift */, 57 | 2A82813B1BDC3B2E00F06E1F /* FloatingAction.swift */, 58 | 2A4B95561BDC31FA00148B08 /* FloatingActionSheetController.h */, 59 | 2A4B95581BDC31FA00148B08 /* Info.plist */, 60 | ); 61 | path = FloatingActionSheetController; 62 | sourceTree = ""; 63 | }; 64 | /* End PBXGroup section */ 65 | 66 | /* Begin PBXHeadersBuildPhase section */ 67 | 2A4B95501BDC31FA00148B08 /* Headers */ = { 68 | isa = PBXHeadersBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 2A4B95571BDC31FA00148B08 /* FloatingActionSheetController.h in Headers */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXHeadersBuildPhase section */ 76 | 77 | /* Begin PBXNativeTarget section */ 78 | 2A4B95521BDC31FA00148B08 /* FloatingActionSheetController */ = { 79 | isa = PBXNativeTarget; 80 | buildConfigurationList = 2A4B955B1BDC31FA00148B08 /* Build configuration list for PBXNativeTarget "FloatingActionSheetController" */; 81 | buildPhases = ( 82 | 2A4B954E1BDC31FA00148B08 /* Sources */, 83 | 2A4B954F1BDC31FA00148B08 /* Frameworks */, 84 | 2A4B95501BDC31FA00148B08 /* Headers */, 85 | 2A4B95511BDC31FA00148B08 /* Resources */, 86 | ); 87 | buildRules = ( 88 | ); 89 | dependencies = ( 90 | ); 91 | name = FloatingActionSheetController; 92 | productName = FloatingActionSheetController; 93 | productReference = 2A4B95531BDC31FA00148B08 /* FloatingActionSheetController.framework */; 94 | productType = "com.apple.product-type.framework"; 95 | }; 96 | /* End PBXNativeTarget section */ 97 | 98 | /* Begin PBXProject section */ 99 | 2A4B954A1BDC31FA00148B08 /* Project object */ = { 100 | isa = PBXProject; 101 | attributes = { 102 | LastSwiftUpdateCheck = 0700; 103 | LastUpgradeCheck = 0900; 104 | ORGANIZATIONNAME = "Ryo Aoyama"; 105 | TargetAttributes = { 106 | 2A4B95521BDC31FA00148B08 = { 107 | CreatedOnToolsVersion = 7.0; 108 | LastSwiftMigration = 0900; 109 | ProvisioningStyle = Manual; 110 | }; 111 | }; 112 | }; 113 | buildConfigurationList = 2A4B954D1BDC31FA00148B08 /* Build configuration list for PBXProject "FloatingActionSheetController" */; 114 | compatibilityVersion = "Xcode 3.2"; 115 | developmentRegion = English; 116 | hasScannedForEncodings = 0; 117 | knownRegions = ( 118 | en, 119 | ); 120 | mainGroup = 2A4B95491BDC31FA00148B08; 121 | productRefGroup = 2A4B95541BDC31FA00148B08 /* Products */; 122 | projectDirPath = ""; 123 | projectRoot = ""; 124 | targets = ( 125 | 2A4B95521BDC31FA00148B08 /* FloatingActionSheetController */, 126 | ); 127 | }; 128 | /* End PBXProject section */ 129 | 130 | /* Begin PBXResourcesBuildPhase section */ 131 | 2A4B95511BDC31FA00148B08 /* Resources */ = { 132 | isa = PBXResourcesBuildPhase; 133 | buildActionMask = 2147483647; 134 | files = ( 135 | ); 136 | runOnlyForDeploymentPostprocessing = 0; 137 | }; 138 | /* End PBXResourcesBuildPhase section */ 139 | 140 | /* Begin PBXSourcesBuildPhase section */ 141 | 2A4B954E1BDC31FA00148B08 /* Sources */ = { 142 | isa = PBXSourcesBuildPhase; 143 | buildActionMask = 2147483647; 144 | files = ( 145 | 2A82813E1BDC458500F06E1F /* FloatingActionGroup.swift in Sources */, 146 | 2A82813A1BDC347F00F06E1F /* FloatingActionSheetController.swift in Sources */, 147 | 2A82813C1BDC3B2E00F06E1F /* FloatingAction.swift in Sources */, 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | /* End PBXSourcesBuildPhase section */ 152 | 153 | /* Begin XCBuildConfiguration section */ 154 | 2A4B95591BDC31FA00148B08 /* Debug */ = { 155 | isa = XCBuildConfiguration; 156 | buildSettings = { 157 | ALWAYS_SEARCH_USER_PATHS = NO; 158 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 159 | CLANG_CXX_LIBRARY = "libc++"; 160 | CLANG_ENABLE_MODULES = YES; 161 | CLANG_ENABLE_OBJC_ARC = YES; 162 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 163 | CLANG_WARN_BOOL_CONVERSION = YES; 164 | CLANG_WARN_COMMA = YES; 165 | CLANG_WARN_CONSTANT_CONVERSION = YES; 166 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 167 | CLANG_WARN_EMPTY_BODY = YES; 168 | CLANG_WARN_ENUM_CONVERSION = YES; 169 | CLANG_WARN_INFINITE_RECURSION = YES; 170 | CLANG_WARN_INT_CONVERSION = YES; 171 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 172 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 175 | CLANG_WARN_STRICT_PROTOTYPES = YES; 176 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 177 | CLANG_WARN_UNREACHABLE_CODE = YES; 178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 179 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 180 | COPY_PHASE_STRIP = NO; 181 | CURRENT_PROJECT_VERSION = 1; 182 | DEBUG_INFORMATION_FORMAT = dwarf; 183 | ENABLE_STRICT_OBJC_MSGSEND = YES; 184 | ENABLE_TESTABILITY = YES; 185 | GCC_C_LANGUAGE_STANDARD = gnu99; 186 | GCC_DYNAMIC_NO_PIC = NO; 187 | GCC_NO_COMMON_BLOCKS = YES; 188 | GCC_OPTIMIZATION_LEVEL = 0; 189 | GCC_PREPROCESSOR_DEFINITIONS = ( 190 | "DEBUG=1", 191 | "$(inherited)", 192 | ); 193 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 194 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 195 | GCC_WARN_UNDECLARED_SELECTOR = YES; 196 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 197 | GCC_WARN_UNUSED_FUNCTION = YES; 198 | GCC_WARN_UNUSED_VARIABLE = YES; 199 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 200 | MTL_ENABLE_DEBUG_INFO = YES; 201 | ONLY_ACTIVE_ARCH = YES; 202 | SDKROOT = iphoneos; 203 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 204 | TARGETED_DEVICE_FAMILY = "1,2"; 205 | VERSIONING_SYSTEM = "apple-generic"; 206 | VERSION_INFO_PREFIX = ""; 207 | }; 208 | name = Debug; 209 | }; 210 | 2A4B955A1BDC31FA00148B08 /* Release */ = { 211 | isa = XCBuildConfiguration; 212 | buildSettings = { 213 | ALWAYS_SEARCH_USER_PATHS = NO; 214 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 215 | CLANG_CXX_LIBRARY = "libc++"; 216 | CLANG_ENABLE_MODULES = YES; 217 | CLANG_ENABLE_OBJC_ARC = YES; 218 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 219 | CLANG_WARN_BOOL_CONVERSION = YES; 220 | CLANG_WARN_COMMA = YES; 221 | CLANG_WARN_CONSTANT_CONVERSION = YES; 222 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 223 | CLANG_WARN_EMPTY_BODY = YES; 224 | CLANG_WARN_ENUM_CONVERSION = YES; 225 | CLANG_WARN_INFINITE_RECURSION = YES; 226 | CLANG_WARN_INT_CONVERSION = YES; 227 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 228 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 229 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 230 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 231 | CLANG_WARN_STRICT_PROTOTYPES = YES; 232 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 233 | CLANG_WARN_UNREACHABLE_CODE = YES; 234 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 235 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 236 | COPY_PHASE_STRIP = NO; 237 | CURRENT_PROJECT_VERSION = 1; 238 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 239 | ENABLE_NS_ASSERTIONS = NO; 240 | ENABLE_STRICT_OBJC_MSGSEND = YES; 241 | GCC_C_LANGUAGE_STANDARD = gnu99; 242 | GCC_NO_COMMON_BLOCKS = YES; 243 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 245 | GCC_WARN_UNDECLARED_SELECTOR = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 247 | GCC_WARN_UNUSED_FUNCTION = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 250 | MTL_ENABLE_DEBUG_INFO = NO; 251 | SDKROOT = iphoneos; 252 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 253 | TARGETED_DEVICE_FAMILY = "1,2"; 254 | VALIDATE_PRODUCT = YES; 255 | VERSIONING_SYSTEM = "apple-generic"; 256 | VERSION_INFO_PREFIX = ""; 257 | }; 258 | name = Release; 259 | }; 260 | 2A4B955C1BDC31FA00148B08 /* Debug */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | CLANG_ENABLE_MODULES = YES; 264 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 265 | DEFINES_MODULE = YES; 266 | DEVELOPMENT_TEAM = ""; 267 | DYLIB_COMPATIBILITY_VERSION = 1; 268 | DYLIB_CURRENT_VERSION = 1; 269 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 270 | INFOPLIST_FILE = FloatingActionSheetController/Info.plist; 271 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 272 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 273 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 274 | PRODUCT_BUNDLE_IDENTIFIER = com.ryo.FloatingActionSheetController; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | SKIP_INSTALL = YES; 277 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 278 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 279 | SWIFT_VERSION = 4.0; 280 | }; 281 | name = Debug; 282 | }; 283 | 2A4B955D1BDC31FA00148B08 /* Release */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | CLANG_ENABLE_MODULES = YES; 287 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 288 | DEFINES_MODULE = YES; 289 | DEVELOPMENT_TEAM = ""; 290 | DYLIB_COMPATIBILITY_VERSION = 1; 291 | DYLIB_CURRENT_VERSION = 1; 292 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 293 | INFOPLIST_FILE = FloatingActionSheetController/Info.plist; 294 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 295 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 297 | PRODUCT_BUNDLE_IDENTIFIER = com.ryo.FloatingActionSheetController; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | SKIP_INSTALL = YES; 300 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 301 | SWIFT_VERSION = 4.0; 302 | }; 303 | name = Release; 304 | }; 305 | /* End XCBuildConfiguration section */ 306 | 307 | /* Begin XCConfigurationList section */ 308 | 2A4B954D1BDC31FA00148B08 /* Build configuration list for PBXProject "FloatingActionSheetController" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | 2A4B95591BDC31FA00148B08 /* Debug */, 312 | 2A4B955A1BDC31FA00148B08 /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | defaultConfigurationName = Release; 316 | }; 317 | 2A4B955B1BDC31FA00148B08 /* Build configuration list for PBXNativeTarget "FloatingActionSheetController" */ = { 318 | isa = XCConfigurationList; 319 | buildConfigurations = ( 320 | 2A4B955C1BDC31FA00148B08 /* Debug */, 321 | 2A4B955D1BDC31FA00148B08 /* Release */, 322 | ); 323 | defaultConfigurationIsVisible = 0; 324 | defaultConfigurationName = Release; 325 | }; 326 | /* End XCConfigurationList section */ 327 | }; 328 | rootObject = 2A4B954A1BDC31FA00148B08 /* Project object */; 329 | } 330 | -------------------------------------------------------------------------------- /FloatingActionSheetController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FloatingActionSheetController.xcodeproj/xcshareddata/xcschemes/FloatingActionSheetController.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /FloatingActionSheetController/FloatingAction.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FloatingAction.swift 3 | // FloatingActionSheetController 4 | // 5 | // Created by Ryo Aoyama on 10/25/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public final class FloatingAction { 12 | 13 | // MARK: Public 14 | 15 | public private(set) var title: String? 16 | public var tintColor: UIColor? 17 | public var textColor: UIColor? 18 | public var font: UIFont? 19 | 20 | public init(title: String, handleImmediately: Bool = false, handler: ((FloatingAction) -> Void)?) { 21 | self.title = title 22 | self.handleImmediately = handleImmediately 23 | self.handler = handler 24 | } 25 | 26 | // MARK: Internal 27 | 28 | private(set) var handler: ((FloatingAction) -> Void)? 29 | private(set) var handleImmediately = false 30 | } 31 | -------------------------------------------------------------------------------- /FloatingActionSheetController/FloatingActionGroup.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FloatingActionGroup.swift 3 | // FloatingActionSheetController 4 | // 5 | // Created by Ryo Aoyama on 10/25/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public final class FloatingActionGroup { 12 | 13 | // MARK: Public 14 | 15 | public init() {} 16 | 17 | public init(action: FloatingAction...) { 18 | action.forEach { add(action: $0) } 19 | } 20 | 21 | public init(actions: [FloatingAction]) { 22 | add(actions: actions) 23 | } 24 | 25 | @discardableResult 26 | public func add(action: FloatingAction...) -> FloatingActionGroup { 27 | actions += action 28 | return self 29 | } 30 | 31 | @discardableResult 32 | public func add(actions: [FloatingAction]) -> FloatingActionGroup { 33 | self.actions += actions 34 | return self 35 | } 36 | 37 | // MARK: Internal 38 | 39 | private(set) var actions = [FloatingAction]() 40 | } 41 | -------------------------------------------------------------------------------- /FloatingActionSheetController/FloatingActionSheetController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FloatingActionSheetController.h 3 | // FloatingActionSheetController 4 | // 5 | // Created by Ryo Aoyama on 10/25/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for FloatingActionSheetController. 12 | FOUNDATION_EXPORT double FloatingActionSheetControllerVersionNumber; 13 | 14 | //! Project version string for FloatingActionSheetController. 15 | FOUNDATION_EXPORT const unsigned char FloatingActionSheetControllerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /FloatingActionSheetController/FloatingActionSheetController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FloatingActionSheetController.swift 3 | // FloatingActionSheetController 4 | // 5 | // Created by Ryo Aoyama on 10/25/15. 6 | // Copyright © 2015 Ryo Aoyama. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class FloatingActionSheetController: UIViewController, UIViewControllerTransitioningDelegate { 12 | 13 | // MARK: Public 14 | 15 | public enum AnimationStyle { 16 | case slideUp 17 | case slideDown 18 | case slideLeft 19 | case slideRight 20 | case pop 21 | } 22 | 23 | open var animationStyle = AnimationStyle.slideUp 24 | open var itemTintColor = UIColor(red:0.13, green:0.13, blue:0.17, alpha:1) 25 | open var font = UIFont.boldSystemFont(ofSize: 14) 26 | open var textColor = UIColor.white 27 | open var dimmingColor = UIColor(white: 0, alpha: 0.7) 28 | open var pushBackScale: CGFloat = 0.85 29 | 30 | public convenience init(animationStyle: AnimationStyle) { 31 | self.init(nibName: nil, bundle: nil) 32 | self.animationStyle = animationStyle 33 | } 34 | 35 | public convenience init(actionGroup: FloatingActionGroup..., animationStyle: AnimationStyle = .slideUp) { 36 | self.init(nibName: nil, bundle: nil) 37 | self.animationStyle = animationStyle 38 | actionGroup.forEach { add(actionGroup: $0) } 39 | } 40 | 41 | public convenience init(actionGroups: [FloatingActionGroup], animationStyle: AnimationStyle = .slideUp) { 42 | self.init(nibName: nil, bundle: nil) 43 | self.animationStyle = animationStyle 44 | add(actionGroups: actionGroups) 45 | } 46 | 47 | public convenience init(actions: [FloatingAction], animationStyle: AnimationStyle = .slideUp) { 48 | self.init(nibName: nil, bundle: nil) 49 | self.animationStyle = animationStyle 50 | add(actions: actions) 51 | } 52 | 53 | public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { 54 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 55 | configure() 56 | } 57 | 58 | public required init?(coder aDecoder: NSCoder) { 59 | fatalError("init(coder:) has not been implemented") 60 | } 61 | 62 | open override var preferredStatusBarStyle: UIStatusBarStyle { 63 | return .lightContent 64 | } 65 | 66 | open override var prefersStatusBarHidden: Bool { 67 | return UIApplication.shared.isStatusBarHidden 68 | } 69 | 70 | open override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { 71 | return .fade 72 | } 73 | 74 | open override func viewWillAppear(_ animated: Bool) { 75 | super.viewWillAppear(animated) 76 | if !isShowing { 77 | showActionSheet() 78 | } 79 | if originalStatusBarStyle == nil { 80 | originalStatusBarStyle = UIApplication.shared.statusBarStyle 81 | } 82 | UIApplication.shared.setStatusBarStyle(.lightContent, animated: true) 83 | } 84 | 85 | open override func viewWillDisappear(_ animated: Bool) { 86 | if let style = originalStatusBarStyle { 87 | UIApplication.shared.setStatusBarStyle(style, animated: true) 88 | } 89 | } 90 | 91 | @discardableResult 92 | public func present(in inViewController: UIViewController, completion: (() -> Void)? = nil) -> Self { 93 | inViewController.present(self, animated: true, completion: completion) 94 | return self 95 | } 96 | 97 | @discardableResult 98 | public func dismiss() -> Self { 99 | dismissActionSheet() 100 | return self 101 | } 102 | 103 | @discardableResult 104 | public func add(actionGroup: FloatingActionGroup...) -> Self { 105 | actionGroups += actionGroup 106 | return self 107 | } 108 | 109 | @discardableResult 110 | public func add(actionGroups: [FloatingActionGroup]) -> Self { 111 | self.actionGroups += actionGroups 112 | return self 113 | } 114 | 115 | @discardableResult 116 | public func add(action: FloatingAction..., newGroup: Bool = false) -> Self { 117 | if let lastGroup = actionGroups.last, !newGroup { 118 | action.forEach { lastGroup.add(action: $0) } 119 | } else { 120 | let actionGroup = FloatingActionGroup() 121 | action.forEach { actionGroup.add(action: $0) } 122 | add(actionGroup: actionGroup) 123 | } 124 | return self 125 | } 126 | 127 | @discardableResult 128 | public func add(actions: [FloatingAction], newGroup: Bool = false) -> Self { 129 | if let lastGroup = actionGroups.last, !newGroup { 130 | lastGroup.add(actions: actions) 131 | } else { 132 | let actionGroup = FloatingActionGroup(actions: actions) 133 | add(actionGroup: actionGroup) 134 | } 135 | return self 136 | } 137 | 138 | // MARK: Private 139 | 140 | fileprivate class ActionButton: UIButton { 141 | 142 | fileprivate var action: FloatingAction? 143 | private var defaultBackgroundColor: UIColor? 144 | 145 | override fileprivate var isHighlighted: Bool { 146 | didSet { 147 | guard oldValue != isHighlighted else { return } 148 | if isHighlighted { 149 | defaultBackgroundColor = backgroundColor 150 | backgroundColor = highlightedColor(defaultBackgroundColor) 151 | } else { 152 | backgroundColor = defaultBackgroundColor 153 | defaultBackgroundColor = nil 154 | } 155 | } 156 | } 157 | 158 | func configure(_ action: FloatingAction) { 159 | self.action = action 160 | setTitle(action.title, for: .normal) 161 | 162 | if let color = action.tintColor { 163 | backgroundColor = color 164 | } 165 | if let color = action.textColor { 166 | setTitleColor(color, for: .normal) 167 | } 168 | if let font = action.font { 169 | titleLabel?.font = font 170 | } 171 | } 172 | 173 | private func highlightedColor(_ originalColor: UIColor?) -> UIColor? { 174 | guard let originalColor = originalColor else { return nil } 175 | var hue: CGFloat = 0, saturatioin: CGFloat = 0, 176 | brightness: CGFloat = 0, alpha: CGFloat = 0 177 | if originalColor.getHue( 178 | &hue, 179 | saturation: &saturatioin, 180 | brightness: &brightness, 181 | alpha: &alpha) { 182 | return UIColor(hue: hue, saturation: saturatioin, brightness: brightness * 0.75, alpha: alpha) 183 | } 184 | return originalColor 185 | } 186 | } 187 | 188 | private var actionGroups = [FloatingActionGroup]() 189 | private var actionButtons = [ActionButton]() 190 | private var isShowing = false 191 | private var originalStatusBarStyle: UIStatusBarStyle? 192 | fileprivate weak var dimmingView: UIControl! 193 | 194 | private func showActionSheet() { 195 | isShowing = true 196 | dimmingView.backgroundColor = dimmingColor 197 | 198 | let itemHeight: CGFloat = 50 199 | let itemSpacing: CGFloat = 10 200 | let groupSpacing: CGFloat = 30 201 | var previousGroupLastButton: ActionButton? 202 | 203 | actionGroups.reversed().forEach { 204 | var previousButton: ActionButton? 205 | $0.actions.reversed().forEach { 206 | let button = createSheetButton($0) 207 | view.addSubview(button) 208 | var constraints = NSLayoutConstraint.constraints( 209 | withVisualFormat: "H:|-(spacing)-[button]-(spacing)-|", 210 | options: [], 211 | metrics: ["spacing": itemSpacing], 212 | views: ["button": button] 213 | ) 214 | if let previousButton = previousButton { 215 | constraints += 216 | NSLayoutConstraint.constraints( 217 | withVisualFormat: "V:[button(height)]-spacing-[previous]", 218 | options: [], 219 | metrics: ["height": itemHeight,"spacing": itemSpacing], 220 | views: ["button": button, "previous": previousButton] 221 | ) 222 | } else if let previousGroupLastButton = previousGroupLastButton { 223 | constraints += 224 | NSLayoutConstraint.constraints( 225 | withVisualFormat: "V:[button(height)]-spacing-[previous]", 226 | options: [], 227 | metrics: ["height": itemHeight, "spacing": groupSpacing], 228 | views: ["button": button, "previous": previousGroupLastButton] 229 | ) 230 | } else { 231 | if #available(iOS 11.0, *) { 232 | constraints += [button.heightAnchor.constraint(equalToConstant: itemHeight), 233 | button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -itemSpacing) 234 | ] 235 | } else { 236 | constraints += 237 | NSLayoutConstraint.constraints( 238 | withVisualFormat: "V:[button(height)]-spacing-|", 239 | options: [], 240 | metrics: ["height": itemHeight,"spacing": itemSpacing], 241 | views: ["button": button] 242 | ) 243 | } 244 | } 245 | view.addConstraints(constraints) 246 | previousButton = button 247 | previousGroupLastButton = button 248 | actionButtons.append(button) 249 | } 250 | } 251 | view.layoutIfNeeded() 252 | 253 | if let topButton = actionButtons.last { 254 | let buttons: [ActionButton] 255 | let preTransform: CATransform3D 256 | let transform: CATransform3D 257 | let topButtonY = topButton.frame.origin.y 258 | assert(topButtonY > 0, "[FloatingActionSheetController] Too many action items error.") 259 | switch animationStyle { 260 | case .slideUp: 261 | let bottomPad = view.bounds.height - topButtonY 262 | buttons = actionButtons.reversed() 263 | preTransform = CATransform3DMakeTranslation(0, bottomPad, 0) 264 | transform = CATransform3DMakeTranslation(0, -10, 0) 265 | case .slideDown: 266 | let topPad = actionButtons[0].frame.maxY 267 | buttons = actionButtons 268 | preTransform = CATransform3DMakeTranslation(0, -topPad, 0) 269 | transform = CATransform3DMakeTranslation(0, 10, 0) 270 | case .slideLeft: 271 | let rightPad = view.bounds.width - topButton.frame.origin.x 272 | buttons = actionButtons.reversed() 273 | preTransform = CATransform3DMakeTranslation(rightPad, 0, 0) 274 | transform = CATransform3DMakeTranslation(-10, 0, 0) 275 | case .slideRight: 276 | let leftPad = topButton.frame.maxX 277 | buttons = actionButtons.reversed() 278 | preTransform = CATransform3DMakeTranslation(-leftPad, 0, 0) 279 | transform = CATransform3DMakeTranslation(10, 0, 0) 280 | case .pop: 281 | buttons = actionButtons.reversed() 282 | preTransform = CATransform3DMakeScale(0, 0, 1) 283 | transform = CATransform3DMakeScale(1.1, 1.1, 1) 284 | } 285 | 286 | buttons.enumerated().forEach { index, button in 287 | button.layer.transform = preTransform 288 | UIView.animate(withDuration: 0.25, delay: TimeInterval(index) * 0.05 + 0.05, 289 | options: .beginFromCurrentState, 290 | animations: { 291 | button.layer.transform = transform 292 | }) { _ in 293 | UIView.animate(withDuration: 0.2, delay: 0, 294 | options: [.beginFromCurrentState, .curveEaseOut], 295 | animations: { 296 | button.layer.transform = CATransform3DIdentity 297 | }, completion: nil) 298 | } 299 | } 300 | } 301 | } 302 | 303 | private func dismissActionSheet(_ completion: (() -> Void)? = nil) { 304 | self.dismiss(animated: true, completion: completion) 305 | if let topButton = actionButtons.last { 306 | let buttons: [ActionButton] 307 | let transform: CATransform3D 308 | var completion: ((ActionButton) -> Void)? 309 | switch animationStyle { 310 | case .slideUp: 311 | let bottomPad = view.bounds.height - topButton.frame.origin.y 312 | buttons = actionButtons 313 | transform = CATransform3DMakeTranslation(0, bottomPad, 0) 314 | case .slideDown: 315 | let topPad = actionButtons[0].frame.maxY 316 | buttons = actionButtons.reversed() 317 | transform = CATransform3DMakeTranslation(0, -topPad, 0) 318 | case .slideLeft: 319 | let leftPad = topButton.frame.maxX 320 | buttons = actionButtons.reversed() 321 | transform = CATransform3DMakeTranslation(-leftPad, 0, 0) 322 | case .slideRight: 323 | let rightPad = view.bounds.width - topButton.frame.origin.x 324 | buttons = actionButtons.reversed() 325 | transform = CATransform3DMakeTranslation(rightPad, 0, 0) 326 | case .pop: 327 | buttons = actionButtons 328 | transform = CATransform3DMakeScale(0.01, 0.01, 1) // 0.01 = Swift bug 329 | completion = { $0.layer.transform = CATransform3DMakeScale(0, 0, 1) } 330 | } 331 | 332 | buttons.enumerated().forEach { index, button in 333 | UIView.animate(withDuration: 0.2, delay: TimeInterval(index) * 0.05 + 0.05, 334 | options: .beginFromCurrentState, 335 | animations: { 336 | button.layer.transform = transform 337 | }) { _ in 338 | completion?(button) 339 | } 340 | } 341 | } 342 | } 343 | 344 | private func createSheetButton(_ action: FloatingAction) -> ActionButton { 345 | let button = ActionButton(type: .custom) 346 | button.layer.cornerRadius = 4 347 | button.backgroundColor = itemTintColor 348 | button.titleLabel?.textAlignment = .center 349 | button.titleLabel?.font = font 350 | button.setTitleColor(textColor, for: .normal) 351 | button.translatesAutoresizingMaskIntoConstraints = false 352 | button.configure(action) 353 | button.addTarget(self, action: #selector(FloatingActionSheetController.didSelectItem(_:)), for: .touchUpInside) 354 | return button 355 | } 356 | 357 | @objc private dynamic func didSelectItem(_ button: ActionButton) { 358 | guard let action = button.action else { return } 359 | 360 | if action.handleImmediately { 361 | action.handler?(action) 362 | } 363 | dismissActionSheet { 364 | if !action.handleImmediately { 365 | action.handler?(action) 366 | } 367 | } 368 | } 369 | 370 | private func configure() { 371 | view.backgroundColor = .clear 372 | modalPresentationStyle = .custom 373 | transitioningDelegate = self 374 | 375 | let dimmingView = UIControl() 376 | dimmingView.addTarget(self, action: #selector(FloatingActionSheetController.handleTapDimmingView), for: .touchUpInside) 377 | dimmingView.translatesAutoresizingMaskIntoConstraints = false 378 | view.addSubview(dimmingView) 379 | self.dimmingView = dimmingView 380 | 381 | view.addConstraints( 382 | NSLayoutConstraint.constraints( 383 | withVisualFormat: "V:|-0-[dimmingView]-0-|", 384 | options: [], 385 | metrics: nil, 386 | views: ["dimmingView": dimmingView] 387 | ) 388 | + NSLayoutConstraint.constraints( 389 | withVisualFormat: "H:|-0-[dimmingView]-0-|", 390 | options: [], 391 | metrics: nil, 392 | views: ["dimmingView": dimmingView] 393 | ) 394 | ) 395 | } 396 | 397 | @objc private dynamic func handleTapDimmingView() { 398 | dismissActionSheet() 399 | } 400 | 401 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 402 | return FloatingTransitionAnimator(dimmingView: dimmingView, pushBackScale: pushBackScale) 403 | } 404 | 405 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 406 | let delay = TimeInterval(actionButtons.count) * 0.03 407 | return FloatingTransitionAnimator(dimmingView: dimmingView, pushBackScale: pushBackScale, delay: delay, forwardTransition: false) 408 | } 409 | 410 | } 411 | 412 | private final class FloatingTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning { 413 | 414 | var forwardTransition = true 415 | let dimmingView: UIView 416 | let pushBackScale: CGFloat 417 | var delay: TimeInterval = 0 418 | 419 | init(dimmingView: UIView, pushBackScale: CGFloat, delay: TimeInterval = 0, forwardTransition: Bool = true) { 420 | self.dimmingView = dimmingView 421 | self.pushBackScale = pushBackScale 422 | super.init() 423 | self.delay = delay 424 | self.forwardTransition = forwardTransition 425 | } 426 | 427 | @objc func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 428 | return 0.5 429 | } 430 | 431 | @objc func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 432 | guard let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), 433 | let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) 434 | else { return } 435 | 436 | let containerView = transitionContext.containerView 437 | let duration = transitionDuration(using: transitionContext) 438 | 439 | if forwardTransition { 440 | containerView.addSubview(toVC.view) 441 | UIView.animate(withDuration: duration, delay: 0, 442 | usingSpringWithDamping: 1, initialSpringVelocity: 0, 443 | options: .beginFromCurrentState, 444 | animations: { 445 | fromVC.view.layer.transform = CATransform3DMakeScale(self.pushBackScale, self.pushBackScale, 1) 446 | self.dimmingView.alpha = 0 447 | self.dimmingView.alpha = 1 448 | }) { _ in 449 | transitionContext.completeTransition(true) 450 | } 451 | } else { 452 | UIView.animate(withDuration: duration, delay: delay, 453 | usingSpringWithDamping: 1, initialSpringVelocity: 0, 454 | options: .beginFromCurrentState, 455 | animations: { 456 | toVC.view.layer.transform = CATransform3DIdentity 457 | self.dimmingView.alpha = 0 458 | }) { _ in 459 | transitionContext.completeTransition(true) 460 | } 461 | } 462 | } 463 | } 464 | -------------------------------------------------------------------------------- /FloatingActionSheetController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 ra1028 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FloationgActionSheetController 2 | ![Platform](http://img.shields.io/badge/platform-iOS-blue.svg?style=flat) 3 | [![Language](https://img.shields.io/badge/swift3-compatible-4BC51D.svg?style=flat)](https://developer.apple.com/swift) 4 | [![CocoaPods Shield](https://img.shields.io/cocoapods/v/FloatingActionSheetController.svg)](https://cocoapods.org/pods/FloatingActionSheetController) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/ra1028/FloatingActionSheetController/blob/master/LICENSE) 7 | 8 | FloatingActionSheetController is a cool design ActionSheetController library written in Swift2. 9 | 10 | ## Overview 11 | 12 | 13 | 14 | 15 | ## Requirements 16 | - Xcode 8+ 17 | - Swift3 18 | - iOS 8.0+ 19 | 20 | ## Installation 21 | 22 | ### CocoaPods 23 | ```ruby 24 | # Podfile 25 | use_frameworks! 26 | target 'YOUR_TARGET_NAME' do 27 | pod "FloatingActionSheetController" 28 | end 29 | ``` 30 | 31 | ### Carthage 32 | ```ruby 33 | # Cartfile 34 | github "ra1028/FloatingActionSheetController" 35 | ``` 36 | 37 | ## Usage 38 | 39 | __Import FloationgActionSheetController at first.__ 40 | ```swift 41 | import FloatingActionSheetController 42 | ``` 43 | 44 | ### example 45 | ```swift 46 | let action1 = FloatingAction(title: "title") { action in 47 | // Do something. 48 | } 49 | let action2 = FloatingAction(title: "title") { action in 50 | // Do something. 51 | } 52 | let action3 = FloatingAction(title: "title", handleImmediately: true) { action in 53 | // Do something. 54 | // If set to 'true' the handleImmediately, handler will be execute soon when Action was select. 55 | } 56 | let group1 = FloatingActionGroup(action: action1) 57 | let group2 = FloatingActionGroup(action: action2, action3) 58 | FloatingActionSheetController(actionGroup: group1, group2) 59 | .present(in: self) 60 | ``` 61 | We have prepared a rich initializer to each Class. Please refer to the demo app and source code. 62 | 63 | ### animations 64 | Custom animation styles. 65 | Please check the overview or demo app for animation details 66 | ```swift 67 | public enum AnimationStyle { 68 | case slideUp 69 | case slideDown 70 | case slideLeft 71 | case slideRight 72 | case pop 73 | } 74 | ``` 75 | How to use 76 | ```swift 77 | FloatingActionSheetController(actionGroup: group, animationStyle: .slideLeft) 78 | ``` 79 | ```swift 80 | let actionSheet = FloatingActionSheetController(actionGroup: group) 81 | actionSheet.animationStyle = .slideLeft 82 | ``` 83 | 84 | ### appearance customization 85 | ```swift 86 | let actionSheet = FloatingActionSheetController(actionGroup: group1) 87 | // Color of action sheet 88 | actionSheet.itemTintColor = .white 89 | // Color of title texts 90 | actionSheet.textColor = .black 91 | // Font of title texts 92 | actionSheet.font = .boldSystemFont(ofSize: 15) 93 | // background dimming color 94 | actionSheet.dimmingColor = UIColor(white: 1, alpha: 0.7) 95 | ``` 96 | If you wants to customize FloatingAction individually. 97 | ```swift 98 | var action = FloatingAction(title: "title") { action in 99 | // Do something. 100 | } 101 | action.tintColor = .whiteColor() 102 | action.textColor = .blackColor() 103 | action.font = .boldSystemFont(ofSize: 15) 104 | ``` 105 | 106 | ## License 107 | FloatingActionSheetController is available under the MIT license. See the LICENSE file for more info. 108 | --------------------------------------------------------------------------------