├── .gitignore ├── Podfile ├── Podfile.lock ├── XYButton.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── xuyang.xcuserdatad │ └── xcschemes │ ├── XYButton.xcscheme │ └── xcschememanagement.plist └── XYButton ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj └── LaunchScreen.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── XYButton.h ├── XYButton.m └── main.m /.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 | *.xcworkspace 20 | !default.xcworkspace 21 | 22 | #CocoaPods 23 | Pods 24 | !Podfile 25 | !Podfile.lock -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'XYButton' do 5 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 6 | # use_frameworks! 7 | pod 'YYKit' 8 | # Pods for XYButton 9 | 10 | end 11 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - YYKit (1.0.9): 3 | - YYKit/no-arc (= 1.0.9) 4 | - YYKit/no-arc (1.0.9) 5 | 6 | DEPENDENCIES: 7 | - YYKit 8 | 9 | SPEC CHECKSUMS: 10 | YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7 11 | 12 | PODFILE CHECKSUM: e90dedfb99cb425214967eb05a12f17ced5ec005 13 | 14 | COCOAPODS: 1.2.1 15 | -------------------------------------------------------------------------------- /XYButton.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 29CF5D621EE186BF00847135 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CF5D611EE186BF00847135 /* main.m */; }; 11 | 29CF5D651EE186BF00847135 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CF5D641EE186BF00847135 /* AppDelegate.m */; }; 12 | 29CF5D681EE186BF00847135 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CF5D671EE186BF00847135 /* ViewController.m */; }; 13 | 29CF5D6D1EE186BF00847135 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29CF5D6C1EE186BF00847135 /* Assets.xcassets */; }; 14 | 29CF5D701EE186BF00847135 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29CF5D6E1EE186BF00847135 /* LaunchScreen.storyboard */; }; 15 | 29CF5D791EE186FF00847135 /* XYButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 29CF5D781EE186FF00847135 /* XYButton.m */; }; 16 | 4C36EF07FA5FDA55A730F8D8 /* libPods-XYButton.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 47CCA0F968778343F1D2B15B /* libPods-XYButton.a */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 0C6802F1D5BDA247523E7C2D /* Pods-XYButton.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XYButton.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XYButton/Pods-XYButton.debug.xcconfig"; sourceTree = ""; }; 21 | 29CF5D5D1EE186BF00847135 /* XYButton.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XYButton.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 29CF5D611EE186BF00847135 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 23 | 29CF5D631EE186BF00847135 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | 29CF5D641EE186BF00847135 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | 29CF5D661EE186BF00847135 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 26 | 29CF5D671EE186BF00847135 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 27 | 29CF5D6C1EE186BF00847135 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | 29CF5D6F1EE186BF00847135 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | 29CF5D711EE186BF00847135 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 29CF5D771EE186FF00847135 /* XYButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XYButton.h; sourceTree = ""; }; 31 | 29CF5D781EE186FF00847135 /* XYButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XYButton.m; sourceTree = ""; }; 32 | 43AF465BFE674505A4BC5081 /* Pods-XYButton.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XYButton.release.xcconfig"; path = "Pods/Target Support Files/Pods-XYButton/Pods-XYButton.release.xcconfig"; sourceTree = ""; }; 33 | 47CCA0F968778343F1D2B15B /* libPods-XYButton.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XYButton.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 29CF5D5A1EE186BF00847135 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | 4C36EF07FA5FDA55A730F8D8 /* libPods-XYButton.a in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 288ABEC51386A07C69D646FF /* Frameworks */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 47CCA0F968778343F1D2B15B /* libPods-XYButton.a */, 52 | ); 53 | name = Frameworks; 54 | sourceTree = ""; 55 | }; 56 | 29CF5D541EE186BF00847135 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 29CF5D5F1EE186BF00847135 /* XYButton */, 60 | 29CF5D5E1EE186BF00847135 /* Products */, 61 | A9DA82447BC3D9E095DFD566 /* Pods */, 62 | 288ABEC51386A07C69D646FF /* Frameworks */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | 29CF5D5E1EE186BF00847135 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 29CF5D5D1EE186BF00847135 /* XYButton.app */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | 29CF5D5F1EE186BF00847135 /* XYButton */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 29CF5D631EE186BF00847135 /* AppDelegate.h */, 78 | 29CF5D641EE186BF00847135 /* AppDelegate.m */, 79 | 29CF5D661EE186BF00847135 /* ViewController.h */, 80 | 29CF5D671EE186BF00847135 /* ViewController.m */, 81 | 29CF5D771EE186FF00847135 /* XYButton.h */, 82 | 29CF5D781EE186FF00847135 /* XYButton.m */, 83 | 29CF5D6C1EE186BF00847135 /* Assets.xcassets */, 84 | 29CF5D6E1EE186BF00847135 /* LaunchScreen.storyboard */, 85 | 29CF5D711EE186BF00847135 /* Info.plist */, 86 | 29CF5D601EE186BF00847135 /* Supporting Files */, 87 | ); 88 | path = XYButton; 89 | sourceTree = ""; 90 | }; 91 | 29CF5D601EE186BF00847135 /* Supporting Files */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 29CF5D611EE186BF00847135 /* main.m */, 95 | ); 96 | name = "Supporting Files"; 97 | sourceTree = ""; 98 | }; 99 | A9DA82447BC3D9E095DFD566 /* Pods */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 0C6802F1D5BDA247523E7C2D /* Pods-XYButton.debug.xcconfig */, 103 | 43AF465BFE674505A4BC5081 /* Pods-XYButton.release.xcconfig */, 104 | ); 105 | name = Pods; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXNativeTarget section */ 111 | 29CF5D5C1EE186BF00847135 /* XYButton */ = { 112 | isa = PBXNativeTarget; 113 | buildConfigurationList = 29CF5D741EE186BF00847135 /* Build configuration list for PBXNativeTarget "XYButton" */; 114 | buildPhases = ( 115 | 41AECF5BE87AA96CC6CDDCC2 /* [CP] Check Pods Manifest.lock */, 116 | 29CF5D591EE186BF00847135 /* Sources */, 117 | 29CF5D5A1EE186BF00847135 /* Frameworks */, 118 | 29CF5D5B1EE186BF00847135 /* Resources */, 119 | 2C836113C259D09FE9F1282A /* [CP] Embed Pods Frameworks */, 120 | 8455699EC72117CEFA890A5B /* [CP] Copy Pods Resources */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = XYButton; 127 | productName = XYButton; 128 | productReference = 29CF5D5D1EE186BF00847135 /* XYButton.app */; 129 | productType = "com.apple.product-type.application"; 130 | }; 131 | /* End PBXNativeTarget section */ 132 | 133 | /* Begin PBXProject section */ 134 | 29CF5D551EE186BF00847135 /* Project object */ = { 135 | isa = PBXProject; 136 | attributes = { 137 | LastUpgradeCheck = 0830; 138 | ORGANIZATIONNAME = "徐阳"; 139 | TargetAttributes = { 140 | 29CF5D5C1EE186BF00847135 = { 141 | CreatedOnToolsVersion = 8.3.2; 142 | DevelopmentTeam = LLNHUK4DDQ; 143 | ProvisioningStyle = Automatic; 144 | }; 145 | }; 146 | }; 147 | buildConfigurationList = 29CF5D581EE186BF00847135 /* Build configuration list for PBXProject "XYButton" */; 148 | compatibilityVersion = "Xcode 3.2"; 149 | developmentRegion = English; 150 | hasScannedForEncodings = 0; 151 | knownRegions = ( 152 | en, 153 | Base, 154 | ); 155 | mainGroup = 29CF5D541EE186BF00847135; 156 | productRefGroup = 29CF5D5E1EE186BF00847135 /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 29CF5D5C1EE186BF00847135 /* XYButton */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 29CF5D5B1EE186BF00847135 /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 29CF5D701EE186BF00847135 /* LaunchScreen.storyboard in Resources */, 171 | 29CF5D6D1EE186BF00847135 /* Assets.xcassets in Resources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXResourcesBuildPhase section */ 176 | 177 | /* Begin PBXShellScriptBuildPhase section */ 178 | 2C836113C259D09FE9F1282A /* [CP] Embed Pods Frameworks */ = { 179 | isa = PBXShellScriptBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | ); 183 | inputPaths = ( 184 | ); 185 | name = "[CP] Embed Pods Frameworks"; 186 | outputPaths = ( 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | shellPath = /bin/sh; 190 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XYButton/Pods-XYButton-frameworks.sh\"\n"; 191 | showEnvVarsInLog = 0; 192 | }; 193 | 41AECF5BE87AA96CC6CDDCC2 /* [CP] Check Pods Manifest.lock */ = { 194 | isa = PBXShellScriptBuildPhase; 195 | buildActionMask = 2147483647; 196 | files = ( 197 | ); 198 | inputPaths = ( 199 | ); 200 | name = "[CP] Check Pods Manifest.lock"; 201 | outputPaths = ( 202 | ); 203 | runOnlyForDeploymentPostprocessing = 0; 204 | shellPath = /bin/sh; 205 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 206 | showEnvVarsInLog = 0; 207 | }; 208 | 8455699EC72117CEFA890A5B /* [CP] Copy Pods Resources */ = { 209 | isa = PBXShellScriptBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | ); 213 | inputPaths = ( 214 | ); 215 | name = "[CP] Copy Pods Resources"; 216 | outputPaths = ( 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | shellPath = /bin/sh; 220 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XYButton/Pods-XYButton-resources.sh\"\n"; 221 | showEnvVarsInLog = 0; 222 | }; 223 | /* End PBXShellScriptBuildPhase section */ 224 | 225 | /* Begin PBXSourcesBuildPhase section */ 226 | 29CF5D591EE186BF00847135 /* Sources */ = { 227 | isa = PBXSourcesBuildPhase; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | 29CF5D681EE186BF00847135 /* ViewController.m in Sources */, 231 | 29CF5D651EE186BF00847135 /* AppDelegate.m in Sources */, 232 | 29CF5D791EE186FF00847135 /* XYButton.m in Sources */, 233 | 29CF5D621EE186BF00847135 /* main.m in Sources */, 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | /* End PBXSourcesBuildPhase section */ 238 | 239 | /* Begin PBXVariantGroup section */ 240 | 29CF5D6E1EE186BF00847135 /* LaunchScreen.storyboard */ = { 241 | isa = PBXVariantGroup; 242 | children = ( 243 | 29CF5D6F1EE186BF00847135 /* Base */, 244 | ); 245 | name = LaunchScreen.storyboard; 246 | sourceTree = ""; 247 | }; 248 | /* End PBXVariantGroup section */ 249 | 250 | /* Begin XCBuildConfiguration section */ 251 | 29CF5D721EE186BF00847135 /* Debug */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | ALWAYS_SEARCH_USER_PATHS = NO; 255 | CLANG_ANALYZER_NONNULL = YES; 256 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 257 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 258 | CLANG_CXX_LIBRARY = "libc++"; 259 | CLANG_ENABLE_MODULES = YES; 260 | CLANG_ENABLE_OBJC_ARC = YES; 261 | CLANG_WARN_BOOL_CONVERSION = YES; 262 | CLANG_WARN_CONSTANT_CONVERSION = YES; 263 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 264 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 265 | CLANG_WARN_EMPTY_BODY = YES; 266 | CLANG_WARN_ENUM_CONVERSION = YES; 267 | CLANG_WARN_INFINITE_RECURSION = YES; 268 | CLANG_WARN_INT_CONVERSION = YES; 269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 270 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 274 | COPY_PHASE_STRIP = NO; 275 | DEBUG_INFORMATION_FORMAT = dwarf; 276 | ENABLE_STRICT_OBJC_MSGSEND = YES; 277 | ENABLE_TESTABILITY = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu99; 279 | GCC_DYNAMIC_NO_PIC = NO; 280 | GCC_NO_COMMON_BLOCKS = YES; 281 | GCC_OPTIMIZATION_LEVEL = 0; 282 | GCC_PREPROCESSOR_DEFINITIONS = ( 283 | "DEBUG=1", 284 | "$(inherited)", 285 | ); 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 293 | MTL_ENABLE_DEBUG_INFO = YES; 294 | ONLY_ACTIVE_ARCH = YES; 295 | SDKROOT = iphoneos; 296 | TARGETED_DEVICE_FAMILY = "1,2"; 297 | }; 298 | name = Debug; 299 | }; 300 | 29CF5D731EE186BF00847135 /* Release */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | ALWAYS_SEARCH_USER_PATHS = NO; 304 | CLANG_ANALYZER_NONNULL = YES; 305 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 306 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 307 | CLANG_CXX_LIBRARY = "libc++"; 308 | CLANG_ENABLE_MODULES = YES; 309 | CLANG_ENABLE_OBJC_ARC = YES; 310 | CLANG_WARN_BOOL_CONVERSION = YES; 311 | CLANG_WARN_CONSTANT_CONVERSION = YES; 312 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 313 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 314 | CLANG_WARN_EMPTY_BODY = YES; 315 | CLANG_WARN_ENUM_CONVERSION = YES; 316 | CLANG_WARN_INFINITE_RECURSION = YES; 317 | CLANG_WARN_INT_CONVERSION = YES; 318 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 319 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 320 | CLANG_WARN_UNREACHABLE_CODE = YES; 321 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 322 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 323 | COPY_PHASE_STRIP = NO; 324 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 325 | ENABLE_NS_ASSERTIONS = NO; 326 | ENABLE_STRICT_OBJC_MSGSEND = YES; 327 | GCC_C_LANGUAGE_STANDARD = gnu99; 328 | GCC_NO_COMMON_BLOCKS = YES; 329 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 330 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 331 | GCC_WARN_UNDECLARED_SELECTOR = YES; 332 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 333 | GCC_WARN_UNUSED_FUNCTION = YES; 334 | GCC_WARN_UNUSED_VARIABLE = YES; 335 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 336 | MTL_ENABLE_DEBUG_INFO = NO; 337 | SDKROOT = iphoneos; 338 | TARGETED_DEVICE_FAMILY = "1,2"; 339 | VALIDATE_PRODUCT = YES; 340 | }; 341 | name = Release; 342 | }; 343 | 29CF5D751EE186BF00847135 /* Debug */ = { 344 | isa = XCBuildConfiguration; 345 | baseConfigurationReference = 0C6802F1D5BDA247523E7C2D /* Pods-XYButton.debug.xcconfig */; 346 | buildSettings = { 347 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 348 | DEVELOPMENT_TEAM = LLNHUK4DDQ; 349 | INFOPLIST_FILE = XYButton/Info.plist; 350 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 351 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 352 | PRODUCT_BUNDLE_IDENTIFIER = com.XYButton; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | }; 355 | name = Debug; 356 | }; 357 | 29CF5D761EE186BF00847135 /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | baseConfigurationReference = 43AF465BFE674505A4BC5081 /* Pods-XYButton.release.xcconfig */; 360 | buildSettings = { 361 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 362 | DEVELOPMENT_TEAM = LLNHUK4DDQ; 363 | INFOPLIST_FILE = XYButton/Info.plist; 364 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 366 | PRODUCT_BUNDLE_IDENTIFIER = com.XYButton; 367 | PRODUCT_NAME = "$(TARGET_NAME)"; 368 | }; 369 | name = Release; 370 | }; 371 | /* End XCBuildConfiguration section */ 372 | 373 | /* Begin XCConfigurationList section */ 374 | 29CF5D581EE186BF00847135 /* Build configuration list for PBXProject "XYButton" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | 29CF5D721EE186BF00847135 /* Debug */, 378 | 29CF5D731EE186BF00847135 /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | 29CF5D741EE186BF00847135 /* Build configuration list for PBXNativeTarget "XYButton" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | 29CF5D751EE186BF00847135 /* Debug */, 387 | 29CF5D761EE186BF00847135 /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | }; 391 | /* End XCConfigurationList section */ 392 | }; 393 | rootObject = 29CF5D551EE186BF00847135 /* Project object */; 394 | } 395 | -------------------------------------------------------------------------------- /XYButton.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XYButton.xcodeproj/xcuserdata/xuyang.xcuserdatad/xcschemes/XYButton.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /XYButton.xcodeproj/xcuserdata/xuyang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XYButton.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 29CF5D5C1EE186BF00847135 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /XYButton/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // XYButton 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /XYButton/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // KeepBtn 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 21 | self.window.backgroundColor = [UIColor whiteColor]; 22 | [self.window makeKeyAndVisible]; 23 | self.window.rootViewController = [ViewController new]; 24 | return YES; 25 | } 26 | 27 | 28 | - (void)applicationWillResignActive:(UIApplication *)application { 29 | // 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. 30 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 31 | } 32 | 33 | 34 | - (void)applicationDidEnterBackground:(UIApplication *)application { 35 | // 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. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | 40 | - (void)applicationWillEnterForeground:(UIApplication *)application { 41 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | 45 | - (void)applicationDidBecomeActive:(UIApplication *)application { 46 | // 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. 47 | } 48 | 49 | 50 | - (void)applicationWillTerminate:(UIApplication *)application { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /XYButton/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 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /XYButton/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /XYButton/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /XYButton/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // XYButton 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /XYButton/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // KeepBtn 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | // _ooOoo_ 9 | // o8888888o 10 | // 88" . "88 11 | // (| -_- |) 12 | // O\ = /O 13 | // ____/`---'\____ 14 | // . ' \\| |// `. 15 | // / \\||| : |||// \ 16 | // / _||||| -:- |||||- \ 17 | // | | \\\ - /// | | 18 | // | \_| ''\---/'' | | 19 | // \ .-\__ `-` ___/-. / 20 | // ___`. .' /--.--\ `. . __ 21 | // ."" '< `.___\_<|>_/___.' >'"". 22 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | 23 | // \ \ `-. \_ __\ /__ _/ .-` / / 24 | // ======`-.____`-.___\_____/___.-`____.-'====== 25 | // `=---=' 26 | // 27 | // ............................................. 28 | // 佛祖镇楼 BUG辟易 29 | // 佛曰: 30 | // 写字楼里写字间,写字间里程序员; 31 | // 程序人员写程序,又拿程序换酒钱。 32 | // 酒醒只在网上坐,酒醉还来网下眠; 33 | // 酒醉酒醒日复日,网上网下年复年。 34 | // 但愿老死电脑间,不愿鞠躬老板前; 35 | // 奔驰宝马贵者趣,公交自行程序员。 36 | // 别人笑我忒疯癫,我笑自己命太贱; 37 | // 不见满街漂亮妹,哪个归得程序员? 38 | 39 | /* 40 | 41 | ********************************************************************************* 42 | * 43 | * 处于研究的心理写了这个按钮,如果您发现有问题,防止误人子弟请及时联系我修正! 44 | * 45 | * 作者 : 臭码农 46 | * 简书地址 : http://www.jianshu.com/u/b309be9a40a7 47 | * GitHub : https://github.com/XuYang8026 48 | * QQ : 49900037 49 | 50 | ********************************************************************************* 51 | 52 | */ 53 | 54 | #import "ViewController.h" 55 | #import "XYButton.h" 56 | #import 57 | 58 | @interface ViewController () 59 | { 60 | XYButton *_leftBtn; 61 | XYButton *_rightBtn; 62 | XYButton *_pauseBtn; 63 | } 64 | 65 | 66 | @end 67 | 68 | @implementation ViewController 69 | 70 | - (void)viewDidLoad { 71 | [super viewDidLoad]; 72 | self.view.backgroundColor = [UIColor colorWithHexString:@"584f60"]; 73 | //创建页面 74 | [self createUI]; 75 | } 76 | 77 | -(UIStatusBarStyle)preferredStatusBarStyle{ 78 | return UIStatusBarStyleLightContent; 79 | } 80 | 81 | #pragma mark ————— 创建页面 ————— 82 | -(void)createUI{ 83 | @weakify(self); 84 | 85 | UILabel *label = [UILabel new]; 86 | label.font = [UIFont systemFontOfSize:100]; 87 | label.text = @"Keep"; 88 | label.textColor = [UIColor whiteColor]; 89 | [label sizeToFit]; 90 | label.centerX = self.view.centerX; 91 | label.top = kScreenHeight / 4; 92 | [self.view addSubview:label]; 93 | 94 | //左边按钮 95 | _leftBtn = [[XYButton alloc] initWithFrame:CGRectMake(0, 0, 85, 85) backgroundColor:[UIColor colorWithHexString:@"24c789"] borderColor:[UIColor colorWithHexString:@"584f60"] title:@"开始" titleColor:[UIColor whiteColor] font:[UIFont systemFontOfSize:18] tapBlock:^(UIButton *btn) { 96 | //点击事件 97 | [weak_self leftBtnClick]; 98 | 99 | }]; 100 | _leftBtn.left = kScreenWidth / 6; 101 | _leftBtn.bottom = kScreenHeight - 60; 102 | [self.view addSubview:_leftBtn]; 103 | 104 | 105 | //右边按钮 106 | _rightBtn = [[XYButton alloc] initWithFrame:CGRectMake(0, 0, 85, 85) backgroundColor:[UIColor colorWithHexString:@"f35252"] borderColor:[UIColor colorWithHexString:@"f35252"] title:@"结束" titleColor:[UIColor whiteColor] font:[UIFont systemFontOfSize:18] tapBlock:^(UIButton *btn) { 107 | //点击事件 108 | }]; 109 | _rightBtn.right = kScreenWidth - kScreenWidth / 6; 110 | _rightBtn.bottom = kScreenHeight - 60; 111 | [self.view addSubview:_rightBtn]; 112 | 113 | 114 | //暂停按钮 115 | _pauseBtn = [[XYButton alloc] initWithFrame:CGRectMake(0, 0, 85, 85) backgroundColor:[UIColor whiteColor] borderColor:[UIColor colorWithHexString:@"584f60"] title:@"暂停" titleColor:[UIColor colorWithHexString:@"584f60"] font:[UIFont systemFontOfSize:18] tapBlock:^(UIButton *btn) { 116 | //点击事件 117 | [weak_self pauseBtnClick]; 118 | }]; 119 | _pauseBtn.centerX = self.view.centerX; 120 | _pauseBtn.bottom = kScreenHeight - 60; 121 | _pauseBtn.alpha = 0 ; 122 | _pauseBtn.transform = CGAffineTransformMakeScale(0.3,0.3); 123 | [self.view addSubview:_pauseBtn]; 124 | 125 | } 126 | #pragma mark ————— 左边按钮点击 ————— 127 | -(void)leftBtnClick{ 128 | 129 | [UIView animateWithDuration:0.2 delay:0 usingSpringWithDamping:0.9 initialSpringVelocity:10 options:0 animations:^{ 130 | _leftBtn.centerX = _rightBtn.centerX = self.view.centerX; 131 | _leftBtn.alpha = _rightBtn.alpha = 0; 132 | } completion:^(BOOL finished) { 133 | [UIView animateWithDuration:0.3 animations:^{ 134 | 135 | _pauseBtn.alpha = 1; 136 | _pauseBtn.transform = CGAffineTransformIdentity; 137 | }]; 138 | }]; 139 | 140 | } 141 | #pragma mark ————— 暂停按钮点击 ————— 142 | -(void)pauseBtnClick{ 143 | [UIView animateWithDuration:0.3 animations:^{ 144 | _pauseBtn.alpha = 0; 145 | } completion:^(BOOL finished) { 146 | _pauseBtn.transform = CGAffineTransformMakeScale(0.3,0.3); 147 | [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:20 options:0 animations:^{ 148 | _leftBtn.alpha = _rightBtn.alpha = 1; 149 | _leftBtn.left = kScreenWidth / 6; 150 | _rightBtn.right = kScreenWidth - kScreenWidth / 6; 151 | } completion:nil]; 152 | }]; 153 | } 154 | 155 | - (void)didReceiveMemoryWarning { 156 | [super didReceiveMemoryWarning]; 157 | // Dispose of any resources that can be recreated. 158 | } 159 | 160 | 161 | @end 162 | -------------------------------------------------------------------------------- /XYButton/XYButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // XYButton.h 3 | // KeepBtn 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^TapBlock)(UIButton *btn);// 12 | 13 | @interface XYButton : UIButton 14 | @property (nonatomic ,assign)BOOL isCanTapWhenAnimating;//在动画期间是否可以再次被点击 默认否 15 | 16 | /** 17 | 圆形按钮 18 | 19 | @param frame frame 20 | @param backgroundColor 背景颜色 21 | @param borderColor 边框颜色 22 | @param title 标题 23 | @param titleColor 标题颜色 24 | @param font 字体 25 | @param tapBlock 点击事件block 26 | */ 27 | -(instancetype)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor borderColor:(UIColor *)borderColor title:(NSString *)title titleColor:(UIColor *)titleColor font:(UIFont *)font tapBlock:(TapBlock) tapBlock; 28 | @end 29 | -------------------------------------------------------------------------------- /XYButton/XYButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // XYButton.m 3 | // KeepBtn 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | 9 | #import "XYButton.h" 10 | 11 | #define LineWidth (self.frame.size.width * 0.023) 12 | #define KDuration 0.15 13 | #define KDurationFast 0.06 14 | 15 | @interface XYButton() 16 | 17 | @property (nonatomic, strong) CAShapeLayer *borderLayer;//边框 18 | @property (nonatomic, strong) CAShapeLayer *bgLayer;//边框 19 | 20 | 21 | @property (nonatomic, strong) UIColor *bgColor; 22 | @property (nonatomic, strong) UIColor *borderColor; 23 | 24 | @property (nonatomic, copy) TapBlock block;//点击事件 25 | 26 | @end 27 | 28 | @implementation XYButton 29 | 30 | #pragma mark ————— 初始化 ————— 31 | -(instancetype)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor borderColor:(UIColor *)borderColor title:(NSString *)title titleColor:(UIColor *)titleColor font:(UIFont *)font tapBlock:(TapBlock) tapBlock{ 32 | if (self = [super initWithFrame:frame]) { 33 | self.block = tapBlock; 34 | self.bgColor = backgroundColor; 35 | self.borderColor = borderColor; 36 | 37 | [self setTitleColor:titleColor forState:UIControlStateNormal]; 38 | [self setTitle:title forState:UIControlStateNormal]; 39 | self.titleLabel.font = font; 40 | [self addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown]; 41 | [self addTarget:self action:@selector(touchCancel:) forControlEvents:UIControlEventTouchCancel]; 42 | [self addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside]; 43 | [self addTarget:self action:@selector(touchCancel:) forControlEvents:UIControlEventTouchUpOutside]; 44 | 45 | 46 | [self.layer insertSublayer:self.bgLayer atIndex:0]; 47 | [self.layer insertSublayer:self.borderLayer above:self.bgLayer]; 48 | 49 | } 50 | return self; 51 | } 52 | #pragma mark ————— 按下 ————— 53 | -(void)touchDown:(UIButton *)btn{ 54 | self.enabled = _isCanTapWhenAnimating ? YES : NO ; 55 | [self downAnimation]; 56 | } 57 | #pragma mark ————— 松开 ————— 58 | -(void)touchUpInside:(UIButton *)btn{ 59 | [self upAnimation:NO]; 60 | 61 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 62 | if (self.block) { 63 | self.block(nil); 64 | } 65 | self.enabled = YES; 66 | }); 67 | } 68 | #pragma mark ————— 取消 ————— 69 | -(void)touchCancel:(UIButton *)btn{ 70 | self.enabled = YES; 71 | [self upAnimation:YES]; 72 | } 73 | 74 | #pragma mark ————— 按下动画 ————— 75 | -(void)downAnimation{ 76 | 77 | CABasicAnimation *bgAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 78 | bgAnimation.toValue = @1.1; 79 | bgAnimation.duration = KDuration; 80 | bgAnimation.removedOnCompletion=NO; 81 | bgAnimation.fillMode=kCAFillModeForwards; 82 | [self.bgLayer addAnimation:bgAnimation forKey:nil]; 83 | 84 | CABasicAnimation *borderAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 85 | borderAnimation.toValue = @0.9; 86 | borderAnimation.duration = KDuration; 87 | borderAnimation.removedOnCompletion=NO; 88 | borderAnimation.fillMode=kCAFillModeForwards; 89 | [self.borderLayer addAnimation:borderAnimation forKey:nil]; 90 | 91 | } 92 | 93 | #pragma mark ————— 松开动画 ————— 94 | -(void)upAnimation:(BOOL) isCancel{ 95 | if (!isCancel) {//如果不是取消,做个动画再还原;如果是取消,直接还原 96 | 97 | CABasicAnimation *bgBig0 = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 98 | bgBig0.toValue = @1.05; 99 | bgBig0.duration = KDurationFast; 100 | bgBig0.removedOnCompletion=NO; 101 | bgBig0.fillMode=kCAFillModeForwards; 102 | bgBig0.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 103 | [self.bgLayer addAnimation:bgBig0 forKey:nil]; 104 | 105 | CABasicAnimation *bgBig = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 106 | bgBig.toValue = @1.15; 107 | bgBig.duration = KDuration; 108 | bgBig.beginTime =CACurrentMediaTime() +KDurationFast; 109 | bgBig.removedOnCompletion=NO; 110 | bgBig.fillMode=kCAFillModeForwards; 111 | bgBig.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 112 | [self.bgLayer addAnimation:bgBig forKey:nil]; 113 | 114 | 115 | CABasicAnimation *bgSmall = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 116 | bgSmall.toValue = @1.0; 117 | bgSmall.beginTime =CACurrentMediaTime() + KDuration + KDurationFast ; 118 | bgSmall.duration = 0.1; 119 | bgSmall.removedOnCompletion=NO; 120 | bgSmall.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 121 | bgSmall.fillMode=kCAFillModeForwards; 122 | [self.bgLayer addAnimation:bgSmall forKey:nil]; 123 | 124 | 125 | CABasicAnimation *borderBig = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 126 | borderBig.toValue = @0.85; 127 | borderBig.duration = KDuration; 128 | borderBig.beginTime =CACurrentMediaTime() +KDurationFast; 129 | borderBig.removedOnCompletion=NO; 130 | borderBig.fillMode=kCAFillModeForwards; 131 | borderBig.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 132 | [self.borderLayer addAnimation:borderBig forKey:nil]; 133 | 134 | CABasicAnimation *borderSmall = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 135 | borderSmall.toValue = @1.0; 136 | borderSmall.duration = 0.1; 137 | borderSmall.beginTime =CACurrentMediaTime() +KDuration + KDurationFast; 138 | borderSmall.removedOnCompletion=NO; 139 | borderSmall.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; 140 | borderSmall.fillMode=kCAFillModeForwards; 141 | [self.borderLayer addAnimation:borderSmall forKey:nil]; 142 | 143 | }else{ 144 | CABasicAnimation *bgAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 145 | bgAnimation.toValue = @1.0; 146 | bgAnimation.duration = KDuration; 147 | bgAnimation.removedOnCompletion=NO; 148 | bgAnimation.fillMode=kCAFillModeForwards; 149 | [self.bgLayer addAnimation:bgAnimation forKey:nil]; 150 | 151 | CABasicAnimation *borderAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 152 | borderAnimation.toValue = @1.0; 153 | borderAnimation.duration = KDuration; 154 | borderAnimation.removedOnCompletion=NO; 155 | borderAnimation.fillMode=kCAFillModeForwards; 156 | [self.borderLayer addAnimation:borderAnimation forKey:nil]; 157 | } 158 | 159 | } 160 | 161 | #pragma mark - ——————— 懒加载 layer ———————— 162 | -(CAShapeLayer *)bgLayer{ 163 | if(!_bgLayer){ 164 | _bgLayer = [CAShapeLayer new]; 165 | _bgLayer.frame = self.bounds; 166 | _bgLayer.backgroundColor = self.bgColor.CGColor; 167 | _bgLayer.cornerRadius = self.bounds.size.width/2; 168 | 169 | } 170 | return _bgLayer; 171 | } 172 | 173 | -(CAShapeLayer *)borderLayer{ 174 | if (!_borderLayer) { 175 | 176 | _borderLayer = [CAShapeLayer new]; 177 | _borderLayer.borderWidth = LineWidth; 178 | _borderLayer.borderColor = self.borderColor.CGColor; 179 | _borderLayer.frame = CGRectMake(LineWidth, LineWidth, self.frame.size.width-(LineWidth*2), self.frame.size.height-(LineWidth*2)); 180 | _borderLayer.cornerRadius = _borderLayer.frame.size.width/2; 181 | } 182 | return _borderLayer; 183 | } 184 | 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /XYButton/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // XYButton 4 | // 5 | // Created by 徐阳 on 2017/6/2. 6 | // Copyright © 2017年 徐阳. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------