├── DeformationButton.gif ├── DeformationButton2.gif ├── DeformationButtonSwift.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── DeformationButtonSwift.xccheckout └── xcuserdata │ └── LuciusLu.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── DeformationButtonSwift.xcscheme │ └── xcschememanagement.plist ├── DeformationButtonSwift ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── DeformationButton │ ├── DeformationButton.swift │ └── MozMaterialDesignSpinner-swift │ │ └── MozMaterialDesignSpinner.swift ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Resources │ ├── 微信logo@2x.png │ └── 微博logo@2x.png └── ViewController.swift ├── DeformationButtonSwiftTests ├── DeformationButtonSwiftTests.swift └── Info.plist └── README.md /DeformationButton.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuciusLu/DeformationButtonSwift/ddf1ac766affa7d221247f375d34f658004737a8/DeformationButton.gif -------------------------------------------------------------------------------- /DeformationButton2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuciusLu/DeformationButtonSwift/ddf1ac766affa7d221247f375d34f658004737a8/DeformationButton2.gif -------------------------------------------------------------------------------- /DeformationButtonSwift.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 82DCDA6B1B54BFF400F6189E /* 微信logo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 82DCDA691B54BFF400F6189E /* 微信logo@2x.png */; }; 11 | 82DCDA6C1B54BFF400F6189E /* 微博logo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 82DCDA6A1B54BFF400F6189E /* 微博logo@2x.png */; }; 12 | 82DCDA751B5503FC00F6189E /* MozMaterialDesignSpinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DCDA741B5503FC00F6189E /* MozMaterialDesignSpinner.swift */; }; 13 | 82DCDA771B55042300F6189E /* DeformationButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DCDA761B55042300F6189E /* DeformationButton.swift */; }; 14 | 82FCECF21B54A48A0004790E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FCECF11B54A48A0004790E /* AppDelegate.swift */; }; 15 | 82FCECF41B54A48A0004790E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FCECF31B54A48A0004790E /* ViewController.swift */; }; 16 | 82FCECF71B54A48A0004790E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82FCECF51B54A48A0004790E /* Main.storyboard */; }; 17 | 82FCECF91B54A48A0004790E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 82FCECF81B54A48A0004790E /* Images.xcassets */; }; 18 | 82FCECFC1B54A48A0004790E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 82FCECFA1B54A48A0004790E /* LaunchScreen.xib */; }; 19 | 82FCED081B54A48A0004790E /* DeformationButtonSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FCED071B54A48A0004790E /* DeformationButtonSwiftTests.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 82FCED021B54A48A0004790E /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 82FCECE41B54A48A0004790E /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 82FCECEB1B54A48A0004790E; 28 | remoteInfo = DeformationButtonSwift; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 82DCDA691B54BFF400F6189E /* 微信logo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "微信logo@2x.png"; sourceTree = ""; }; 34 | 82DCDA6A1B54BFF400F6189E /* 微博logo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "微博logo@2x.png"; sourceTree = ""; }; 35 | 82DCDA741B5503FC00F6189E /* MozMaterialDesignSpinner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MozMaterialDesignSpinner.swift; sourceTree = ""; }; 36 | 82DCDA761B55042300F6189E /* DeformationButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeformationButton.swift; sourceTree = ""; }; 37 | 82FCECEC1B54A48A0004790E /* DeformationButtonSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DeformationButtonSwift.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 82FCECF01B54A48A0004790E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 39 | 82FCECF11B54A48A0004790E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 82FCECF31B54A48A0004790E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 41 | 82FCECF61B54A48A0004790E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 82FCECF81B54A48A0004790E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 43 | 82FCECFB1B54A48A0004790E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 44 | 82FCED011B54A48A0004790E /* DeformationButtonSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DeformationButtonSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 82FCED061B54A48A0004790E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | 82FCED071B54A48A0004790E /* DeformationButtonSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeformationButtonSwiftTests.swift; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 82FCECE91B54A48A0004790E /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | 82FCECFE1B54A48A0004790E /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 82DCDA671B54BFF400F6189E /* DeformationButton */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 82DCDA731B5503FC00F6189E /* MozMaterialDesignSpinner-swift */, 71 | 82DCDA761B55042300F6189E /* DeformationButton.swift */, 72 | ); 73 | path = DeformationButton; 74 | sourceTree = ""; 75 | }; 76 | 82DCDA681B54BFF400F6189E /* Resources */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 82DCDA691B54BFF400F6189E /* 微信logo@2x.png */, 80 | 82DCDA6A1B54BFF400F6189E /* 微博logo@2x.png */, 81 | ); 82 | path = Resources; 83 | sourceTree = ""; 84 | }; 85 | 82DCDA731B5503FC00F6189E /* MozMaterialDesignSpinner-swift */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 82DCDA741B5503FC00F6189E /* MozMaterialDesignSpinner.swift */, 89 | ); 90 | path = "MozMaterialDesignSpinner-swift"; 91 | sourceTree = ""; 92 | }; 93 | 82FCECE31B54A48A0004790E = { 94 | isa = PBXGroup; 95 | children = ( 96 | 82FCECEE1B54A48A0004790E /* DeformationButtonSwift */, 97 | 82FCED041B54A48A0004790E /* DeformationButtonSwiftTests */, 98 | 82FCECED1B54A48A0004790E /* Products */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 82FCECED1B54A48A0004790E /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 82FCECEC1B54A48A0004790E /* DeformationButtonSwift.app */, 106 | 82FCED011B54A48A0004790E /* DeformationButtonSwiftTests.xctest */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | 82FCECEE1B54A48A0004790E /* DeformationButtonSwift */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 82DCDA681B54BFF400F6189E /* Resources */, 115 | 82DCDA671B54BFF400F6189E /* DeformationButton */, 116 | 82FCECF11B54A48A0004790E /* AppDelegate.swift */, 117 | 82FCECF31B54A48A0004790E /* ViewController.swift */, 118 | 82FCECF51B54A48A0004790E /* Main.storyboard */, 119 | 82FCECF81B54A48A0004790E /* Images.xcassets */, 120 | 82FCECFA1B54A48A0004790E /* LaunchScreen.xib */, 121 | 82FCECEF1B54A48A0004790E /* Supporting Files */, 122 | ); 123 | path = DeformationButtonSwift; 124 | sourceTree = ""; 125 | }; 126 | 82FCECEF1B54A48A0004790E /* Supporting Files */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 82FCECF01B54A48A0004790E /* Info.plist */, 130 | ); 131 | name = "Supporting Files"; 132 | sourceTree = ""; 133 | }; 134 | 82FCED041B54A48A0004790E /* DeformationButtonSwiftTests */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 82FCED071B54A48A0004790E /* DeformationButtonSwiftTests.swift */, 138 | 82FCED051B54A48A0004790E /* Supporting Files */, 139 | ); 140 | path = DeformationButtonSwiftTests; 141 | sourceTree = ""; 142 | }; 143 | 82FCED051B54A48A0004790E /* Supporting Files */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 82FCED061B54A48A0004790E /* Info.plist */, 147 | ); 148 | name = "Supporting Files"; 149 | sourceTree = ""; 150 | }; 151 | /* End PBXGroup section */ 152 | 153 | /* Begin PBXNativeTarget section */ 154 | 82FCECEB1B54A48A0004790E /* DeformationButtonSwift */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = 82FCED0B1B54A48A0004790E /* Build configuration list for PBXNativeTarget "DeformationButtonSwift" */; 157 | buildPhases = ( 158 | 82FCECE81B54A48A0004790E /* Sources */, 159 | 82FCECE91B54A48A0004790E /* Frameworks */, 160 | 82FCECEA1B54A48A0004790E /* Resources */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | ); 166 | name = DeformationButtonSwift; 167 | productName = DeformationButtonSwift; 168 | productReference = 82FCECEC1B54A48A0004790E /* DeformationButtonSwift.app */; 169 | productType = "com.apple.product-type.application"; 170 | }; 171 | 82FCED001B54A48A0004790E /* DeformationButtonSwiftTests */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 82FCED0E1B54A48A0004790E /* Build configuration list for PBXNativeTarget "DeformationButtonSwiftTests" */; 174 | buildPhases = ( 175 | 82FCECFD1B54A48A0004790E /* Sources */, 176 | 82FCECFE1B54A48A0004790E /* Frameworks */, 177 | 82FCECFF1B54A48A0004790E /* Resources */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | 82FCED031B54A48A0004790E /* PBXTargetDependency */, 183 | ); 184 | name = DeformationButtonSwiftTests; 185 | productName = DeformationButtonSwiftTests; 186 | productReference = 82FCED011B54A48A0004790E /* DeformationButtonSwiftTests.xctest */; 187 | productType = "com.apple.product-type.bundle.unit-test"; 188 | }; 189 | /* End PBXNativeTarget section */ 190 | 191 | /* Begin PBXProject section */ 192 | 82FCECE41B54A48A0004790E /* Project object */ = { 193 | isa = PBXProject; 194 | attributes = { 195 | LastSwiftMigration = 0710; 196 | LastSwiftUpdateCheck = 0710; 197 | LastUpgradeCheck = 0640; 198 | ORGANIZATIONNAME = Moz; 199 | TargetAttributes = { 200 | 82FCECEB1B54A48A0004790E = { 201 | CreatedOnToolsVersion = 6.4; 202 | }; 203 | 82FCED001B54A48A0004790E = { 204 | CreatedOnToolsVersion = 6.4; 205 | TestTargetID = 82FCECEB1B54A48A0004790E; 206 | }; 207 | }; 208 | }; 209 | buildConfigurationList = 82FCECE71B54A48A0004790E /* Build configuration list for PBXProject "DeformationButtonSwift" */; 210 | compatibilityVersion = "Xcode 3.2"; 211 | developmentRegion = English; 212 | hasScannedForEncodings = 0; 213 | knownRegions = ( 214 | en, 215 | Base, 216 | ); 217 | mainGroup = 82FCECE31B54A48A0004790E; 218 | productRefGroup = 82FCECED1B54A48A0004790E /* Products */; 219 | projectDirPath = ""; 220 | projectRoot = ""; 221 | targets = ( 222 | 82FCECEB1B54A48A0004790E /* DeformationButtonSwift */, 223 | 82FCED001B54A48A0004790E /* DeformationButtonSwiftTests */, 224 | ); 225 | }; 226 | /* End PBXProject section */ 227 | 228 | /* Begin PBXResourcesBuildPhase section */ 229 | 82FCECEA1B54A48A0004790E /* Resources */ = { 230 | isa = PBXResourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 82FCECF71B54A48A0004790E /* Main.storyboard in Resources */, 234 | 82FCECFC1B54A48A0004790E /* LaunchScreen.xib in Resources */, 235 | 82DCDA6B1B54BFF400F6189E /* 微信logo@2x.png in Resources */, 236 | 82FCECF91B54A48A0004790E /* Images.xcassets in Resources */, 237 | 82DCDA6C1B54BFF400F6189E /* 微博logo@2x.png in Resources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | 82FCECFF1B54A48A0004790E /* Resources */ = { 242 | isa = PBXResourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXResourcesBuildPhase section */ 249 | 250 | /* Begin PBXSourcesBuildPhase section */ 251 | 82FCECE81B54A48A0004790E /* Sources */ = { 252 | isa = PBXSourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | 82DCDA751B5503FC00F6189E /* MozMaterialDesignSpinner.swift in Sources */, 256 | 82FCECF41B54A48A0004790E /* ViewController.swift in Sources */, 257 | 82DCDA771B55042300F6189E /* DeformationButton.swift in Sources */, 258 | 82FCECF21B54A48A0004790E /* AppDelegate.swift in Sources */, 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | }; 262 | 82FCECFD1B54A48A0004790E /* Sources */ = { 263 | isa = PBXSourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | 82FCED081B54A48A0004790E /* DeformationButtonSwiftTests.swift in Sources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | /* End PBXSourcesBuildPhase section */ 271 | 272 | /* Begin PBXTargetDependency section */ 273 | 82FCED031B54A48A0004790E /* PBXTargetDependency */ = { 274 | isa = PBXTargetDependency; 275 | target = 82FCECEB1B54A48A0004790E /* DeformationButtonSwift */; 276 | targetProxy = 82FCED021B54A48A0004790E /* PBXContainerItemProxy */; 277 | }; 278 | /* End PBXTargetDependency section */ 279 | 280 | /* Begin PBXVariantGroup section */ 281 | 82FCECF51B54A48A0004790E /* Main.storyboard */ = { 282 | isa = PBXVariantGroup; 283 | children = ( 284 | 82FCECF61B54A48A0004790E /* Base */, 285 | ); 286 | name = Main.storyboard; 287 | sourceTree = ""; 288 | }; 289 | 82FCECFA1B54A48A0004790E /* LaunchScreen.xib */ = { 290 | isa = PBXVariantGroup; 291 | children = ( 292 | 82FCECFB1B54A48A0004790E /* Base */, 293 | ); 294 | name = LaunchScreen.xib; 295 | sourceTree = ""; 296 | }; 297 | /* End PBXVariantGroup section */ 298 | 299 | /* Begin XCBuildConfiguration section */ 300 | 82FCED091B54A48A0004790E /* Debug */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | ALWAYS_SEARCH_USER_PATHS = NO; 304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 305 | CLANG_CXX_LIBRARY = "libc++"; 306 | CLANG_ENABLE_MODULES = YES; 307 | CLANG_ENABLE_OBJC_ARC = YES; 308 | CLANG_WARN_BOOL_CONVERSION = YES; 309 | CLANG_WARN_CONSTANT_CONVERSION = YES; 310 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 311 | CLANG_WARN_EMPTY_BODY = YES; 312 | CLANG_WARN_ENUM_CONVERSION = YES; 313 | CLANG_WARN_INT_CONVERSION = YES; 314 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 315 | CLANG_WARN_UNREACHABLE_CODE = YES; 316 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 317 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 318 | COPY_PHASE_STRIP = NO; 319 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 320 | ENABLE_STRICT_OBJC_MSGSEND = YES; 321 | GCC_C_LANGUAGE_STANDARD = gnu99; 322 | GCC_DYNAMIC_NO_PIC = NO; 323 | GCC_NO_COMMON_BLOCKS = YES; 324 | GCC_OPTIMIZATION_LEVEL = 0; 325 | GCC_PREPROCESSOR_DEFINITIONS = ( 326 | "DEBUG=1", 327 | "$(inherited)", 328 | ); 329 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 337 | MTL_ENABLE_DEBUG_INFO = YES; 338 | ONLY_ACTIVE_ARCH = YES; 339 | SDKROOT = iphoneos; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 341 | }; 342 | name = Debug; 343 | }; 344 | 82FCED0A1B54A48A0004790E /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ALWAYS_SEARCH_USER_PATHS = NO; 348 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 349 | CLANG_CXX_LIBRARY = "libc++"; 350 | CLANG_ENABLE_MODULES = YES; 351 | CLANG_ENABLE_OBJC_ARC = YES; 352 | CLANG_WARN_BOOL_CONVERSION = YES; 353 | CLANG_WARN_CONSTANT_CONVERSION = YES; 354 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 355 | CLANG_WARN_EMPTY_BODY = YES; 356 | CLANG_WARN_ENUM_CONVERSION = YES; 357 | CLANG_WARN_INT_CONVERSION = YES; 358 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 359 | CLANG_WARN_UNREACHABLE_CODE = YES; 360 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 361 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 362 | COPY_PHASE_STRIP = NO; 363 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 364 | ENABLE_NS_ASSERTIONS = NO; 365 | ENABLE_STRICT_OBJC_MSGSEND = YES; 366 | GCC_C_LANGUAGE_STANDARD = gnu99; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 369 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 370 | GCC_WARN_UNDECLARED_SELECTOR = YES; 371 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 372 | GCC_WARN_UNUSED_FUNCTION = YES; 373 | GCC_WARN_UNUSED_VARIABLE = YES; 374 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 375 | MTL_ENABLE_DEBUG_INFO = NO; 376 | SDKROOT = iphoneos; 377 | VALIDATE_PRODUCT = YES; 378 | }; 379 | name = Release; 380 | }; 381 | 82FCED0C1B54A48A0004790E /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 385 | INFOPLIST_FILE = DeformationButtonSwift/Info.plist; 386 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | }; 389 | name = Debug; 390 | }; 391 | 82FCED0D1B54A48A0004790E /* Release */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 395 | INFOPLIST_FILE = DeformationButtonSwift/Info.plist; 396 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 397 | PRODUCT_NAME = "$(TARGET_NAME)"; 398 | }; 399 | name = Release; 400 | }; 401 | 82FCED0F1B54A48A0004790E /* Debug */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | BUNDLE_LOADER = "$(TEST_HOST)"; 405 | FRAMEWORK_SEARCH_PATHS = ( 406 | "$(SDKROOT)/Developer/Library/Frameworks", 407 | "$(inherited)", 408 | ); 409 | GCC_PREPROCESSOR_DEFINITIONS = ( 410 | "DEBUG=1", 411 | "$(inherited)", 412 | ); 413 | INFOPLIST_FILE = DeformationButtonSwiftTests/Info.plist; 414 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DeformationButtonSwift.app/DeformationButtonSwift"; 417 | }; 418 | name = Debug; 419 | }; 420 | 82FCED101B54A48A0004790E /* Release */ = { 421 | isa = XCBuildConfiguration; 422 | buildSettings = { 423 | BUNDLE_LOADER = "$(TEST_HOST)"; 424 | FRAMEWORK_SEARCH_PATHS = ( 425 | "$(SDKROOT)/Developer/Library/Frameworks", 426 | "$(inherited)", 427 | ); 428 | INFOPLIST_FILE = DeformationButtonSwiftTests/Info.plist; 429 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 430 | PRODUCT_NAME = "$(TARGET_NAME)"; 431 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DeformationButtonSwift.app/DeformationButtonSwift"; 432 | }; 433 | name = Release; 434 | }; 435 | /* End XCBuildConfiguration section */ 436 | 437 | /* Begin XCConfigurationList section */ 438 | 82FCECE71B54A48A0004790E /* Build configuration list for PBXProject "DeformationButtonSwift" */ = { 439 | isa = XCConfigurationList; 440 | buildConfigurations = ( 441 | 82FCED091B54A48A0004790E /* Debug */, 442 | 82FCED0A1B54A48A0004790E /* Release */, 443 | ); 444 | defaultConfigurationIsVisible = 0; 445 | defaultConfigurationName = Release; 446 | }; 447 | 82FCED0B1B54A48A0004790E /* Build configuration list for PBXNativeTarget "DeformationButtonSwift" */ = { 448 | isa = XCConfigurationList; 449 | buildConfigurations = ( 450 | 82FCED0C1B54A48A0004790E /* Debug */, 451 | 82FCED0D1B54A48A0004790E /* Release */, 452 | ); 453 | defaultConfigurationIsVisible = 0; 454 | defaultConfigurationName = Release; 455 | }; 456 | 82FCED0E1B54A48A0004790E /* Build configuration list for PBXNativeTarget "DeformationButtonSwiftTests" */ = { 457 | isa = XCConfigurationList; 458 | buildConfigurations = ( 459 | 82FCED0F1B54A48A0004790E /* Debug */, 460 | 82FCED101B54A48A0004790E /* Release */, 461 | ); 462 | defaultConfigurationIsVisible = 0; 463 | defaultConfigurationName = Release; 464 | }; 465 | /* End XCConfigurationList section */ 466 | }; 467 | rootObject = 82FCECE41B54A48A0004790E /* Project object */; 468 | } 469 | -------------------------------------------------------------------------------- /DeformationButtonSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DeformationButtonSwift.xcodeproj/project.xcworkspace/xcshareddata/DeformationButtonSwift.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 98DCA20E-CE68-42F6-867A-2F76A637443F 9 | IDESourceControlProjectName 10 | DeformationButtonSwift 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 716A17ED369C799A3CB164FF04FA77AF72573A15 14 | https://github.com/LuciusLu/DeformationButtonSwift.git 15 | 16 | IDESourceControlProjectPath 17 | DeformationButtonSwift.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 716A17ED369C799A3CB164FF04FA77AF72573A15 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/LuciusLu/DeformationButtonSwift.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 716A17ED369C799A3CB164FF04FA77AF72573A15 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 716A17ED369C799A3CB164FF04FA77AF72573A15 36 | IDESourceControlWCCName 37 | DeformationButtonSwift 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /DeformationButtonSwift.xcodeproj/xcuserdata/LuciusLu.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /DeformationButtonSwift.xcodeproj/xcuserdata/LuciusLu.xcuserdatad/xcschemes/DeformationButtonSwift.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /DeformationButtonSwift.xcodeproj/xcuserdata/LuciusLu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DeformationButtonSwift.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 82FCECEB1B54A48A0004790E 16 | 17 | primary 18 | 19 | 20 | 82FCED001B54A48A0004790E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /DeformationButtonSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DeformationButtonSwift 4 | // 5 | // Created by 陆浩志 on 15/7/14. 6 | // Copyright (c) 2015年 Moz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /DeformationButtonSwift/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /DeformationButtonSwift/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 | -------------------------------------------------------------------------------- /DeformationButtonSwift/DeformationButton/DeformationButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeformationButton.swift 3 | // DeformationButtonSwift 4 | // 5 | // Created by 陆浩志 on 15/7/14. 6 | // Copyright (c) 2015年 Moz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | //@property(nonatomic, assign)BOOL isLoading; 11 | //@property(nonatomic, retain)MMMaterialDesignSpinner *spinnerView; 12 | //@property(nonatomic, retain)UIColor *contentColor; 13 | //@property(nonatomic, retain)UIColor *progressColor; 14 | // 15 | //@property(nonatomic, retain)UIButton *forDisplayButton; 16 | class DeformationButton: UIControl { 17 | 18 | var defaultW:CGFloat! 19 | var defaultH:CGFloat! 20 | var defaultR:CGFloat! 21 | var scale:CGFloat! 22 | var bgView:UIView! 23 | 24 | var spinnerView:MozMaterialDesignSpinner! 25 | var forDisplayButton:UIButton! 26 | 27 | var btnBackgroundImage:UIImage? 28 | 29 | var _isLoading:Bool = false 30 | var isLoading:Bool{ 31 | get{ return _isLoading } 32 | set{ 33 | _isLoading = newValue 34 | if _isLoading { 35 | self.startLoading() 36 | }else{ 37 | self.stopLoading() 38 | } 39 | } 40 | } 41 | 42 | var _contentColor:UIColor! 43 | var contentColor:UIColor { 44 | get{ 45 | return _contentColor 46 | } 47 | set{ 48 | _contentColor = newValue 49 | } 50 | } 51 | 52 | var _progressColor:UIColor! 53 | var progressColor:UIColor { 54 | get{ 55 | return _progressColor 56 | } 57 | set{ 58 | _progressColor = newValue 59 | } 60 | } 61 | 62 | override var frame: CGRect { 63 | get { 64 | let _frame = super.frame 65 | 66 | return _frame 67 | } 68 | set { 69 | super.frame = newValue 70 | } 71 | } 72 | 73 | override var selected: Bool{ 74 | get{return super.selected} 75 | set{ 76 | super.selected = newValue 77 | self.forDisplayButton.selected = newValue 78 | } 79 | } 80 | 81 | override var highlighted: Bool{ 82 | get{return super.highlighted} 83 | set{ 84 | super.highlighted = newValue 85 | self.forDisplayButton.highlighted = newValue 86 | } 87 | } 88 | 89 | init(frame: CGRect, color:UIColor) { 90 | super.init(frame: frame) 91 | initSettingWithColor(color) 92 | } 93 | 94 | required init?(coder aDecoder: NSCoder) { 95 | super.init(coder: aDecoder) 96 | initSettingWithColor(self.tintColor) 97 | } 98 | 99 | func imageWithColor(color:UIColor, cornerRadius:CGFloat) -> UIImage{ 100 | let rect = CGRectMake(0, 0, cornerRadius*2+10, cornerRadius*2+10) 101 | 102 | let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius) 103 | path.lineWidth = 0 104 | 105 | UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) 106 | let context = UIGraphicsGetCurrentContext() 107 | CGContextSetFillColorWithColor(context, color.CGColor) 108 | 109 | path.fill() 110 | path.stroke() 111 | path.addClip() 112 | 113 | let image = UIGraphicsGetImageFromCurrentImageContext(); 114 | UIGraphicsEndImageContext(); 115 | return image; 116 | } 117 | 118 | func initSettingWithColor(color:UIColor) { 119 | self.scale = 1.2 120 | self.bgView = UIView(frame: self.bounds) 121 | self.bgView.backgroundColor = color 122 | self.bgView.userInteractionEnabled = false 123 | self.bgView.hidden = true 124 | self.bgView.layer.cornerRadius = CGFloat(3) 125 | self.addSubview(self.bgView) 126 | 127 | defaultW = self.bgView.frame.width 128 | defaultH = self.bgView.frame.height 129 | defaultR = self.bgView.layer.cornerRadius 130 | 131 | self.spinnerView = MozMaterialDesignSpinner(frame: CGRectMake(0 , 0, defaultH*0.8, defaultH*0.8)) 132 | self.spinnerView.tintColor = UIColor.whiteColor() 133 | self.spinnerView.lineWidth = 2 134 | self.spinnerView.center = CGPointMake(CGRectGetMidX(self.layer.bounds), CGRectGetMidY(self.layer.bounds)) 135 | self.spinnerView.translatesAutoresizingMaskIntoConstraints = false 136 | self.spinnerView.userInteractionEnabled = false 137 | 138 | self.addSubview(self.spinnerView) 139 | 140 | self.addTarget(self, action: "loadingAction", forControlEvents: UIControlEvents.TouchUpInside) 141 | 142 | self.forDisplayButton = UIButton(frame: self.bounds) 143 | self.forDisplayButton.userInteractionEnabled = false 144 | 145 | let image = imageWithColor(color, cornerRadius: 3) 146 | self.forDisplayButton.setBackgroundImage(image.resizableImageWithCapInsets(UIEdgeInsetsMake(10, 10, 10, 10)), forState: UIControlState.Normal) 147 | 148 | self.addSubview(self.forDisplayButton) 149 | self.contentColor = color; 150 | } 151 | 152 | func loadingAction() { 153 | if (self.isLoading) { 154 | self.stopLoading() 155 | }else{ 156 | self.startLoading() 157 | } 158 | } 159 | 160 | func startLoading(){ 161 | if (btnBackgroundImage == nil) { 162 | btnBackgroundImage = self.forDisplayButton.backgroundImageForState(UIControlState.Normal) 163 | } 164 | 165 | _isLoading = true; 166 | self.bgView.hidden = false 167 | 168 | let animation = CABasicAnimation(keyPath: "cornerRadius") 169 | animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 170 | animation.fromValue = defaultR 171 | animation.toValue = defaultH*scale*0.5 172 | animation.duration = 0.3 173 | self.bgView.layer.cornerRadius = defaultH*scale*0.5 174 | self.bgView.layer.addAnimation(animation, forKey: "cornerRadius") 175 | 176 | self.forDisplayButton.setBackgroundImage(nil, forState: UIControlState.Normal) 177 | 178 | UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in 179 | self.bgView.layer.bounds = CGRectMake(0, 0, self.defaultW*self.scale, self.defaultH*self.scale) 180 | }) { (Bool) -> Void in 181 | if self._isLoading { 182 | UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in 183 | self.bgView.layer.bounds = CGRectMake(0, 0, self.defaultH*self.scale, self.defaultH*self.scale) 184 | self.forDisplayButton.transform = CGAffineTransformMakeScale(0.1, 0.1) 185 | self.forDisplayButton.alpha = 0 186 | }) { (Bool) -> Void in 187 | if self._isLoading { 188 | self.forDisplayButton.hidden = true 189 | self.spinnerView.startAnimating() 190 | } 191 | } 192 | 193 | } 194 | } 195 | } 196 | 197 | func stopLoading(){ 198 | _isLoading = false; 199 | self.spinnerView.stopAnimating() 200 | self.forDisplayButton.hidden = false 201 | 202 | UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in 203 | self.forDisplayButton.transform = CGAffineTransformMakeScale(1, 1); 204 | self.forDisplayButton.alpha = 1; 205 | }) { (Bool) -> Void in 206 | } 207 | 208 | let animation = CABasicAnimation(keyPath: "cornerRadius") 209 | animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 210 | animation.fromValue = defaultH*scale*0.5 211 | animation.toValue = defaultR 212 | animation.duration = 0.3 213 | self.bgView.layer.cornerRadius = defaultR 214 | self.bgView.layer.addAnimation(animation, forKey: "cornerRadius") 215 | 216 | UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in 217 | self.bgView.layer.bounds = CGRectMake(0, 0, self.defaultW*self.scale, self.defaultH*self.scale); 218 | }) { (Bool) -> Void in 219 | if !self._isLoading { 220 | let animation = CABasicAnimation(keyPath: "cornerRadius") 221 | animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 222 | animation.fromValue = self.bgView.layer.cornerRadius 223 | animation.toValue = self.defaultR 224 | animation.duration = 0.2 225 | self.bgView.layer.cornerRadius = self.defaultR 226 | self.bgView.layer.addAnimation(animation, forKey: "cornerRadius") 227 | 228 | UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in 229 | self.bgView.layer.bounds = CGRectMake(0, 0, self.defaultW, self.defaultH); 230 | }) { (Bool) -> Void in 231 | if !self._isLoading { 232 | if (self.btnBackgroundImage != nil) { 233 | self.forDisplayButton.setBackgroundImage(self.btnBackgroundImage, forState: UIControlState.Normal) 234 | } 235 | self.bgView.hidden = true 236 | } 237 | } 238 | } 239 | } 240 | } 241 | 242 | 243 | 244 | /* 245 | // Only override drawRect: if you perform custom drawing. 246 | // An empty implementation adversely affects performance during animation. 247 | override func drawRect(rect: CGRect) { 248 | // Drawing code 249 | } 250 | */ 251 | 252 | } 253 | -------------------------------------------------------------------------------- /DeformationButtonSwift/DeformationButton/MozMaterialDesignSpinner-swift/MozMaterialDesignSpinner.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MozMaterialDesignSpinner.swift 3 | // DeformationButtonSwift 4 | // 5 | // Created by 陆浩志 on 15/7/14. 6 | // Copyright (c) 2015年 Moz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MozMaterialDesignSpinner: UIView { 12 | 13 | let kAnimationStrokeKey:String! = "animationStrokeKey" 14 | let kAnimationRotationKey:String! = "animationRotationKey" 15 | 16 | var _progressLayer:CAShapeLayer! 17 | var progressLayer:CAShapeLayer { 18 | get{ 19 | if (_progressLayer == nil){ 20 | _progressLayer = CAShapeLayer() 21 | _progressLayer.strokeColor = self.tintColor.CGColor 22 | _progressLayer.fillColor = nil 23 | _progressLayer.lineWidth = 2 24 | // _progressLayer.shouldRasterize = true 25 | } 26 | return _progressLayer 27 | } 28 | set{ self._progressLayer = newValue } 29 | } 30 | 31 | var isAnimating:Bool = false 32 | var _hidesWhenStopped:Bool = true 33 | let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 34 | 35 | var lineWidth:CGFloat{ 36 | get{ return self.progressLayer.lineWidth } 37 | set{ self.progressLayer.lineWidth = newValue 38 | updatePath() } 39 | } 40 | 41 | override init(frame: CGRect) { 42 | super.init(frame: frame) 43 | initialize() 44 | } 45 | 46 | required init?(coder aDecoder: NSCoder) { 47 | super.init(coder: aDecoder) 48 | initialize() 49 | } 50 | 51 | func initialize() { 52 | self.layer.addSublayer(self.progressLayer) 53 | 54 | self.progressLayer.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) 55 | updatePath() 56 | 57 | NSNotificationCenter.defaultCenter().addObserver(self, selector: "resetAnimations", name: UIApplicationDidBecomeActiveNotification, object: nil) 58 | } 59 | 60 | deinit{ 61 | NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidBecomeActiveNotification, object: nil) 62 | } 63 | 64 | override func tintColorDidChange() { 65 | super.tintColorDidChange() 66 | self.progressLayer.strokeColor = self.tintColor.CGColor 67 | } 68 | 69 | func resetAnimations() { 70 | if self.isAnimating { 71 | stopAnimating() 72 | startAnimating() 73 | } 74 | } 75 | 76 | func setAnimating(animate:Bool) { 77 | animate ? startAnimating() : stopAnimating() 78 | } 79 | 80 | func startAnimating() { 81 | if self.isAnimating { 82 | return 83 | } 84 | 85 | let animation = CABasicAnimation() 86 | animation.keyPath = "transform.rotation" 87 | animation.duration = 4.0 88 | animation.fromValue = 0 89 | animation.toValue = 2*M_PI 90 | animation.repeatCount = Float(NSIntegerMax) 91 | self.progressLayer.addAnimation(animation, forKey: kAnimationRotationKey) 92 | 93 | let headAnimation = CABasicAnimation() 94 | headAnimation.keyPath = "strokeStart"; 95 | headAnimation.duration = 1.0 96 | headAnimation.fromValue = 0 97 | headAnimation.toValue = 0.25 98 | headAnimation.timingFunction = self.timingFunction 99 | 100 | let tailAnimation = CABasicAnimation() 101 | tailAnimation.keyPath = "strokeEnd" 102 | tailAnimation.duration = 1.0 103 | tailAnimation.fromValue = 0 104 | tailAnimation.toValue = 1.0 105 | tailAnimation.timingFunction = self.timingFunction 106 | 107 | let endHeadAnimation = CABasicAnimation() 108 | endHeadAnimation.keyPath = "strokeStart" 109 | endHeadAnimation.beginTime = 1.0 110 | endHeadAnimation.duration = 0.5 111 | endHeadAnimation.fromValue = 0.25 112 | endHeadAnimation.toValue = 1.0 113 | endHeadAnimation.timingFunction = self.timingFunction 114 | 115 | let endTailAnimation = CABasicAnimation() 116 | endTailAnimation.keyPath = "strokeEnd" 117 | endTailAnimation.beginTime = 1.0 118 | endTailAnimation.duration = 0.5 119 | endTailAnimation.fromValue = 1.0 120 | endTailAnimation.toValue = 1.0 121 | endTailAnimation.timingFunction = self.timingFunction 122 | 123 | let animations = CAAnimationGroup() 124 | animations.duration = 1.5 125 | animations.animations = [headAnimation, tailAnimation, endHeadAnimation, endTailAnimation] 126 | animations.repeatCount = Float(NSIntegerMax) 127 | self.progressLayer.addAnimation(animations, forKey: kAnimationStrokeKey) 128 | 129 | self.isAnimating = true 130 | 131 | if _hidesWhenStopped { 132 | self.hidden = false 133 | } 134 | } 135 | 136 | func stopAnimating() { 137 | if !self.isAnimating { 138 | return 139 | } 140 | 141 | self.progressLayer.removeAnimationForKey(kAnimationRotationKey) 142 | self.progressLayer.removeAnimationForKey(kAnimationStrokeKey) 143 | self.isAnimating = false 144 | 145 | if _hidesWhenStopped { 146 | self.hidden = true 147 | } 148 | 149 | } 150 | 151 | //MARK: - Private 152 | 153 | func updatePath() { 154 | // let acenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)) 155 | let aradius = min(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds) / 2) - self.progressLayer.lineWidth / 2 156 | let astartAngle = CGFloat(0) 157 | let aendAngle = CGFloat(2*M_PI) 158 | let path:UIBezierPath = UIBezierPath(arcCenter: center, radius: aradius, startAngle: astartAngle, endAngle: aendAngle, clockwise: true) 159 | 160 | self.progressLayer.path = path.CGPath 161 | self.progressLayer.strokeStart = 0.0 162 | self.progressLayer.strokeEnd = 0.0 163 | } 164 | 165 | //MARK: - Properties 166 | 167 | // func lineWidth() -> CGFloat{ 168 | // return self.progressLayer.lineWidth 169 | // } 170 | // 171 | // func setLineWidth(lineWidth:CGFloat){ 172 | // self.progressLayer.lineWidth = lineWidth 173 | // updatePath() 174 | // } 175 | 176 | func setHidesWhenStopped(hidesWhenStopped:Bool){ 177 | _hidesWhenStopped = hidesWhenStopped 178 | self.hidden = !self.isAnimating && hidesWhenStopped 179 | } 180 | 181 | /* 182 | // Only override drawRect: if you perform custom drawing. 183 | // An empty implementation adversely affects performance during animation. 184 | override func drawRect(rect: CGRect) { 185 | // Drawing code 186 | } 187 | */ 188 | 189 | } 190 | -------------------------------------------------------------------------------- /DeformationButtonSwift/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "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 | } -------------------------------------------------------------------------------- /DeformationButtonSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | moe.moz.$(PRODUCT_NAME:rfc1034identifier) 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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /DeformationButtonSwift/Resources/微信logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuciusLu/DeformationButtonSwift/ddf1ac766affa7d221247f375d34f658004737a8/DeformationButtonSwift/Resources/微信logo@2x.png -------------------------------------------------------------------------------- /DeformationButtonSwift/Resources/微博logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuciusLu/DeformationButtonSwift/ddf1ac766affa7d221247f375d34f658004737a8/DeformationButtonSwift/Resources/微博logo@2x.png -------------------------------------------------------------------------------- /DeformationButtonSwift/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // DeformationButtonSwift 4 | // 5 | // Created by 陆浩志 on 15/7/14. 6 | // Copyright (c) 2015年 Moz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | func getColor(hexColor:String)->UIColor{ 14 | var redInt:uint = 0 15 | var greenInt:uint = 0 16 | var blueInt:uint = 0 17 | var range = NSMakeRange(0, 2) 18 | 19 | NSScanner(string: (hexColor as NSString).substringWithRange(range)).scanHexInt(&redInt) 20 | range.location = 2 21 | NSScanner(string: (hexColor as NSString).substringWithRange(range)).scanHexInt(&greenInt) 22 | range.location = 4 23 | NSScanner(string: (hexColor as NSString).substringWithRange(range)).scanHexInt(&blueInt) 24 | 25 | return UIColor(red: (CGFloat(redInt)/255.0), green: (CGFloat(greenInt)/255.0), blue: (CGFloat(blueInt)/255.0), alpha: 1) 26 | } 27 | 28 | override func viewDidLoad() { 29 | super.viewDidLoad() 30 | 31 | let deformationBtn = DeformationButton(frame: CGRectMake(100, 100, 140, 36), color: getColor("e13536")) 32 | self.view.addSubview(deformationBtn) 33 | 34 | deformationBtn.forDisplayButton.setTitle("微博注册", forState: UIControlState.Normal) 35 | deformationBtn.forDisplayButton.titleLabel?.font = UIFont.systemFontOfSize(15); 36 | deformationBtn.forDisplayButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal) 37 | deformationBtn.forDisplayButton.titleEdgeInsets = UIEdgeInsetsMake(0, 6, 0, 0) 38 | deformationBtn.forDisplayButton.setImage(UIImage(named:"微博logo.png"), forState: UIControlState.Normal) 39 | 40 | deformationBtn.addTarget(self, action: "btnEvent", forControlEvents: UIControlEvents.TouchUpInside) 41 | } 42 | 43 | func btnEvent(){ 44 | print("btnEvent", terminator: "") 45 | } 46 | 47 | override func didReceiveMemoryWarning() { 48 | super.didReceiveMemoryWarning() 49 | // Dispose of any resources that can be recreated. 50 | } 51 | 52 | 53 | } 54 | 55 | -------------------------------------------------------------------------------- /DeformationButtonSwiftTests/DeformationButtonSwiftTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DeformationButtonSwiftTests.swift 3 | // DeformationButtonSwiftTests 4 | // 5 | // Created by 陆浩志 on 15/7/14. 6 | // Copyright (c) 2015年 Moz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class DeformationButtonSwiftTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /DeformationButtonSwiftTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | moe.moz.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## demo 2 | 3 | ![Alt text](/DeformationButton.gif) 4 | ![Alt text](/DeformationButton2.gif) 5 | 6 | --------------------------------------- 7 | ## code 8 | let deformationBtn = DeformationButton(frame: CGRectMake(100, 100, 140, 36), color: getColor("e13536")) 9 | self.view.addSubview(deformationBtn) 10 | 11 | deformationBtn.forDisplayButton.setTitle("微博注册", forState: UIControlState.Normal) 12 | deformationBtn.forDisplayButton.titleLabel?.font = UIFont.systemFontOfSize(15); 13 | deformationBtn.forDisplayButton.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal) 14 | deformationBtn.forDisplayButton.titleEdgeInsets = UIEdgeInsetsMake(0, 6, 0, 0) 15 | deformationBtn.forDisplayButton.setImage(UIImage(named:"微博logo.png"), forState: UIControlState.Normal) 16 | 17 | deformationBtn.addTarget(self, action: "btnEvent", forControlEvents: UIControlEvents.TouchUpInside) 18 | 19 | --------------------------------------- 20 | ### Thanks for [MMMaterialDesignSpinner] 21 | [MMMaterialDesignSpinner]: https://github.com/misterwell/MMMaterialDesignSpinner --------------------------------------------------------------------------------