├── README.md ├── TLDragButton-demo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── TLDragButton-demo.xccheckout │ └── xcuserdata │ │ └── andezhou.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── andezhou.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── TLDragButton-demo.xcscheme │ └── xcschememanagement.plist ├── TLDragButton-demo ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── TLDragButton.h ├── TLDragButton.m ├── ViewController.h ├── ViewController.m └── main.m └── TLDragButton-demoTests ├── Info.plist └── TLDragButton_demoTests.m /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhouande/TLDragButton/31cd8d102874e9c2eb10be0cf6c5f2590c16b0ea/README.md -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 13BC4F7D1B501548009E73D1 /* TLDragButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BC4F7C1B501548009E73D1 /* TLDragButton.m */; }; 11 | 13BC64AE1B4FC8C200C8C4D4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BC64AD1B4FC8C200C8C4D4 /* main.m */; }; 12 | 13BC64B11B4FC8C200C8C4D4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BC64B01B4FC8C200C8C4D4 /* AppDelegate.m */; }; 13 | 13BC64B41B4FC8C200C8C4D4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BC64B31B4FC8C200C8C4D4 /* ViewController.m */; }; 14 | 13BC64B71B4FC8C200C8C4D4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 13BC64B51B4FC8C200C8C4D4 /* Main.storyboard */; }; 15 | 13BC64B91B4FC8C200C8C4D4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13BC64B81B4FC8C200C8C4D4 /* Images.xcassets */; }; 16 | 13BC64BC1B4FC8C200C8C4D4 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13BC64BA1B4FC8C200C8C4D4 /* LaunchScreen.xib */; }; 17 | 13BC64C81B4FC8C200C8C4D4 /* TLDragButton_demoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BC64C71B4FC8C200C8C4D4 /* TLDragButton_demoTests.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 13BC64C21B4FC8C200C8C4D4 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 13BC64A01B4FC8C200C8C4D4 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 13BC64A71B4FC8C200C8C4D4; 26 | remoteInfo = "TLDragButton-demo"; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 13BC4F7B1B501548009E73D1 /* TLDragButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLDragButton.h; sourceTree = ""; }; 32 | 13BC4F7C1B501548009E73D1 /* TLDragButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TLDragButton.m; sourceTree = ""; }; 33 | 13BC64A81B4FC8C200C8C4D4 /* TLDragButton-demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TLDragButton-demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 13BC64AC1B4FC8C200C8C4D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 13BC64AD1B4FC8C200C8C4D4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 36 | 13BC64AF1B4FC8C200C8C4D4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 37 | 13BC64B01B4FC8C200C8C4D4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 38 | 13BC64B21B4FC8C200C8C4D4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 39 | 13BC64B31B4FC8C200C8C4D4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 40 | 13BC64B61B4FC8C200C8C4D4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 41 | 13BC64B81B4FC8C200C8C4D4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 42 | 13BC64BB1B4FC8C200C8C4D4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 43 | 13BC64C11B4FC8C200C8C4D4 /* TLDragButton-demoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TLDragButton-demoTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 13BC64C61B4FC8C200C8C4D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 13BC64C71B4FC8C200C8C4D4 /* TLDragButton_demoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TLDragButton_demoTests.m; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 13BC64A51B4FC8C200C8C4D4 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | 13BC64BE1B4FC8C200C8C4D4 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | 13BC649F1B4FC8C200C8C4D4 = { 67 | isa = PBXGroup; 68 | children = ( 69 | 13BC64AA1B4FC8C200C8C4D4 /* TLDragButton-demo */, 70 | 13BC64C41B4FC8C200C8C4D4 /* TLDragButton-demoTests */, 71 | 13BC64A91B4FC8C200C8C4D4 /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | 13BC64A91B4FC8C200C8C4D4 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 13BC64A81B4FC8C200C8C4D4 /* TLDragButton-demo.app */, 79 | 13BC64C11B4FC8C200C8C4D4 /* TLDragButton-demoTests.xctest */, 80 | ); 81 | name = Products; 82 | sourceTree = ""; 83 | }; 84 | 13BC64AA1B4FC8C200C8C4D4 /* TLDragButton-demo */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 13BC64AF1B4FC8C200C8C4D4 /* AppDelegate.h */, 88 | 13BC64B01B4FC8C200C8C4D4 /* AppDelegate.m */, 89 | 13BC4F7B1B501548009E73D1 /* TLDragButton.h */, 90 | 13BC4F7C1B501548009E73D1 /* TLDragButton.m */, 91 | 13BC64B21B4FC8C200C8C4D4 /* ViewController.h */, 92 | 13BC64B31B4FC8C200C8C4D4 /* ViewController.m */, 93 | 13BC64B51B4FC8C200C8C4D4 /* Main.storyboard */, 94 | 13BC64B81B4FC8C200C8C4D4 /* Images.xcassets */, 95 | 13BC64BA1B4FC8C200C8C4D4 /* LaunchScreen.xib */, 96 | 13BC64AB1B4FC8C200C8C4D4 /* Supporting Files */, 97 | ); 98 | path = "TLDragButton-demo"; 99 | sourceTree = ""; 100 | }; 101 | 13BC64AB1B4FC8C200C8C4D4 /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 13BC64AC1B4FC8C200C8C4D4 /* Info.plist */, 105 | 13BC64AD1B4FC8C200C8C4D4 /* main.m */, 106 | ); 107 | name = "Supporting Files"; 108 | sourceTree = ""; 109 | }; 110 | 13BC64C41B4FC8C200C8C4D4 /* TLDragButton-demoTests */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 13BC64C71B4FC8C200C8C4D4 /* TLDragButton_demoTests.m */, 114 | 13BC64C51B4FC8C200C8C4D4 /* Supporting Files */, 115 | ); 116 | path = "TLDragButton-demoTests"; 117 | sourceTree = ""; 118 | }; 119 | 13BC64C51B4FC8C200C8C4D4 /* Supporting Files */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 13BC64C61B4FC8C200C8C4D4 /* Info.plist */, 123 | ); 124 | name = "Supporting Files"; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 13BC64A71B4FC8C200C8C4D4 /* TLDragButton-demo */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 13BC64CB1B4FC8C200C8C4D4 /* Build configuration list for PBXNativeTarget "TLDragButton-demo" */; 133 | buildPhases = ( 134 | 13BC64A41B4FC8C200C8C4D4 /* Sources */, 135 | 13BC64A51B4FC8C200C8C4D4 /* Frameworks */, 136 | 13BC64A61B4FC8C200C8C4D4 /* Resources */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = "TLDragButton-demo"; 143 | productName = "TLDragButton-demo"; 144 | productReference = 13BC64A81B4FC8C200C8C4D4 /* TLDragButton-demo.app */; 145 | productType = "com.apple.product-type.application"; 146 | }; 147 | 13BC64C01B4FC8C200C8C4D4 /* TLDragButton-demoTests */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 13BC64CE1B4FC8C200C8C4D4 /* Build configuration list for PBXNativeTarget "TLDragButton-demoTests" */; 150 | buildPhases = ( 151 | 13BC64BD1B4FC8C200C8C4D4 /* Sources */, 152 | 13BC64BE1B4FC8C200C8C4D4 /* Frameworks */, 153 | 13BC64BF1B4FC8C200C8C4D4 /* Resources */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | 13BC64C31B4FC8C200C8C4D4 /* PBXTargetDependency */, 159 | ); 160 | name = "TLDragButton-demoTests"; 161 | productName = "TLDragButton-demoTests"; 162 | productReference = 13BC64C11B4FC8C200C8C4D4 /* TLDragButton-demoTests.xctest */; 163 | productType = "com.apple.product-type.bundle.unit-test"; 164 | }; 165 | /* End PBXNativeTarget section */ 166 | 167 | /* Begin PBXProject section */ 168 | 13BC64A01B4FC8C200C8C4D4 /* Project object */ = { 169 | isa = PBXProject; 170 | attributes = { 171 | LastUpgradeCheck = 0630; 172 | ORGANIZATIONNAME = andezhou; 173 | TargetAttributes = { 174 | 13BC64A71B4FC8C200C8C4D4 = { 175 | CreatedOnToolsVersion = 6.3.2; 176 | DevelopmentTeam = 46MF2PE5UD; 177 | }; 178 | 13BC64C01B4FC8C200C8C4D4 = { 179 | CreatedOnToolsVersion = 6.3.2; 180 | TestTargetID = 13BC64A71B4FC8C200C8C4D4; 181 | }; 182 | }; 183 | }; 184 | buildConfigurationList = 13BC64A31B4FC8C200C8C4D4 /* Build configuration list for PBXProject "TLDragButton-demo" */; 185 | compatibilityVersion = "Xcode 3.2"; 186 | developmentRegion = English; 187 | hasScannedForEncodings = 0; 188 | knownRegions = ( 189 | en, 190 | Base, 191 | ); 192 | mainGroup = 13BC649F1B4FC8C200C8C4D4; 193 | productRefGroup = 13BC64A91B4FC8C200C8C4D4 /* Products */; 194 | projectDirPath = ""; 195 | projectRoot = ""; 196 | targets = ( 197 | 13BC64A71B4FC8C200C8C4D4 /* TLDragButton-demo */, 198 | 13BC64C01B4FC8C200C8C4D4 /* TLDragButton-demoTests */, 199 | ); 200 | }; 201 | /* End PBXProject section */ 202 | 203 | /* Begin PBXResourcesBuildPhase section */ 204 | 13BC64A61B4FC8C200C8C4D4 /* Resources */ = { 205 | isa = PBXResourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | 13BC64B71B4FC8C200C8C4D4 /* Main.storyboard in Resources */, 209 | 13BC64BC1B4FC8C200C8C4D4 /* LaunchScreen.xib in Resources */, 210 | 13BC64B91B4FC8C200C8C4D4 /* Images.xcassets in Resources */, 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | 13BC64BF1B4FC8C200C8C4D4 /* Resources */ = { 215 | isa = PBXResourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXResourcesBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | 13BC64A41B4FC8C200C8C4D4 /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 13BC64B41B4FC8C200C8C4D4 /* ViewController.m in Sources */, 229 | 13BC64B11B4FC8C200C8C4D4 /* AppDelegate.m in Sources */, 230 | 13BC64AE1B4FC8C200C8C4D4 /* main.m in Sources */, 231 | 13BC4F7D1B501548009E73D1 /* TLDragButton.m in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | 13BC64BD1B4FC8C200C8C4D4 /* Sources */ = { 236 | isa = PBXSourcesBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | 13BC64C81B4FC8C200C8C4D4 /* TLDragButton_demoTests.m in Sources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | /* End PBXSourcesBuildPhase section */ 244 | 245 | /* Begin PBXTargetDependency section */ 246 | 13BC64C31B4FC8C200C8C4D4 /* PBXTargetDependency */ = { 247 | isa = PBXTargetDependency; 248 | target = 13BC64A71B4FC8C200C8C4D4 /* TLDragButton-demo */; 249 | targetProxy = 13BC64C21B4FC8C200C8C4D4 /* PBXContainerItemProxy */; 250 | }; 251 | /* End PBXTargetDependency section */ 252 | 253 | /* Begin PBXVariantGroup section */ 254 | 13BC64B51B4FC8C200C8C4D4 /* Main.storyboard */ = { 255 | isa = PBXVariantGroup; 256 | children = ( 257 | 13BC64B61B4FC8C200C8C4D4 /* Base */, 258 | ); 259 | name = Main.storyboard; 260 | sourceTree = ""; 261 | }; 262 | 13BC64BA1B4FC8C200C8C4D4 /* LaunchScreen.xib */ = { 263 | isa = PBXVariantGroup; 264 | children = ( 265 | 13BC64BB1B4FC8C200C8C4D4 /* Base */, 266 | ); 267 | name = LaunchScreen.xib; 268 | sourceTree = ""; 269 | }; 270 | /* End PBXVariantGroup section */ 271 | 272 | /* Begin XCBuildConfiguration section */ 273 | 13BC64C91B4FC8C200C8C4D4 /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ALWAYS_SEARCH_USER_PATHS = NO; 277 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 278 | CLANG_CXX_LIBRARY = "libc++"; 279 | CLANG_ENABLE_MODULES = YES; 280 | CLANG_ENABLE_OBJC_ARC = YES; 281 | CLANG_WARN_BOOL_CONVERSION = YES; 282 | CLANG_WARN_CONSTANT_CONVERSION = YES; 283 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 284 | CLANG_WARN_EMPTY_BODY = YES; 285 | CLANG_WARN_ENUM_CONVERSION = YES; 286 | CLANG_WARN_INT_CONVERSION = YES; 287 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 288 | CLANG_WARN_UNREACHABLE_CODE = YES; 289 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 290 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 291 | COPY_PHASE_STRIP = NO; 292 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 293 | ENABLE_STRICT_OBJC_MSGSEND = YES; 294 | GCC_C_LANGUAGE_STANDARD = gnu99; 295 | GCC_DYNAMIC_NO_PIC = NO; 296 | GCC_NO_COMMON_BLOCKS = YES; 297 | GCC_OPTIMIZATION_LEVEL = 0; 298 | GCC_PREPROCESSOR_DEFINITIONS = ( 299 | "DEBUG=1", 300 | "$(inherited)", 301 | ); 302 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 303 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 304 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 305 | GCC_WARN_UNDECLARED_SELECTOR = YES; 306 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 307 | GCC_WARN_UNUSED_FUNCTION = YES; 308 | GCC_WARN_UNUSED_VARIABLE = YES; 309 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 310 | MTL_ENABLE_DEBUG_INFO = YES; 311 | ONLY_ACTIVE_ARCH = YES; 312 | SDKROOT = iphoneos; 313 | }; 314 | name = Debug; 315 | }; 316 | 13BC64CA1B4FC8C200C8C4D4 /* Release */ = { 317 | isa = XCBuildConfiguration; 318 | buildSettings = { 319 | ALWAYS_SEARCH_USER_PATHS = NO; 320 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 321 | CLANG_CXX_LIBRARY = "libc++"; 322 | CLANG_ENABLE_MODULES = YES; 323 | CLANG_ENABLE_OBJC_ARC = YES; 324 | CLANG_WARN_BOOL_CONVERSION = YES; 325 | CLANG_WARN_CONSTANT_CONVERSION = YES; 326 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 327 | CLANG_WARN_EMPTY_BODY = YES; 328 | CLANG_WARN_ENUM_CONVERSION = YES; 329 | CLANG_WARN_INT_CONVERSION = YES; 330 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 331 | CLANG_WARN_UNREACHABLE_CODE = YES; 332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 334 | COPY_PHASE_STRIP = NO; 335 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 336 | ENABLE_NS_ASSERTIONS = NO; 337 | ENABLE_STRICT_OBJC_MSGSEND = YES; 338 | GCC_C_LANGUAGE_STANDARD = gnu99; 339 | GCC_NO_COMMON_BLOCKS = YES; 340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 342 | GCC_WARN_UNDECLARED_SELECTOR = YES; 343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 344 | GCC_WARN_UNUSED_FUNCTION = YES; 345 | GCC_WARN_UNUSED_VARIABLE = YES; 346 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 347 | MTL_ENABLE_DEBUG_INFO = NO; 348 | SDKROOT = iphoneos; 349 | VALIDATE_PRODUCT = YES; 350 | }; 351 | name = Release; 352 | }; 353 | 13BC64CC1B4FC8C200C8C4D4 /* Debug */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 357 | CODE_SIGN_IDENTITY = "iPhone Developer"; 358 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 359 | INFOPLIST_FILE = "TLDragButton-demo/Info.plist"; 360 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 361 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | PROVISIONING_PROFILE = ""; 364 | }; 365 | name = Debug; 366 | }; 367 | 13BC64CD1B4FC8C200C8C4D4 /* Release */ = { 368 | isa = XCBuildConfiguration; 369 | buildSettings = { 370 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 371 | CODE_SIGN_IDENTITY = "iPhone Developer"; 372 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 373 | INFOPLIST_FILE = "TLDragButton-demo/Info.plist"; 374 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 375 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | PROVISIONING_PROFILE = ""; 378 | }; 379 | name = Release; 380 | }; 381 | 13BC64CF1B4FC8C200C8C4D4 /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | BUNDLE_LOADER = "$(TEST_HOST)"; 385 | FRAMEWORK_SEARCH_PATHS = ( 386 | "$(SDKROOT)/Developer/Library/Frameworks", 387 | "$(inherited)", 388 | ); 389 | GCC_PREPROCESSOR_DEFINITIONS = ( 390 | "DEBUG=1", 391 | "$(inherited)", 392 | ); 393 | INFOPLIST_FILE = "TLDragButton-demoTests/Info.plist"; 394 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TLDragButton-demo.app/TLDragButton-demo"; 397 | }; 398 | name = Debug; 399 | }; 400 | 13BC64D01B4FC8C200C8C4D4 /* Release */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | BUNDLE_LOADER = "$(TEST_HOST)"; 404 | FRAMEWORK_SEARCH_PATHS = ( 405 | "$(SDKROOT)/Developer/Library/Frameworks", 406 | "$(inherited)", 407 | ); 408 | INFOPLIST_FILE = "TLDragButton-demoTests/Info.plist"; 409 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 410 | PRODUCT_NAME = "$(TARGET_NAME)"; 411 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TLDragButton-demo.app/TLDragButton-demo"; 412 | }; 413 | name = Release; 414 | }; 415 | /* End XCBuildConfiguration section */ 416 | 417 | /* Begin XCConfigurationList section */ 418 | 13BC64A31B4FC8C200C8C4D4 /* Build configuration list for PBXProject "TLDragButton-demo" */ = { 419 | isa = XCConfigurationList; 420 | buildConfigurations = ( 421 | 13BC64C91B4FC8C200C8C4D4 /* Debug */, 422 | 13BC64CA1B4FC8C200C8C4D4 /* Release */, 423 | ); 424 | defaultConfigurationIsVisible = 0; 425 | defaultConfigurationName = Release; 426 | }; 427 | 13BC64CB1B4FC8C200C8C4D4 /* Build configuration list for PBXNativeTarget "TLDragButton-demo" */ = { 428 | isa = XCConfigurationList; 429 | buildConfigurations = ( 430 | 13BC64CC1B4FC8C200C8C4D4 /* Debug */, 431 | 13BC64CD1B4FC8C200C8C4D4 /* Release */, 432 | ); 433 | defaultConfigurationIsVisible = 0; 434 | defaultConfigurationName = Release; 435 | }; 436 | 13BC64CE1B4FC8C200C8C4D4 /* Build configuration list for PBXNativeTarget "TLDragButton-demoTests" */ = { 437 | isa = XCConfigurationList; 438 | buildConfigurations = ( 439 | 13BC64CF1B4FC8C200C8C4D4 /* Debug */, 440 | 13BC64D01B4FC8C200C8C4D4 /* Release */, 441 | ); 442 | defaultConfigurationIsVisible = 0; 443 | defaultConfigurationName = Release; 444 | }; 445 | /* End XCConfigurationList section */ 446 | }; 447 | rootObject = 13BC64A01B4FC8C200C8C4D4 /* Project object */; 448 | } 449 | -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/project.xcworkspace/xcshareddata/TLDragButton-demo.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 74331B8E-AC4E-4FBB-99CA-F47949FEFB68 9 | IDESourceControlProjectName 10 | TLDragButton-demo 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 7D153813D0D66D65B832B1312ED6FB95CC6A0C9D 14 | https://github.com/zhouande/TLDragButton.git 15 | A50D76C2AF5C1DB6B0080A2D34D948FAE27514BF 16 | https://github.com/zhouande/TLDragButton.git 17 | 18 | IDESourceControlProjectPath 19 | TLDragButton-demo.xcodeproj 20 | IDESourceControlProjectRelativeInstallPathDictionary 21 | 22 | 7D153813D0D66D65B832B1312ED6FB95CC6A0C9D 23 | ../.. 24 | A50D76C2AF5C1DB6B0080A2D34D948FAE27514BF 25 | ../../../TLDragButton-master 26 | 27 | IDESourceControlProjectURL 28 | https://github.com/zhouande/TLDragButton.git 29 | IDESourceControlProjectVersion 30 | 111 31 | IDESourceControlProjectWCCIdentifier 32 | 7D153813D0D66D65B832B1312ED6FB95CC6A0C9D 33 | IDESourceControlProjectWCConfigurations 34 | 35 | 36 | IDESourceControlRepositoryExtensionIdentifierKey 37 | public.vcs.git 38 | IDESourceControlWCCIdentifierKey 39 | 7D153813D0D66D65B832B1312ED6FB95CC6A0C9D 40 | IDESourceControlWCCName 41 | TLDragButto 42 | 43 | 44 | IDESourceControlRepositoryExtensionIdentifierKey 45 | public.vcs.git 46 | IDESourceControlWCCIdentifierKey 47 | A50D76C2AF5C1DB6B0080A2D34D948FAE27514BF 48 | IDESourceControlWCCName 49 | TLDragButton-master 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/project.xcworkspace/xcuserdata/andezhou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhouande/TLDragButton/31cd8d102874e9c2eb10be0cf6c5f2590c16b0ea/TLDragButton-demo.xcodeproj/project.xcworkspace/xcuserdata/andezhou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/xcuserdata/andezhou.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/xcuserdata/andezhou.xcuserdatad/xcschemes/TLDragButton-demo.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 | -------------------------------------------------------------------------------- /TLDragButton-demo.xcodeproj/xcuserdata/andezhou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TLDragButton-demo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 13BC64A71B4FC8C200C8C4D4 16 | 17 | primary 18 | 19 | 20 | 13BC64C01B4FC8C200C8C4D4 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TLDragButton-demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TLDragButton-demo 4 | // 5 | // Created by andezhou on 15/7/10. 6 | // Copyright (c) 2015年 andezhou. 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 | -------------------------------------------------------------------------------- /TLDragButton-demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TLDragButton-demo 4 | // 5 | // Created by andezhou on 15/7/10. 6 | // Copyright (c) 2015年 andezhou. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /TLDragButton-demo/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 | -------------------------------------------------------------------------------- /TLDragButton-demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /TLDragButton-demo/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 | } -------------------------------------------------------------------------------- /TLDragButton-demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.AMeD.hospitalMeeting.$(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 | -------------------------------------------------------------------------------- /TLDragButton-demo/TLDragButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // TLDragButton.h 3 | // 按钮拖拽 4 | // 5 | // Created by andezhou on 15/7/10. 6 | // Copyright (c) 2015年 andezhou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void (^DisplayCompletionBlock)(void); 12 | typedef void (^DisplayCloseBlock)(UIView *displayView, CFTimeInterval duration); 13 | typedef void (^DisplayOpenBlock)(UIView *displayView, CFTimeInterval duration); 14 | 15 | @class TLDragButton; 16 | 17 | @protocol TLDragButtonDelegate 18 | 19 | /** 20 | * @brief 通知父视图button的排列顺序发生了改变 21 | * 22 | * @param dragButton 按钮位置已经改变button 23 | * @param dragButtons 新排列的button数组 24 | */ 25 | - (void)dragButton:(TLDragButton *)dragButton dragButtons:(NSArray *)dragButtons; 26 | 27 | @end 28 | 29 | @interface TLDragButton : UIButton 30 | 31 | /** 32 | * 代理方法 33 | */ 34 | @property (nonatomic, weak) id delegate; 35 | 36 | /** 37 | * 存放需要拖拽的按钮数组 38 | */ 39 | @property (nonatomic, strong) NSMutableArray *btnArray; 40 | 41 | /** 42 | * 按钮正在被拖拽时的颜色 43 | */ 44 | @property (nonatomic, strong) UIColor *dragColor; 45 | 46 | /** 47 | * 一排按钮的个数, 如使用openDisplayView方法,linecout不能为空 48 | */ 49 | @property (nonatomic, assign) NSUInteger lineCount; 50 | 51 | #pragma mack - public methods 52 | - (void)openDisplayView:(UIView *)displayView 53 | openBlock:(DisplayOpenBlock)openBlock 54 | closeBlock:(DisplayCloseBlock)closeBlock 55 | completionBlock:(DisplayCompletionBlock)completionBlock; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /TLDragButton-demo/TLDragButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLDragButton.m 3 | // 按钮拖拽 4 | // 5 | // Created by andezhou on 15/7/10. 6 | // Copyright (c) 2015年 andezhou. All rights reserved. 7 | // 8 | 9 | #import "TLDragButton.h" 10 | 11 | static CGFloat kDuration = .2f; 12 | static CGFloat kBaseDuration = .4f; 13 | 14 | #define screenHeight self.superview.frame.size.height //[UIScreen mainScreen].bounds.size.height 15 | 16 | @interface TLDragButton () 17 | 18 | @property (nonatomic, assign) NSInteger dragIndex; 19 | @property (nonatomic, assign) CGPoint dragCenter; 20 | @property (nonatomic, strong) UIColor *bgColor; 21 | 22 | @property (nonatomic, assign) NSMutableArray *dragButtons; 23 | @property (nonatomic, assign) CGPoint startPoint; 24 | @property (nonatomic, assign) NSUInteger startIndex; 25 | 26 | @property (nonatomic, strong) UIView *displayView; 27 | @property (nonatomic, strong) UIButton *topView, *bottomView; 28 | 29 | @property (nonatomic, copy) DisplayOpenBlock openBlock; 30 | @property (nonatomic, copy) DisplayCloseBlock closeBlock; 31 | @property (nonatomic, copy) DisplayCompletionBlock completionBlock; 32 | 33 | @end 34 | 35 | @implementation TLDragButton 36 | 37 | #pragma mark - 38 | #pragma mark lifecycle 39 | - (instancetype)initWithFrame:(CGRect)frame { 40 | self = [super initWithFrame:frame]; 41 | if (self) { 42 | UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(buttonLongPressed:)]; 43 | [self addGestureRecognizer:longGesture]; 44 | } 45 | return self; 46 | } 47 | 48 | - (void)setBtnArray:(NSMutableArray *)btnArray 49 | { 50 | _btnArray = btnArray; 51 | 52 | for (TLDragButton *btn in btnArray) { 53 | btn.dragButtons = btnArray; 54 | } 55 | } 56 | 57 | #pragma mark - 58 | #pragma mark init methods 59 | 60 | #pragma mark - 61 | #pragma mark GestureRecognizer 62 | // 手势响应,并判断状态 63 | - (void)buttonLongPressed:(UILongPressGestureRecognizer *)gestureRecognizer 64 | { 65 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { 66 | 67 | [self touchesBegan:gestureRecognizer]; 68 | 69 | } else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { 70 | 71 | [self touchesMoved:gestureRecognizer]; 72 | 73 | } else { 74 | [self touchesEnded:gestureRecognizer]; 75 | } 76 | } 77 | 78 | // 拖拽开始 79 | - (void)touchesBegan:(UILongPressGestureRecognizer *)gestureRecognizer { 80 | [[self superview] bringSubviewToFront:self]; 81 | 82 | self.startPoint = [gestureRecognizer locationInView:self]; 83 | self.bgColor = self.backgroundColor; 84 | self.dragCenter = self.center; 85 | self.dragIndex = [self.dragButtons indexOfObject:self]; 86 | self.startIndex = [self.dragButtons indexOfObject:self]; 87 | 88 | [UIView animateWithDuration:kDuration animations:^{ 89 | self.backgroundColor = self.dragColor ? self.dragColor : self.bgColor; 90 | self.transform = CGAffineTransformMakeScale(1.2, 1.2); 91 | }]; 92 | } 93 | 94 | // 拖拽移动 95 | - (void)touchesMoved:(UILongPressGestureRecognizer *)gestureRecognizer { 96 | // 调整被拖拽按钮的center, 保证它根手指一起滑动 97 | CGPoint newPoint = [gestureRecognizer locationInView:self]; 98 | CGFloat deltaX = newPoint.x - self.startPoint.x; 99 | CGFloat deltaY = newPoint.y - self.startPoint.y; 100 | self.center = CGPointMake(self.center.x + deltaX, self.center.y + deltaY); 101 | 102 | for (NSInteger index = 0; index < self.dragButtons.count; index ++) { 103 | UIButton *button = self.dragButtons[index]; 104 | 105 | if (self.dragIndex != index) { 106 | if (CGRectContainsPoint(button.frame, self.center)) { 107 | [self adjustButtons:self index:index]; 108 | } 109 | } 110 | } 111 | } 112 | 113 | // 拖拽结束 114 | - (void)touchesEnded:(UILongPressGestureRecognizer *)gestureRecognizer { 115 | [UIView animateWithDuration:kDuration animations:^{ 116 | self.backgroundColor = self.bgColor; 117 | self.transform = CGAffineTransformIdentity; 118 | self.center = self.dragCenter; 119 | }]; 120 | 121 | // 判断按钮位置是否已经改变,如果发生改变通过代理通知父视图 122 | if (self.startIndex != self.dragIndex) { 123 | if ([self.delegate respondsToSelector:@selector(dragButton:dragButtons:)]) { 124 | [self.delegate dragButton:self dragButtons:self.dragButtons]; 125 | } 126 | } 127 | } 128 | 129 | // 调整按钮位置 130 | - (void)adjustButtons:(UIButton *)dragBtn index:(NSInteger)index { 131 | UIButton *moveBtn = self.dragButtons[index]; 132 | CGPoint moveCenter = moveBtn.center; 133 | 134 | __block CGPoint oldCenter = self.dragCenter; 135 | __block CGPoint nextCenter = CGPointZero; 136 | 137 | if (index < self.dragIndex) { // 将靠前的按钮移动到靠后的位置 138 | 139 | for (NSInteger num = self.dragIndex - 1; num >= index; num--) { 140 | // 将上一个按钮的位置赋值给当前按钮 141 | [UIView animateWithDuration:kDuration animations:^{ 142 | UIButton *nextBtn = [self.dragButtons objectAtIndex:num]; 143 | nextCenter = nextBtn.center; 144 | nextBtn.center = oldCenter; 145 | oldCenter = nextCenter; 146 | }]; 147 | } 148 | 149 | // 调整顺序 150 | [self.dragButtons insertObject:dragBtn atIndex:index]; 151 | [self.dragButtons removeObjectAtIndex:self.dragIndex + 1]; 152 | 153 | } else { // 将靠后的按钮移动到前边 154 | 155 | for (NSInteger num = self.dragIndex + 1; num <= index; num ++) { 156 | // 将上一个按钮的位置赋值给当前按钮 157 | [UIView animateWithDuration:kDuration animations:^{ 158 | UIButton *nextBtn = [self.dragButtons objectAtIndex:num]; 159 | nextCenter = nextBtn.center; 160 | nextBtn.center = oldCenter; 161 | oldCenter = nextCenter; 162 | }]; 163 | } 164 | 165 | // 调整顺序 166 | [self.dragButtons insertObject:dragBtn atIndex:index + 1]; 167 | [self.dragButtons removeObjectAtIndex:self.dragIndex]; 168 | } 169 | 170 | self.dragIndex = index; 171 | self.dragCenter = moveCenter; 172 | } 173 | 174 | #pragma mack - public methods 175 | - (void)openDisplayView:(UIView *)displayView 176 | openBlock:(DisplayOpenBlock)openBlock 177 | closeBlock:(DisplayCloseBlock)closeBlock 178 | completionBlock:(DisplayCompletionBlock)completionBlock { 179 | 180 | if (!self.lineCount) { 181 | #warning 如使用此方法,lineCount不能为空 182 | return; 183 | } 184 | // 回调block 185 | self.openBlock = openBlock; 186 | self.completionBlock = completionBlock; 187 | self.closeBlock = closeBlock; 188 | 189 | self.displayView = displayView; 190 | self.dragIndex = [self.dragButtons indexOfObject:self]; 191 | 192 | // 设置displayView的frame 193 | CGFloat height = CGRectGetHeight(self.displayView.frame); 194 | CGFloat width = CGRectGetWidth(self.displayView.frame); 195 | CGFloat position = CGRectGetMaxY(self.frame); 196 | 197 | CGFloat offsetY = 0.0f; 198 | // 检查父视图是否为UIScrollView 199 | if ([self.superview isKindOfClass:[UIScrollView class]]) { 200 | UIScrollView *scrollView = (UIScrollView *)self.superview; 201 | offsetY = scrollView.contentOffset.y; 202 | position -= offsetY; 203 | } 204 | 205 | // 检查点击的按钮是否全部在屏幕之中 206 | CGFloat btnOffset = 0.0f; 207 | if (position - screenHeight > 0) { 208 | btnOffset = position - screenHeight; 209 | // 此时position就是屏幕的高度 210 | position -= btnOffset; 211 | } 212 | 213 | // 屏幕不够显示displayView时,按钮向上偏移值 214 | CGFloat deltaY = 0.0f; 215 | if (position + height > screenHeight) { 216 | deltaY = height - (screenHeight - position); 217 | } 218 | 219 | // 初始化上下阴影 220 | CGRect upperRect = CGRectMake(0, offsetY, width, position); 221 | CGRect lowerRect = CGRectMake(0, position + offsetY, width, screenHeight - position); 222 | self.topView = [self buttonForRect:upperRect position:position]; 223 | self.bottomView = [self buttonForRect:lowerRect position:position]; 224 | 225 | // 设置展示视图 226 | CGRect showFrame = self.displayView.frame; 227 | showFrame.origin = CGPointMake(0, position + offsetY - deltaY); 228 | self.displayView.frame = showFrame; 229 | 230 | // 加载视图 231 | [self.superview addSubview:self.topView]; 232 | [self.superview addSubview:self.bottomView]; 233 | [self.superview insertSubview:self.displayView atIndex:0]; 234 | 235 | // 展开动画 236 | [self openAnimationWithDeltaY:deltaY btnOffset:btnOffset height:height]; 237 | 238 | // 透明变半透明 239 | [UIView animateWithDuration:kBaseDuration animations:^{ 240 | self.topView.alpha = 0.4f; 241 | self.bottomView.alpha = 0.4f; 242 | }]; 243 | 244 | // openBlock 245 | if (self.openBlock) { 246 | self.openBlock(self.displayView, kBaseDuration); 247 | } 248 | } 249 | 250 | #pragma mark - private methods 251 | // 关闭动画 252 | - (void)performClose:(UIButton *)sender { 253 | CGFloat height = CGRectGetHeight(self.displayView.frame); 254 | CGFloat position = CGRectGetMaxY(self.frame); 255 | 256 | CGFloat offsetY = 0.0f; 257 | // 检查父视图是否为UIScrollView 258 | if ([self.superview isKindOfClass:[UIScrollView class]]) { 259 | UIScrollView *scrollView = (UIScrollView *)self.superview; 260 | offsetY = scrollView.contentOffset.y; 261 | position = position - offsetY; 262 | } 263 | 264 | // 检查点击的按钮是否全部在屏幕之中 265 | CGFloat btnOffset = 0.0f; 266 | if (position - screenHeight > 0) { 267 | btnOffset = position - screenHeight; 268 | // 此时position就是屏幕的高度 269 | position -= btnOffset; 270 | } 271 | 272 | // 屏幕不够显示displayView时,按钮向上偏移值 273 | CGFloat deltaY = 0.0f; 274 | if (position + height > screenHeight) { 275 | deltaY = height - (screenHeight - position); 276 | } 277 | 278 | // 关闭动画 279 | [self closeAnimationWithDeltaY:deltaY btnOffset:btnOffset height:height]; 280 | 281 | // 半透明变透明 282 | [UIView animateWithDuration:kBaseDuration animations:^{ 283 | self.topView.alpha = 0.0f; 284 | self.bottomView.alpha = 0.0f; 285 | self.displayView.alpha = 0.0f; 286 | }]; 287 | 288 | // closeBlock 289 | if (self.closeBlock) { 290 | self.closeBlock(self.displayView, kBaseDuration); 291 | } 292 | } 293 | 294 | // 开启动画 295 | - (void)openAnimationWithDeltaY:(CGFloat)deltaY btnOffset:(CGFloat)btnOffset height:(CGFloat)height { 296 | // 获取当前点击所在的行 297 | NSUInteger line = self.dragIndex / self.lineCount + 1; 298 | NSUInteger count = self.lineCount * line; 299 | 300 | // 设置上下阴影的动画 301 | CABasicAnimation *topAnimation = [self positionMoveBasicAnimationFromValue:btnOffset toValue:-deltaY]; 302 | [self.topView.layer addAnimation:topAnimation forKey:@"top1"]; 303 | 304 | CABasicAnimation *bottomAnimation = [self positionMoveBasicAnimationFromValue:0 toValue:height - deltaY]; 305 | [self.bottomView.layer addAnimation:bottomAnimation forKey:@"bottom1"]; 306 | 307 | // 设置上下按钮动画 308 | CABasicAnimation *topDragAnimation = [self positionMoveBasicAnimationFromValue:0 toValue:-deltaY - btnOffset]; 309 | NSUInteger maxCount = count < self.dragButtons.count ? count : self.dragButtons.count; 310 | for (NSUInteger index = 0; index < maxCount; index ++) { 311 | TLDragButton *dragBtn = self.dragButtons[index]; 312 | [dragBtn.layer addAnimation:topDragAnimation forKey:@"topDrag1"]; 313 | } 314 | 315 | CABasicAnimation *bottomDragAnimation = [self positionMoveBasicAnimationFromValue:0 toValue:height - deltaY - btnOffset]; 316 | for (NSUInteger index = self.dragButtons.count - 1; index >= count; index --) { 317 | TLDragButton *dragBtn = self.dragButtons[index]; 318 | [dragBtn.layer addAnimation:bottomDragAnimation forKey:@"bottomDrag1"]; 319 | } 320 | } 321 | 322 | // 关闭动画 323 | - (void)closeAnimationWithDeltaY:(CGFloat)deltaY btnOffset:(CGFloat)btnOffset height:(CGFloat)height { 324 | NSUInteger line = self.dragIndex / self.lineCount + 1; 325 | NSUInteger count = self.lineCount * line; 326 | NSUInteger maxCount = count < self.dragButtons.count ? count : self.dragButtons.count; 327 | 328 | CGFloat fromvalue = height - deltaY; 329 | // 关闭上下button动画 330 | CABasicAnimation *topDragAnimation = [self positionMoveBasicAnimationFromValue:-deltaY - btnOffset toValue:0]; 331 | for (NSUInteger index = 0; index < maxCount; index ++) { 332 | TLDragButton *dragBtn = self.dragButtons[index]; 333 | [dragBtn.layer addAnimation:topDragAnimation forKey:@"topDrag2"]; 334 | } 335 | 336 | CABasicAnimation *bottomDragAnimation = [self positionMoveBasicAnimationFromValue:fromvalue - btnOffset toValue:0]; 337 | for (NSUInteger index = self.dragButtons.count - 1; index >= count; index --) { 338 | TLDragButton *dragBtn = self.dragButtons[index]; 339 | [dragBtn.layer addAnimation:bottomDragAnimation forKey:@"bottomDrag2"]; 340 | } 341 | 342 | // 关闭阴影动画 343 | CABasicAnimation *topAnimation = [self positionMoveBasicAnimationFromValue:-deltaY toValue:btnOffset]; 344 | [self.topView.layer addAnimation:topAnimation forKey:@"top2"]; 345 | 346 | CABasicAnimation *bottomAnimation = [self positionMoveBasicAnimationFromValue:fromvalue toValue:0]; 347 | [bottomAnimation setValue:@"close" forKey:@"animationType"]; 348 | bottomAnimation.delegate = self; 349 | [self.bottomView.layer addAnimation:bottomAnimation forKey:@"base"]; 350 | } 351 | 352 | // 初始化阴影按钮 353 | - (UIButton *)buttonForRect:(CGRect)rect position:(CGFloat)position { 354 | UIButton *btn = [[UIButton alloc] initWithFrame:rect]; 355 | btn.backgroundColor = [UIColor whiteColor]; 356 | btn.alpha = 0; 357 | [btn addTarget:self action:@selector(performClose:) forControlEvents:UIControlEventTouchUpInside]; 358 | return btn; 359 | } 360 | 361 | // 基本动画 362 | - (CABasicAnimation *)positionMoveBasicAnimationFromValue:(CGFloat)fromValue toValue:(CGFloat)toValue { 363 | CABasicAnimation *position = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"]; 364 | position.duration = kBaseDuration; 365 | position.speed = 1.1; 366 | position.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 367 | position.fromValue = @(fromValue); 368 | position.toValue = @(toValue); 369 | position.removedOnCompletion = NO; 370 | position.fillMode = kCAFillModeForwards; 371 | return position; 372 | } 373 | 374 | // CABasicAnimation的代理方法 375 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 376 | if ([[anim valueForKey:@"animationType"] isEqualToString:@"close"]) { 377 | [self.displayView removeFromSuperview]; 378 | [self.topView removeFromSuperview]; 379 | [self.bottomView removeFromSuperview]; 380 | 381 | self.displayView = nil; 382 | self.topView = nil; 383 | self.bottomView = nil; 384 | 385 | // completionBlock 386 | if (self.completionBlock) { 387 | self.completionBlock(); 388 | } 389 | } 390 | } 391 | 392 | @end 393 | -------------------------------------------------------------------------------- /TLDragButton-demo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // 按钮拖拽 4 | // 5 | // Created by andezhou on 15/7/9. 6 | // Copyright (c) 2015年 andezhou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TLDragButton-demo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // 按钮拖拽 4 | // 5 | // Created by andezhou on 15/7/9. 6 | // Copyright (c) 2015年 andezhou. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "TLDragButton.h" 11 | 12 | static NSUInteger kLineCount = 4; 13 | 14 | @interface ViewController () 15 | 16 | @property (nonatomic, strong) NSArray *tags; 17 | @property (nonatomic, strong) UIScrollView *scrollView; 18 | 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | self.title = @"拖拽"; 26 | self.view.backgroundColor = [UIColor whiteColor]; 27 | 28 | NSMutableArray *array = [NSMutableArray array]; 29 | CGFloat kMargin = 1; 30 | CGFloat width = ([UIScreen mainScreen].bounds.size.width - kMargin*(kLineCount + 1))/kLineCount; 31 | CGFloat height = 130; 32 | 33 | self.tags = @[@1, @4, @5, @7, @8, @9, @11, @14, @18]; 34 | 35 | self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 64)]; 36 | self.scrollView.backgroundColor = [UIColor lightGrayColor]; 37 | self.scrollView.contentSize = CGSizeMake(0, 5*131); 38 | [self.view addSubview:self.scrollView]; 39 | 40 | for (NSInteger index = 0; index < 20; index ++) { 41 | NSUInteger X = index % kLineCount; 42 | NSUInteger Y = index / kLineCount; 43 | 44 | TLDragButton *btn = [TLDragButton buttonWithType:UIButtonTypeCustom]; 45 | btn.frame = CGRectMake(X * (width + kMargin) + kMargin, Y * (height + kMargin), width, height); 46 | btn.backgroundColor = [self getColor]; 47 | btn.tag = index; 48 | btn.lineCount = kLineCount; 49 | btn.dragColor = [UIColor blueColor]; 50 | btn.delegate = self; 51 | [btn setTitle:[NSString stringWithFormat:@"%zi", index] forState:UIControlStateNormal]; 52 | [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 53 | [btn addTarget:self action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside]; 54 | [self.scrollView addSubview:btn]; 55 | 56 | [array addObject:btn]; 57 | btn.btnArray = array; 58 | } 59 | // Do any additional setup after loading the view, typically from a nib. 60 | } 61 | 62 | - (void)clickAction:(TLDragButton *)sender { 63 | NSLog(@"你点中了:%@", sender.currentTitle); 64 | 65 | if ([self.tags containsObject:@(sender.tag)]) { 66 | UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200)]; 67 | view.backgroundColor = [UIColor lightGrayColor]; 68 | [sender openDisplayView:view openBlock:^(UIView *displayView, CFTimeInterval duration) { 69 | // NSLog(@"开始"); 70 | self.scrollView.scrollEnabled = NO; 71 | } closeBlock:^(UIView *displayView, CFTimeInterval duration) { 72 | // NSLog(@"关闭"); 73 | } completionBlock:^{ 74 | // NSLog(@"完成"); 75 | self.scrollView.scrollEnabled = YES; 76 | }]; 77 | } 78 | } 79 | 80 | - (void)dragButton:(TLDragButton *)dragButton dragButtons:(NSArray *)dragButtons { 81 | NSString *currentTitle = dragButton.currentTitle; 82 | NSLog(@"%@位置发生了改变", currentTitle); 83 | } 84 | 85 | - (UIColor *)getColor { 86 | CGFloat red = arc4random() % 256; 87 | CGFloat green = arc4random() % 256; 88 | CGFloat blue = arc4random() % 256; 89 | return [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1]; 90 | } 91 | 92 | - (void)didReceiveMemoryWarning { 93 | [super didReceiveMemoryWarning]; 94 | // Dispose of any resources that can be recreated. 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /TLDragButton-demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TLDragButton-demo 4 | // 5 | // Created by andezhou on 15/7/10. 6 | // Copyright (c) 2015年 andezhou. 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 | -------------------------------------------------------------------------------- /TLDragButton-demoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.AMeD.hospitalMeeting.$(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 | -------------------------------------------------------------------------------- /TLDragButton-demoTests/TLDragButton_demoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TLDragButton_demoTests.m 3 | // TLDragButton-demoTests 4 | // 5 | // Created by andezhou on 15/7/10. 6 | // Copyright (c) 2015年 andezhou. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface TLDragButton_demoTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation TLDragButton_demoTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------