├── HDragImageView.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── HDragImageView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── HDragView │ ├── HDragItem.h │ ├── HDragItem.m │ ├── HDragItemListView.h │ ├── HDragItemListView.m │ ├── UIButton+Ex.h │ ├── UIButton+Ex.m │ ├── UIView+Ex.h │ ├── UIView+Ex.m │ ├── add_image@2x.png │ ├── wc_drag_delete@2x.png │ ├── wc_drag_delete@3x.png │ ├── wc_drag_delete_activate@2x.png │ └── wc_drag_delete_activate@3x.png ├── Info.plist ├── ViewController.h ├── ViewController.m ├── gif │ └── 微信朋友圈发布.gif └── main.m └── README.md /HDragImageView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4989338F2140156F00F6D8EE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4989338E2140156F00F6D8EE /* AppDelegate.m */; }; 11 | 498933922140156F00F6D8EE /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 498933912140156F00F6D8EE /* ViewController.m */; }; 12 | 498933952140156F00F6D8EE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 498933932140156F00F6D8EE /* Main.storyboard */; }; 13 | 498933972140156F00F6D8EE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 498933962140156F00F6D8EE /* Assets.xcassets */; }; 14 | 4989339A2140156F00F6D8EE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 498933982140156F00F6D8EE /* LaunchScreen.storyboard */; }; 15 | 4989339D2140157000F6D8EE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4989339C2140157000F6D8EE /* main.m */; }; 16 | 498933B12140158900F6D8EE /* UIView+Ex.m in Sources */ = {isa = PBXBuildFile; fileRef = 498933A42140158900F6D8EE /* UIView+Ex.m */; }; 17 | 498933B22140158900F6D8EE /* HDragItemListView.m in Sources */ = {isa = PBXBuildFile; fileRef = 498933A72140158900F6D8EE /* HDragItemListView.m */; }; 18 | 498933B32140158900F6D8EE /* wc_drag_delete_activate@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 498933A82140158900F6D8EE /* wc_drag_delete_activate@3x.png */; }; 19 | 498933B42140158900F6D8EE /* wc_drag_delete_activate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 498933A92140158900F6D8EE /* wc_drag_delete_activate@2x.png */; }; 20 | 498933B52140158900F6D8EE /* wc_drag_delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 498933AA2140158900F6D8EE /* wc_drag_delete@2x.png */; }; 21 | 498933B62140158900F6D8EE /* add_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 498933AB2140158900F6D8EE /* add_image@2x.png */; }; 22 | 498933B72140158900F6D8EE /* UIButton+Ex.m in Sources */ = {isa = PBXBuildFile; fileRef = 498933AC2140158900F6D8EE /* UIButton+Ex.m */; }; 23 | 498933B82140158900F6D8EE /* wc_drag_delete@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 498933AD2140158900F6D8EE /* wc_drag_delete@3x.png */; }; 24 | 498933B92140158900F6D8EE /* HDragItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 498933B02140158900F6D8EE /* HDragItem.m */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 4989338A2140156F00F6D8EE /* HDragImageView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HDragImageView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 4989338D2140156F00F6D8EE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 30 | 4989338E2140156F00F6D8EE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 31 | 498933902140156F00F6D8EE /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 32 | 498933912140156F00F6D8EE /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 33 | 498933942140156F00F6D8EE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 34 | 498933962140156F00F6D8EE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 35 | 498933992140156F00F6D8EE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 36 | 4989339B2140156F00F6D8EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 4989339C2140157000F6D8EE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 38 | 498933A42140158900F6D8EE /* UIView+Ex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Ex.m"; sourceTree = ""; }; 39 | 498933A52140158900F6D8EE /* UIButton+Ex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+Ex.h"; sourceTree = ""; }; 40 | 498933A62140158900F6D8EE /* HDragItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDragItem.h; sourceTree = ""; }; 41 | 498933A72140158900F6D8EE /* HDragItemListView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDragItemListView.m; sourceTree = ""; }; 42 | 498933A82140158900F6D8EE /* wc_drag_delete_activate@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "wc_drag_delete_activate@3x.png"; sourceTree = ""; }; 43 | 498933A92140158900F6D8EE /* wc_drag_delete_activate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "wc_drag_delete_activate@2x.png"; sourceTree = ""; }; 44 | 498933AA2140158900F6D8EE /* wc_drag_delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "wc_drag_delete@2x.png"; sourceTree = ""; }; 45 | 498933AB2140158900F6D8EE /* add_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "add_image@2x.png"; sourceTree = ""; }; 46 | 498933AC2140158900F6D8EE /* UIButton+Ex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+Ex.m"; sourceTree = ""; }; 47 | 498933AD2140158900F6D8EE /* wc_drag_delete@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "wc_drag_delete@3x.png"; sourceTree = ""; }; 48 | 498933AE2140158900F6D8EE /* UIView+Ex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Ex.h"; sourceTree = ""; }; 49 | 498933AF2140158900F6D8EE /* HDragItemListView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDragItemListView.h; sourceTree = ""; }; 50 | 498933B02140158900F6D8EE /* HDragItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDragItem.m; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | 498933872140156F00F6D8EE /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 498933812140156F00F6D8EE = { 65 | isa = PBXGroup; 66 | children = ( 67 | 4989338C2140156F00F6D8EE /* HDragImageView */, 68 | 4989338B2140156F00F6D8EE /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 4989338B2140156F00F6D8EE /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 4989338A2140156F00F6D8EE /* HDragImageView.app */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 4989338C2140156F00F6D8EE /* HDragImageView */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 498933A32140158900F6D8EE /* HDragView */, 84 | 4989338D2140156F00F6D8EE /* AppDelegate.h */, 85 | 4989338E2140156F00F6D8EE /* AppDelegate.m */, 86 | 498933902140156F00F6D8EE /* ViewController.h */, 87 | 498933912140156F00F6D8EE /* ViewController.m */, 88 | 498933932140156F00F6D8EE /* Main.storyboard */, 89 | 498933962140156F00F6D8EE /* Assets.xcassets */, 90 | 498933982140156F00F6D8EE /* LaunchScreen.storyboard */, 91 | 4989339B2140156F00F6D8EE /* Info.plist */, 92 | 4989339C2140157000F6D8EE /* main.m */, 93 | ); 94 | path = HDragImageView; 95 | sourceTree = ""; 96 | }; 97 | 498933A32140158900F6D8EE /* HDragView */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 498933A42140158900F6D8EE /* UIView+Ex.m */, 101 | 498933A52140158900F6D8EE /* UIButton+Ex.h */, 102 | 498933A62140158900F6D8EE /* HDragItem.h */, 103 | 498933A72140158900F6D8EE /* HDragItemListView.m */, 104 | 498933A82140158900F6D8EE /* wc_drag_delete_activate@3x.png */, 105 | 498933A92140158900F6D8EE /* wc_drag_delete_activate@2x.png */, 106 | 498933AA2140158900F6D8EE /* wc_drag_delete@2x.png */, 107 | 498933AB2140158900F6D8EE /* add_image@2x.png */, 108 | 498933AC2140158900F6D8EE /* UIButton+Ex.m */, 109 | 498933AD2140158900F6D8EE /* wc_drag_delete@3x.png */, 110 | 498933AE2140158900F6D8EE /* UIView+Ex.h */, 111 | 498933AF2140158900F6D8EE /* HDragItemListView.h */, 112 | 498933B02140158900F6D8EE /* HDragItem.m */, 113 | ); 114 | path = HDragView; 115 | sourceTree = ""; 116 | }; 117 | /* End PBXGroup section */ 118 | 119 | /* Begin PBXNativeTarget section */ 120 | 498933892140156F00F6D8EE /* HDragImageView */ = { 121 | isa = PBXNativeTarget; 122 | buildConfigurationList = 498933A02140157000F6D8EE /* Build configuration list for PBXNativeTarget "HDragImageView" */; 123 | buildPhases = ( 124 | 498933862140156F00F6D8EE /* Sources */, 125 | 498933872140156F00F6D8EE /* Frameworks */, 126 | 498933882140156F00F6D8EE /* Resources */, 127 | ); 128 | buildRules = ( 129 | ); 130 | dependencies = ( 131 | ); 132 | name = HDragImageView; 133 | productName = HDragImageView; 134 | productReference = 4989338A2140156F00F6D8EE /* HDragImageView.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 498933822140156F00F6D8EE /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastUpgradeCheck = 0940; 144 | ORGANIZATIONNAME = huangjianglong; 145 | TargetAttributes = { 146 | 498933892140156F00F6D8EE = { 147 | CreatedOnToolsVersion = 9.4.1; 148 | }; 149 | }; 150 | }; 151 | buildConfigurationList = 498933852140156F00F6D8EE /* Build configuration list for PBXProject "HDragImageView" */; 152 | compatibilityVersion = "Xcode 9.3"; 153 | developmentRegion = en; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | Base, 158 | ); 159 | mainGroup = 498933812140156F00F6D8EE; 160 | productRefGroup = 4989338B2140156F00F6D8EE /* Products */; 161 | projectDirPath = ""; 162 | projectRoot = ""; 163 | targets = ( 164 | 498933892140156F00F6D8EE /* HDragImageView */, 165 | ); 166 | }; 167 | /* End PBXProject section */ 168 | 169 | /* Begin PBXResourcesBuildPhase section */ 170 | 498933882140156F00F6D8EE /* Resources */ = { 171 | isa = PBXResourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 4989339A2140156F00F6D8EE /* LaunchScreen.storyboard in Resources */, 175 | 498933B52140158900F6D8EE /* wc_drag_delete@2x.png in Resources */, 176 | 498933B32140158900F6D8EE /* wc_drag_delete_activate@3x.png in Resources */, 177 | 498933972140156F00F6D8EE /* Assets.xcassets in Resources */, 178 | 498933B82140158900F6D8EE /* wc_drag_delete@3x.png in Resources */, 179 | 498933B42140158900F6D8EE /* wc_drag_delete_activate@2x.png in Resources */, 180 | 498933B62140158900F6D8EE /* add_image@2x.png in Resources */, 181 | 498933952140156F00F6D8EE /* Main.storyboard in Resources */, 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | }; 185 | /* End PBXResourcesBuildPhase section */ 186 | 187 | /* Begin PBXSourcesBuildPhase section */ 188 | 498933862140156F00F6D8EE /* Sources */ = { 189 | isa = PBXSourcesBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | 498933922140156F00F6D8EE /* ViewController.m in Sources */, 193 | 4989339D2140157000F6D8EE /* main.m in Sources */, 194 | 498933B22140158900F6D8EE /* HDragItemListView.m in Sources */, 195 | 4989338F2140156F00F6D8EE /* AppDelegate.m in Sources */, 196 | 498933B72140158900F6D8EE /* UIButton+Ex.m in Sources */, 197 | 498933B12140158900F6D8EE /* UIView+Ex.m in Sources */, 198 | 498933B92140158900F6D8EE /* HDragItem.m in Sources */, 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | /* End PBXSourcesBuildPhase section */ 203 | 204 | /* Begin PBXVariantGroup section */ 205 | 498933932140156F00F6D8EE /* Main.storyboard */ = { 206 | isa = PBXVariantGroup; 207 | children = ( 208 | 498933942140156F00F6D8EE /* Base */, 209 | ); 210 | name = Main.storyboard; 211 | sourceTree = ""; 212 | }; 213 | 498933982140156F00F6D8EE /* LaunchScreen.storyboard */ = { 214 | isa = PBXVariantGroup; 215 | children = ( 216 | 498933992140156F00F6D8EE /* Base */, 217 | ); 218 | name = LaunchScreen.storyboard; 219 | sourceTree = ""; 220 | }; 221 | /* End PBXVariantGroup section */ 222 | 223 | /* Begin XCBuildConfiguration section */ 224 | 4989339E2140157000F6D8EE /* Debug */ = { 225 | isa = XCBuildConfiguration; 226 | buildSettings = { 227 | ALWAYS_SEARCH_USER_PATHS = NO; 228 | CLANG_ANALYZER_NONNULL = YES; 229 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 231 | CLANG_CXX_LIBRARY = "libc++"; 232 | CLANG_ENABLE_MODULES = YES; 233 | CLANG_ENABLE_OBJC_ARC = YES; 234 | CLANG_ENABLE_OBJC_WEAK = YES; 235 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 236 | CLANG_WARN_BOOL_CONVERSION = YES; 237 | CLANG_WARN_COMMA = YES; 238 | CLANG_WARN_CONSTANT_CONVERSION = YES; 239 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 240 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 241 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 242 | CLANG_WARN_EMPTY_BODY = YES; 243 | CLANG_WARN_ENUM_CONVERSION = YES; 244 | CLANG_WARN_INFINITE_RECURSION = YES; 245 | CLANG_WARN_INT_CONVERSION = YES; 246 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 247 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 248 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 249 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 250 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 251 | CLANG_WARN_STRICT_PROTOTYPES = YES; 252 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 253 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 254 | CLANG_WARN_UNREACHABLE_CODE = YES; 255 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 256 | CODE_SIGN_IDENTITY = "iPhone Developer"; 257 | COPY_PHASE_STRIP = NO; 258 | DEBUG_INFORMATION_FORMAT = dwarf; 259 | ENABLE_STRICT_OBJC_MSGSEND = YES; 260 | ENABLE_TESTABILITY = YES; 261 | GCC_C_LANGUAGE_STANDARD = gnu11; 262 | GCC_DYNAMIC_NO_PIC = NO; 263 | GCC_NO_COMMON_BLOCKS = YES; 264 | GCC_OPTIMIZATION_LEVEL = 0; 265 | GCC_PREPROCESSOR_DEFINITIONS = ( 266 | "DEBUG=1", 267 | "$(inherited)", 268 | ); 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 276 | MTL_ENABLE_DEBUG_INFO = YES; 277 | ONLY_ACTIVE_ARCH = YES; 278 | SDKROOT = iphoneos; 279 | }; 280 | name = Debug; 281 | }; 282 | 4989339F2140157000F6D8EE /* Release */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ALWAYS_SEARCH_USER_PATHS = NO; 286 | CLANG_ANALYZER_NONNULL = YES; 287 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 288 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 289 | CLANG_CXX_LIBRARY = "libc++"; 290 | CLANG_ENABLE_MODULES = YES; 291 | CLANG_ENABLE_OBJC_ARC = YES; 292 | CLANG_ENABLE_OBJC_WEAK = YES; 293 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 294 | CLANG_WARN_BOOL_CONVERSION = YES; 295 | CLANG_WARN_COMMA = YES; 296 | CLANG_WARN_CONSTANT_CONVERSION = YES; 297 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 298 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 299 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 300 | CLANG_WARN_EMPTY_BODY = YES; 301 | CLANG_WARN_ENUM_CONVERSION = YES; 302 | CLANG_WARN_INFINITE_RECURSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 305 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 306 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 307 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 308 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 309 | CLANG_WARN_STRICT_PROTOTYPES = YES; 310 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 311 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 312 | CLANG_WARN_UNREACHABLE_CODE = YES; 313 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 314 | CODE_SIGN_IDENTITY = "iPhone Developer"; 315 | COPY_PHASE_STRIP = NO; 316 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 317 | ENABLE_NS_ASSERTIONS = NO; 318 | ENABLE_STRICT_OBJC_MSGSEND = YES; 319 | GCC_C_LANGUAGE_STANDARD = gnu11; 320 | GCC_NO_COMMON_BLOCKS = YES; 321 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 322 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 323 | GCC_WARN_UNDECLARED_SELECTOR = YES; 324 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 325 | GCC_WARN_UNUSED_FUNCTION = YES; 326 | GCC_WARN_UNUSED_VARIABLE = YES; 327 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 328 | MTL_ENABLE_DEBUG_INFO = NO; 329 | SDKROOT = iphoneos; 330 | VALIDATE_PRODUCT = YES; 331 | }; 332 | name = Release; 333 | }; 334 | 498933A12140157000F6D8EE /* Debug */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 338 | CODE_SIGN_STYLE = Automatic; 339 | INFOPLIST_FILE = HDragImageView/Info.plist; 340 | LD_RUNPATH_SEARCH_PATHS = ( 341 | "$(inherited)", 342 | "@executable_path/Frameworks", 343 | ); 344 | PRODUCT_BUNDLE_IDENTIFIER = www.huangjianglong.com.HDragImageView; 345 | PRODUCT_NAME = "$(TARGET_NAME)"; 346 | TARGETED_DEVICE_FAMILY = "1,2"; 347 | }; 348 | name = Debug; 349 | }; 350 | 498933A22140157000F6D8EE /* Release */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | CODE_SIGN_STYLE = Automatic; 355 | INFOPLIST_FILE = HDragImageView/Info.plist; 356 | LD_RUNPATH_SEARCH_PATHS = ( 357 | "$(inherited)", 358 | "@executable_path/Frameworks", 359 | ); 360 | PRODUCT_BUNDLE_IDENTIFIER = www.huangjianglong.com.HDragImageView; 361 | PRODUCT_NAME = "$(TARGET_NAME)"; 362 | TARGETED_DEVICE_FAMILY = "1,2"; 363 | }; 364 | name = Release; 365 | }; 366 | /* End XCBuildConfiguration section */ 367 | 368 | /* Begin XCConfigurationList section */ 369 | 498933852140156F00F6D8EE /* Build configuration list for PBXProject "HDragImageView" */ = { 370 | isa = XCConfigurationList; 371 | buildConfigurations = ( 372 | 4989339E2140157000F6D8EE /* Debug */, 373 | 4989339F2140157000F6D8EE /* Release */, 374 | ); 375 | defaultConfigurationIsVisible = 0; 376 | defaultConfigurationName = Release; 377 | }; 378 | 498933A02140157000F6D8EE /* Build configuration list for PBXNativeTarget "HDragImageView" */ = { 379 | isa = XCConfigurationList; 380 | buildConfigurations = ( 381 | 498933A12140157000F6D8EE /* Debug */, 382 | 498933A22140157000F6D8EE /* Release */, 383 | ); 384 | defaultConfigurationIsVisible = 0; 385 | defaultConfigurationName = Release; 386 | }; 387 | /* End XCConfigurationList section */ 388 | }; 389 | rootObject = 498933822140156F00F6D8EE /* Project object */; 390 | } 391 | -------------------------------------------------------------------------------- /HDragImageView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HDragImageView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. 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 | -------------------------------------------------------------------------------- /HDragImageView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. 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 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // 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. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /HDragImageView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /HDragImageView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /HDragImageView/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 | -------------------------------------------------------------------------------- /HDragImageView/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 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/HDragItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // HDragItem.h 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HDragItem : UIImageView 12 | 13 | @property (nonatomic, assign) BOOL isAdd; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/HDragItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // HDragItem.m 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import "HDragItem.h" 10 | 11 | @implementation HDragItem 12 | 13 | - (instancetype)init 14 | { 15 | self = [super init]; 16 | if (self) { 17 | self.userInteractionEnabled = YES; 18 | self.layer.masksToBounds = YES; 19 | self.contentMode = UIViewContentModeScaleAspectFill; 20 | } 21 | return self; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/HDragItemListView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HDragItemListView.h 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HDragItem.h" 11 | 12 | @interface HDragItemListView : UIView 13 | /** 14 | * item间距,和距离左,上间距,默认10 15 | */ 16 | @property (nonatomic, assign) CGFloat itemMargin; 17 | 18 | /** 19 | * 是否需要自定义ItemList高度,默认为Yes 20 | */ 21 | @property (nonatomic, assign) BOOL isFitItemListH; 22 | 23 | /** 24 | * 是否需要排序功能 25 | */ 26 | @property (nonatomic, assign) BOOL isSort; 27 | 28 | /** 29 | * 在排序的时候,放大标签的比例,必须大于1 30 | */ 31 | @property (nonatomic, assign) CGFloat scaleItemInSort; 32 | 33 | /******列表总列数 默认3列******/ 34 | /** 35 | * item间距会自动计算 36 | */ 37 | @property (nonatomic, assign) NSInteger itemListCols; 38 | 39 | /** 40 | * 显示拖拽到底部出现删除 默认yes 41 | */ 42 | @property (nonatomic, assign) BOOL showDeleteView; 43 | /** 44 | * DragItemBottomView 的高度 默认50 45 | */ 46 | @property (nonatomic, assign) CGFloat deleteViewHeight; 47 | 48 | /** 49 | * item列表的高度 50 | */ 51 | @property (nonatomic, assign) CGFloat itemListH; 52 | 53 | /** 54 | * 获取所有item 55 | */ 56 | @property (nonatomic, strong, readonly) NSMutableArray *itemArray; 57 | /** 58 | * item 最多个数 默认9个 59 | */ 60 | @property (nonatomic, assign) int maxItem; 61 | 62 | /** 63 | * 添加item 64 | * */ 65 | - (void)addItem:(HDragItem *)item; 66 | 67 | /** 68 | * 添加多个item 69 | */ 70 | - (void)addItems:(NSArray * )items; 71 | 72 | /** 73 | * 删除item 74 | */ 75 | - (void)deleteItem:(HDragItem *)item; 76 | 77 | /** 78 | * 点击标签,执行Block 79 | */ 80 | @property (nonatomic, strong) void(^clickItemBlock)(HDragItem *item); 81 | 82 | /** 83 | * 移除回调 84 | */ 85 | @property (nonatomic, strong) void(^deleteItemBlock)(HDragItem *item); 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/HDragItemListView.m: -------------------------------------------------------------------------------- 1 | // 2 | // HDragItemListView.m 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import "HDragItemListView.h" 10 | #import "UIButton+Ex.h" 11 | #import "UIView+Ex.h" 12 | 13 | #define SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width 14 | #define SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height 15 | 16 | @interface HDragItemListView() 17 | 18 | @property (nonatomic, strong) NSMutableArray *items; 19 | @property (nonatomic, assign) CGSize itemSize; 20 | /** 21 | * 需要移动的矩阵 22 | */ 23 | @property (nonatomic, assign) CGRect moveFinalRect; 24 | @property (nonatomic, assign) CGPoint oriCenter; 25 | 26 | @property (nonatomic, strong) UIView *deleteView; 27 | @end 28 | 29 | @implementation HDragItemListView 30 | 31 | - (NSMutableArray *)itemArray{ 32 | return [self.items mutableCopy]; 33 | } 34 | 35 | - (NSMutableArray *)items 36 | { 37 | if (!_items) { 38 | _items = [[NSMutableArray alloc] init]; 39 | } 40 | return _items; 41 | } 42 | 43 | - (CGFloat)itemListH 44 | { 45 | if (self.items.count <= 0) return 0; 46 | return CGRectGetMaxY([self.items.lastObject frame]) + _itemMargin; 47 | } 48 | 49 | - (instancetype)initWithFrame:(CGRect)frame 50 | { 51 | if (self = [super initWithFrame:frame]) { 52 | [self setup]; 53 | } 54 | 55 | return self; 56 | } 57 | 58 | 59 | #pragma mark - 初始化 60 | - (void)setup 61 | { 62 | _itemMargin = 10; 63 | _itemListCols = 3; 64 | _scaleItemInSort = 1; 65 | _isFitItemListH = YES; 66 | _showDeleteView = YES; 67 | _deleteViewHeight = 50.0; 68 | _maxItem = 9; 69 | CGFloat width = (self.frame.size.width - ((_itemListCols + 1) * _itemMargin)) / _itemListCols; 70 | _itemSize = CGSizeMake(width, width); 71 | self.clipsToBounds = YES; 72 | } 73 | 74 | - (void)setScaleItemInSort:(CGFloat)scaleItemInSort 75 | { 76 | if (_scaleItemInSort < 1) { 77 | @throw [NSException exceptionWithName:@"YZError" reason:@"(scaleTagInSort)缩放比例必须大于1" userInfo:nil]; 78 | } 79 | _scaleItemInSort = scaleItemInSort; 80 | } 81 | 82 | #pragma mark - 操作标签方法 83 | // 添加多个标签 84 | - (void)addItems:(NSArray *)items 85 | { 86 | if (self.frame.size.width == 0) { 87 | @throw [NSException exceptionWithName:@"YZError" reason:@"先设置标签列表的frame" userInfo:nil]; 88 | } 89 | 90 | for (HDragItem *item in items) { 91 | [self addItem:item]; 92 | } 93 | } 94 | 95 | // 添加标签 96 | - (void)addItem:(HDragItem *)item 97 | { 98 | 99 | //移除“添加”item 100 | if (self.items.count && self.items.count == _maxItem) { 101 | HDragItem *last = [self.items lastObject]; 102 | [self.items removeObject:last]; 103 | [last removeFromSuperview]; 104 | } 105 | 106 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickItem:)]; 107 | [item addGestureRecognizer:tap]; 108 | 109 | if (_isSort && !item.isAdd) { 110 | // 添加拖动手势 111 | UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; 112 | [item addGestureRecognizer:pan]; 113 | } 114 | [self addSubview:item]; 115 | 116 | NSInteger tag = self.items.count; 117 | HDragItem *addItem = nil; 118 | if (self.items.count) { 119 | HDragItem *lastItem = [self.items lastObject]; 120 | if (lastItem.isAdd) { 121 | addItem = lastItem; 122 | tag = lastItem.tag; 123 | lastItem.tag = tag +1; 124 | } 125 | } 126 | 127 | item.tag = tag; 128 | 129 | // 保存到数组 130 | if (addItem) { 131 | [self.items insertObject:item atIndex:self.items.count - 1]; 132 | } 133 | else { 134 | [self.items addObject:item]; 135 | } 136 | 137 | // 设置按钮的位置 138 | [self updateItemFrame:item.tag extreMargin:YES]; 139 | if (addItem) { 140 | [self updateItemFrame:addItem.tag extreMargin:YES]; 141 | } 142 | 143 | // 更新自己的高度 144 | if (_isFitItemListH) { 145 | CGRect frame = self.frame; 146 | frame.size.height = self.itemListH; 147 | [UIView animateWithDuration:0.25 animations:^{ 148 | self.frame = frame; 149 | }]; 150 | } 151 | } 152 | 153 | // 点击标签 154 | - (void)clickItem:(UITapGestureRecognizer *)tap 155 | { 156 | [self dismissKeyBord]; 157 | if (_clickItemBlock) { 158 | _clickItemBlock((HDragItem *)tap.view); 159 | } 160 | } 161 | 162 | // 拖动标签 163 | - (void)pan:(UIPanGestureRecognizer *)pan 164 | { 165 | [self dismissKeyBord]; 166 | 167 | //坐标转换 168 | CGRect rect = [self.superview convertRect:self.frame toView:[UIApplication sharedApplication].keyWindow]; 169 | 170 | // 获取偏移量 171 | CGPoint transP = [pan translationInView:self]; 172 | 173 | HDragItem *tagButton = (HDragItem *)pan.view; 174 | 175 | // 开始 176 | if (pan.state == UIGestureRecognizerStateBegan) { 177 | _oriCenter = tagButton.center; 178 | [UIView animateWithDuration:-.25 animations:^{ 179 | tagButton.transform = CGAffineTransformMakeScale(self->_scaleItemInSort, self->_scaleItemInSort); 180 | }]; 181 | 182 | if (self.showDeleteView) { 183 | [self showDeleteViewAnimation]; 184 | } 185 | 186 | [[UIApplication sharedApplication].keyWindow addSubview:tagButton]; 187 | 188 | tagButton.top = rect.origin.y + tagButton.top; 189 | tagButton.left = rect.origin.x + tagButton.left; 190 | } 191 | 192 | CGPoint center = tagButton.center; 193 | center.x += transP.x; 194 | center.y += transP.y; 195 | tagButton.center = center; 196 | 197 | // 改变 198 | if (pan.state == UIGestureRecognizerStateChanged) { 199 | 200 | // 获取当前按钮中心点在哪个按钮上 201 | HDragItem *otherButton = [self buttonCenterInButtons:tagButton]; 202 | 203 | if (otherButton && !otherButton.isAdd) { // 插入到当前按钮的位置 204 | // 获取插入的角标 205 | NSInteger i = otherButton.tag; 206 | 207 | // 获取当前角标 208 | NSInteger curI = tagButton.tag; 209 | 210 | _moveFinalRect = otherButton.frame; 211 | 212 | // 排序 213 | // 移除之前的按钮 214 | [self.items removeObject:tagButton]; 215 | [self.items insertObject:tagButton atIndex:i]; 216 | 217 | // 更新tag 218 | [self updateItem]; 219 | 220 | if (curI > i) { // 往前插 221 | 222 | // 更新之后标签frame 223 | [UIView animateWithDuration:0.25 animations:^{ 224 | [self updateLaterItemButtonFrame:i + 1]; 225 | }]; 226 | 227 | } else { // 往后插 228 | 229 | // 更新之前标签frame 230 | [UIView animateWithDuration:0.25 animations:^{ 231 | [self updateBeforeTagButtonFrame:i]; 232 | }]; 233 | } 234 | } 235 | 236 | if (self.showDeleteView) { 237 | if (tagButton.frame.origin.y + tagButton.frame.size.height > SCREEN_HEIGHT - _deleteViewHeight) { 238 | [self setDeleteViewDeleteState]; 239 | } 240 | else { 241 | [self setDeleteViewNormalState]; 242 | } 243 | } 244 | 245 | } 246 | 247 | // 结束 248 | if (pan.state == UIGestureRecognizerStateEnded) { 249 | BOOL deleted = NO; 250 | if (self.showDeleteView) { 251 | [self hiddenDeleteViewAnimation]; 252 | if (tagButton.frame.origin.y + tagButton.frame.size.height > SCREEN_HEIGHT - _deleteViewHeight) { 253 | deleted = YES; 254 | [self deleteItem:tagButton]; 255 | } 256 | } 257 | 258 | [UIView animateWithDuration:0.25 animations:^{ 259 | tagButton.transform = CGAffineTransformIdentity; 260 | if (self->_moveFinalRect.size.width <= 0) { 261 | tagButton.center = self->_oriCenter; 262 | } else { 263 | tagButton.frame = self->_moveFinalRect; 264 | } 265 | tagButton.left = tagButton.left + rect.origin.x; 266 | tagButton.top = tagButton.top + rect.origin.y; 267 | } completion:^(BOOL finished) { 268 | self->_moveFinalRect = CGRectZero; 269 | if (!deleted) { 270 | [self addSubview:tagButton]; 271 | tagButton.left = tagButton.left - rect.origin.x; 272 | tagButton.top = tagButton.top - rect.origin.y; 273 | } 274 | }]; 275 | 276 | } 277 | 278 | [pan setTranslation:CGPointZero inView:self]; 279 | } 280 | 281 | // 看下当前按钮中心点在哪个按钮上 282 | - (HDragItem *)buttonCenterInButtons:(HDragItem *)curItem 283 | { 284 | for (HDragItem *button in self.items) { 285 | if (curItem == button) continue; 286 | //坐标转换 287 | CGRect rect = [self.superview convertRect:self.frame toView:[UIApplication sharedApplication].keyWindow]; 288 | CGRect frame = CGRectMake(button.x + rect.origin.x, button.y + rect.origin.y, button.width, button.height); 289 | if (CGRectContainsPoint(frame, curItem.center)) { 290 | return button; 291 | } 292 | } 293 | return nil; 294 | } 295 | 296 | 297 | // 删除Itme 298 | - (void)deleteItem:(HDragItem *)item 299 | { 300 | [item removeFromSuperview]; 301 | 302 | // 移除数组 303 | [self.items removeObject:item]; 304 | 305 | // 更新item 306 | [self updateItem]; 307 | 308 | // 更新后面item的frame 309 | [UIView animateWithDuration:0.25 animations:^{ 310 | [self updateLaterItemButtonFrame:item.tag]; 311 | }]; 312 | 313 | // 更新自己的frame 314 | if (_isFitItemListH) { 315 | CGRect frame = self.frame; 316 | frame.size.height = self.itemListH; 317 | [UIView animateWithDuration:0.25 animations:^{ 318 | self.frame = frame; 319 | }]; 320 | } 321 | 322 | if (_deleteItemBlock) { 323 | _deleteItemBlock(nil); 324 | } 325 | } 326 | 327 | // 更新item 328 | - (void)updateItem 329 | { 330 | NSInteger count = self.items.count; 331 | for (int i = 0; i < count; i++) { 332 | UIButton *tagButton = self.items[i]; 333 | tagButton.tag = i; 334 | } 335 | } 336 | 337 | // 更新之前按钮 338 | - (void)updateBeforeTagButtonFrame:(NSInteger)beforeI 339 | { 340 | for (int i = 0; i < beforeI; i++) { 341 | // 更新按钮 342 | [self updateItemFrame:i extreMargin:NO]; 343 | } 344 | } 345 | 346 | // 更新以后按钮 347 | - (void)updateLaterItemButtonFrame:(NSInteger)laterI 348 | { 349 | NSInteger count = self.items.count; 350 | 351 | for (NSInteger i = laterI; i < count; i++) { 352 | // 更新按钮 353 | [self updateItemFrame:i extreMargin:NO]; 354 | } 355 | } 356 | 357 | - (void)updateItemFrame:(NSInteger)i extreMargin:(BOOL)extreMargin 358 | { 359 | // 获取上一个按钮 360 | NSInteger preI = i - 1; 361 | 362 | // 定义上一个按钮 363 | HDragItem *preItem; 364 | 365 | // 过滤上一个角标 366 | if (preI >= 0) { 367 | preItem = self.items[preI]; 368 | } 369 | 370 | // 获取当前按钮 371 | HDragItem *tagItem = self.items[i]; 372 | 373 | [self setupItemButtonRegularFrame:tagItem]; 374 | 375 | } 376 | 377 | // 计算标签按钮frame(按规律排布) 378 | - (void)setupItemButtonRegularFrame:(HDragItem *)tagItem 379 | { 380 | // 获取角标 381 | NSInteger i = tagItem.tag; 382 | NSInteger col = i % _itemListCols; 383 | NSInteger row = i / _itemListCols; 384 | CGFloat btnW = _itemSize.width; 385 | CGFloat btnH = _itemSize.height; 386 | // NSInteger margin = (self.bounds.size.width - _itemListCols * btnW - 2 * _itemMargin) / (_itemListCols - 1); 387 | CGFloat btnX = col * (btnW + _itemMargin) + _itemMargin; 388 | CGFloat btnY = row * (btnH + _itemMargin); 389 | tagItem.frame = CGRectMake(btnX, btnY, btnW, btnH); 390 | } 391 | 392 | #pragma mark - 底部删除 视图 393 | - (UIView *)deleteView{ 394 | if (!_deleteView) { 395 | _deleteView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT, SCREEN_WIDTH, _deleteViewHeight)]; 396 | _deleteView.backgroundColor = [UIColor redColor]; 397 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 398 | button.tag = 201809; 399 | [button setImage:[UIImage imageNamed:@"wc_drag_delete"] forState:UIControlStateNormal]; 400 | [button setImage:[UIImage imageNamed:@"wc_drag_delete_activate"] forState:UIControlStateSelected]; 401 | [button setTitle:@"拖到此处删除" forState:UIControlStateNormal]; 402 | [button setTitle:@"松手即可删除" forState:UIControlStateSelected]; 403 | [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 404 | button.titleLabel.font = [UIFont systemFontOfSize:12]; 405 | [button layoutButtonWithEdgeInsetsStyle:TYButtonEdgeInsetsStyleTop imageTitleSpace:30]; 406 | [_deleteView addSubview:button]; 407 | [button sizeToFit]; 408 | CGRect frame = button.frame; 409 | frame.origin.x = (_deleteView.frame.size.width - frame.size.width) / 2; 410 | frame.origin.y = (_deleteViewHeight - frame.size.height) / 2 + 5; 411 | button.frame = frame; 412 | 413 | [[UIApplication sharedApplication].keyWindow addSubview:_deleteView]; 414 | } 415 | return _deleteView; 416 | } 417 | 418 | - (void)showDeleteViewAnimation{ 419 | self.deleteView.hidden = NO; 420 | [UIView animateWithDuration:0.25 animations:^{ 421 | self.deleteView.transform = CGAffineTransformTranslate( self.deleteView.transform, 0, - self->_deleteViewHeight); 422 | 423 | } completion:^(BOOL finished) { 424 | 425 | }]; 426 | } 427 | 428 | - (void)hiddenDeleteViewAnimation{ 429 | [UIView animateWithDuration:0.25 animations:^{ 430 | self.deleteView.transform = CGAffineTransformIdentity; 431 | } completion:^(BOOL finished) { 432 | 433 | }]; 434 | } 435 | 436 | - (void)setDeleteViewDeleteState{ 437 | UIButton *button = (UIButton *)[_deleteView viewWithTag:201809]; 438 | button.selected = YES; 439 | } 440 | 441 | - (void)setDeleteViewNormalState{ 442 | UIButton *button = (UIButton *)[_deleteView viewWithTag:201809]; 443 | button.selected = NO; 444 | } 445 | 446 | - (void)dismissKeyBord{ 447 | [[[UIApplication sharedApplication] keyWindow] endEditing:YES]; 448 | } 449 | 450 | @end 451 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/UIButton+Ex.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Ex.h 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, TYButtonEdgeInsetsStyle) { 12 | TYButtonEdgeInsetsStyleTop, // image在上,label在下 13 | TYButtonEdgeInsetsStyleLeft, // image在左,label在右 14 | TYButtonEdgeInsetsStyleBottom, // image在下,label在上 15 | TYButtonEdgeInsetsStyleRight // image在右,label在左 16 | }; 17 | 18 | 19 | @interface UIButton (Ex) 20 | /** 21 | * 设置button的titleLabel和imageView的布局样式,及间距 22 | * 23 | * @param style titleLabel和imageView的布局样式 24 | * @param space titleLabel和imageView的间距 25 | */ 26 | - (void)layoutButtonWithEdgeInsetsStyle:(TYButtonEdgeInsetsStyle)style 27 | imageTitleSpace:(CGFloat)space; 28 | @end 29 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/UIButton+Ex.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+Ex.m 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import "UIButton+Ex.h" 10 | 11 | @implementation UIButton (Ex) 12 | 13 | - (void)layoutButtonWithEdgeInsetsStyle:(TYButtonEdgeInsetsStyle)style 14 | imageTitleSpace:(CGFloat)space 15 | { 16 | // 1. 得到imageView和titleLabel的宽、高 17 | CGFloat imageWidth = self.imageView.frame.size.width; 18 | CGFloat imageHeight = self.imageView.frame.size.height; 19 | 20 | CGFloat labelWidth = 0.0; 21 | CGFloat labelHeight = 0.0; 22 | if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0) { 23 | // 由于iOS8中titleLabel的size为0,用下面的这种设置 24 | labelWidth = self.titleLabel.intrinsicContentSize.width; 25 | labelHeight = self.titleLabel.intrinsicContentSize.height; 26 | } else { 27 | labelWidth = self.titleLabel.frame.size.width; 28 | labelHeight = self.titleLabel.frame.size.height; 29 | } 30 | 31 | // 2. 声明全局的imageEdgeInsets和labelEdgeInsets 32 | UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero; 33 | UIEdgeInsets labelEdgeInsets = UIEdgeInsetsZero; 34 | 35 | // 3. 根据style和space得到imageEdgeInsets和labelEdgeInsets的值 36 | switch (style) { 37 | case TYButtonEdgeInsetsStyleTop: 38 | { 39 | //CGFloat top, CGFloat left, CGFloat bottom, CGFloat right 40 | imageEdgeInsets = UIEdgeInsetsMake(-labelHeight-space/2.0, 0, 0, -labelWidth); 41 | labelEdgeInsets = UIEdgeInsetsMake(0, -30, -imageHeight-space/2.0, 0); 42 | } 43 | break; 44 | case TYButtonEdgeInsetsStyleLeft: 45 | { 46 | imageEdgeInsets = UIEdgeInsetsMake(0, -space/2.0, 0, space/2.0); 47 | labelEdgeInsets = UIEdgeInsetsMake(0, space/2.0, 0, -space/2.0); 48 | } 49 | break; 50 | case TYButtonEdgeInsetsStyleBottom: 51 | { 52 | imageEdgeInsets = UIEdgeInsetsMake(0, 0, -labelHeight-space/2.0, -labelWidth); 53 | labelEdgeInsets = UIEdgeInsetsMake(-imageHeight-space/2.0, -imageWidth, 0, 0); 54 | } 55 | break; 56 | case TYButtonEdgeInsetsStyleRight: 57 | { 58 | imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth+space/2.0, 0, -labelWidth-space/2.0); 59 | labelEdgeInsets = UIEdgeInsetsMake(0, -imageWidth-space/2.0, 0, imageWidth+space/2.0); 60 | } 61 | break; 62 | default: 63 | break; 64 | } 65 | // 4. 赋值 66 | self.titleEdgeInsets = labelEdgeInsets; 67 | self.imageEdgeInsets = imageEdgeInsets; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/UIView+Ex.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Ex.h 3 | // QianLongZan 4 | // 5 | // Created by wufeilinMacmini on 16/10/8. 6 | // Copyright © 2016年 szteyou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Ex) 12 | 13 | @property (nonatomic, assign) CGFloat x; 14 | @property (nonatomic, assign) CGFloat y; 15 | @property (nonatomic, assign) CGFloat centerX; 16 | @property (nonatomic, assign) CGFloat centerY; 17 | @property (nonatomic, assign) CGFloat width; 18 | @property (nonatomic, assign) CGFloat height; 19 | @property (nonatomic, assign) CGSize size; 20 | 21 | @property (nonatomic, assign) CGFloat top; 22 | @property (nonatomic, assign) CGFloat bottom; 23 | @property (nonatomic, assign) CGFloat left; 24 | @property (nonatomic, assign) CGFloat right; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/UIView+Ex.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Ex.m 3 | // QianLongZan 4 | // 5 | // Created by wufeilinMacmini on 16/10/8. 6 | // Copyright © 2016年 szteyou. All rights reserved. 7 | // 8 | 9 | #import "UIView+Ex.h" 10 | 11 | @implementation UIView (Ex) 12 | 13 | - (void)setX:(CGFloat)x 14 | { 15 | CGRect frame = self.frame; 16 | frame.origin.x = x; 17 | self.frame = frame; 18 | } 19 | 20 | - (CGFloat)x 21 | { 22 | return self.frame.origin.x; 23 | } 24 | 25 | - (void)setY:(CGFloat)y 26 | { 27 | CGRect frame = self.frame; 28 | frame.origin.y = y; 29 | self.frame = frame; 30 | } 31 | 32 | - (CGFloat)y 33 | { 34 | return self.frame.origin.y; 35 | } 36 | 37 | - (void)setCenterX:(CGFloat)centerX 38 | { 39 | CGPoint center = self.center; 40 | center.x = centerX; 41 | self.center = center; 42 | } 43 | 44 | - (CGFloat)centerX 45 | { 46 | return self.center.x; 47 | } 48 | 49 | - (void)setCenterY:(CGFloat)centerY 50 | { 51 | CGPoint center = self.center; 52 | center.y = centerY; 53 | self.center = center; 54 | } 55 | 56 | - (CGFloat)centerY 57 | { 58 | return self.center.y; 59 | } 60 | 61 | - (void)setWidth:(CGFloat)width 62 | { 63 | CGRect frame = self.frame; 64 | frame.size.width = width; 65 | self.frame = frame; 66 | } 67 | 68 | - (CGFloat)width 69 | { 70 | return self.frame.size.width; 71 | } 72 | 73 | - (void)setHeight:(CGFloat)height 74 | { 75 | CGRect frame = self.frame; 76 | frame.size.height = height; 77 | self.frame = frame; 78 | } 79 | 80 | - (CGFloat)height 81 | { 82 | return self.frame.size.height; 83 | } 84 | 85 | - (void)setSize:(CGSize)size 86 | { 87 | CGRect frame = self.frame; 88 | frame.size = size; 89 | self.frame = frame; 90 | } 91 | 92 | - (CGSize)size 93 | { 94 | return self.frame.size; 95 | } 96 | 97 | - (void)setTop:(CGFloat)t 98 | { 99 | self.frame = CGRectMake(self.left, t, self.width, self.height); 100 | } 101 | 102 | - (CGFloat)top 103 | { 104 | return self.frame.origin.y; 105 | } 106 | 107 | - (void)setBottom:(CGFloat)b 108 | { 109 | self.frame = CGRectMake(self.left, b - self.height, self.width, self.height); 110 | } 111 | 112 | - (CGFloat)bottom 113 | { 114 | return self.frame.origin.y + self.frame.size.height; 115 | } 116 | 117 | - (void)setLeft:(CGFloat)l 118 | { 119 | self.frame = CGRectMake(l, self.top, self.width, self.height); 120 | } 121 | 122 | - (CGFloat)left 123 | { 124 | return self.frame.origin.x; 125 | } 126 | 127 | - (void)setRight:(CGFloat)r 128 | { 129 | self.frame = CGRectMake(r - self.width, self.top, self.width, self.height); 130 | } 131 | 132 | - (CGFloat)right 133 | { 134 | return self.frame.origin.x + self.frame.size.width; 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /HDragImageView/HDragView/add_image@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jethuang/HDragImageView/91aef3e465f1d29f74d9c781f7aef8ccf0dcc5e6/HDragImageView/HDragView/add_image@2x.png -------------------------------------------------------------------------------- /HDragImageView/HDragView/wc_drag_delete@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jethuang/HDragImageView/91aef3e465f1d29f74d9c781f7aef8ccf0dcc5e6/HDragImageView/HDragView/wc_drag_delete@2x.png -------------------------------------------------------------------------------- /HDragImageView/HDragView/wc_drag_delete@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jethuang/HDragImageView/91aef3e465f1d29f74d9c781f7aef8ccf0dcc5e6/HDragImageView/HDragView/wc_drag_delete@3x.png -------------------------------------------------------------------------------- /HDragImageView/HDragView/wc_drag_delete_activate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jethuang/HDragImageView/91aef3e465f1d29f74d9c781f7aef8ccf0dcc5e6/HDragImageView/HDragView/wc_drag_delete_activate@2x.png -------------------------------------------------------------------------------- /HDragImageView/HDragView/wc_drag_delete_activate@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jethuang/HDragImageView/91aef3e465f1d29f74d9c781f7aef8ccf0dcc5e6/HDragImageView/HDragView/wc_drag_delete_activate@3x.png -------------------------------------------------------------------------------- /HDragImageView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /HDragImageView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /HDragImageView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HDragImageDemo 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "HDragItemListView.h" 11 | #import "UIView+Ex.h" 12 | 13 | #define kSingleLineHeight 36 14 | #define kMaxLines 6 15 | 16 | @interface ViewController () 17 | 18 | @property (nonatomic, strong) UITableView *tableView; 19 | @property (nonatomic, strong) HDragItemListView *itemList; 20 | @property (nonatomic, strong) UIView *headerView; 21 | @property (nonatomic, strong) UITextView *textView; 22 | 23 | @property (nonatomic, assign) CGFloat lastTextViewHeight; 24 | 25 | @end 26 | 27 | @implementation ViewController 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | // Do any additional setup after loading the view, typically from a nib. 32 | 33 | HDragItem *item = [[HDragItem alloc] init]; 34 | item.backgroundColor = [UIColor clearColor]; 35 | item.image = [UIImage imageNamed:@"add_image"]; 36 | item.isAdd = YES; 37 | 38 | // 创建标签列表 39 | HDragItemListView *itemList = [[HDragItemListView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 0)]; 40 | self.itemList = itemList; 41 | itemList.backgroundColor = [UIColor clearColor]; 42 | // 高度可以设置为0,会自动跟随标题计算 43 | // 设置排序时,缩放比例 44 | itemList.scaleItemInSort = 1.3; 45 | // 需要排序 46 | itemList.isSort = YES; 47 | itemList.isFitItemListH = YES; 48 | 49 | [itemList addItem:item]; 50 | 51 | __weak typeof(self) weakSelf = self; 52 | 53 | [itemList setClickItemBlock:^(HDragItem *item) { 54 | if (item.isAdd) { 55 | NSLog(@"添加"); 56 | [weakSelf showUIImagePickerController]; 57 | } 58 | }]; 59 | 60 | /** 61 | * 移除tag 高度变化,得重设 62 | */ 63 | itemList.deleteItemBlock = ^(HDragItem *item) { 64 | HDragItem *lastItem = [weakSelf.itemList.itemArray lastObject]; 65 | dispatch_async(dispatch_get_main_queue(), ^{ 66 | if (!lastItem.isAdd) { 67 | HDragItem *item = [[HDragItem alloc] init]; 68 | item.backgroundColor = [UIColor clearColor]; 69 | item.image = [UIImage imageNamed:@"add_image"]; 70 | item.isAdd = YES; 71 | [weakSelf.itemList addItem:item]; 72 | } 73 | [weakSelf updateHeaderViewHeight]; 74 | }); 75 | }; 76 | 77 | [self.view addSubview:itemList]; 78 | 79 | _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height) style:UITableViewStylePlain]; 80 | _tableView.delegate = self; 81 | _tableView.dataSource = self; 82 | _tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; 83 | [self.view addSubview:_tableView]; 84 | 85 | UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, itemList.frame.size.height)]; 86 | 87 | [headerView addSubview:itemList]; 88 | 89 | _textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 10, self.view.bounds.size.width, kSingleLineHeight)]; 90 | _textView.font = [UIFont systemFontOfSize:16]; 91 | _textView.text = @" 发表动态"; 92 | [headerView addSubview:_textView]; 93 | 94 | itemList.y = _textView.height + 20; 95 | headerView.height = itemList.height + itemList.y; 96 | 97 | _tableView.tableHeaderView = headerView; 98 | _tableView.tableFooterView = [UIView new]; 99 | 100 | [_tableView registerClass:UITableViewCell.class forCellReuseIdentifier:NSStringFromClass(UITableViewCell.class)]; 101 | 102 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewChange:) name:UITextViewTextDidChangeNotification object:nil]; 103 | 104 | } 105 | 106 | //更新头部高度 107 | - (void)updateHeaderViewHeight{ 108 | self.itemList.y = _textView.height + 20; 109 | self.tableView.tableHeaderView.height = self.itemList.itemListH + self.itemList.y; 110 | [self.tableView beginUpdates]; //加上这对代码,改header的时候,会有动画,不然比较僵硬 111 | self.tableView.tableHeaderView = self.tableView.tableHeaderView; 112 | [self.tableView endUpdates]; 113 | } 114 | 115 | 116 | - (void)didReceiveMemoryWarning { 117 | [super didReceiveMemoryWarning]; 118 | // Dispose of any resources that can be recreated. 119 | } 120 | 121 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 122 | return 3; 123 | } 124 | 125 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 126 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(UITableViewCell.class)]; 127 | if (indexPath.row == 0) { 128 | cell.textLabel.text = @"所在位置"; 129 | } else if (indexPath.row == 1) { 130 | cell.textLabel.text = @"谁可以看"; 131 | } else if (indexPath.row == 2) { 132 | cell.textLabel.text = @"提醒谁看"; 133 | } 134 | return cell; 135 | } 136 | 137 | 138 | #pragma mark - textView 139 | - (void)textViewChange:(NSNotificationCenter *)notifi{ 140 | CGSize size = [_textView sizeThatFits:CGSizeMake(self.view.frame.size.width, CGFLOAT_MAX)]; 141 | CGFloat height = size.height; 142 | BOOL scrollEnabled = NO; 143 | if (height > kSingleLineHeight * kMaxLines) { 144 | height = kSingleLineHeight * kMaxLines; 145 | scrollEnabled = YES; 146 | } 147 | _textView.scrollEnabled = scrollEnabled; 148 | _textView.height = height; 149 | 150 | if (_lastTextViewHeight != height && _lastTextViewHeight > 0) { //换行 151 | [self updateHeaderViewHeight]; 152 | } 153 | 154 | _lastTextViewHeight = height; 155 | } 156 | 157 | #pragma mark - UIImagePickerController 158 | - (void)showUIImagePickerController{ 159 | UIImagePickerController *controller = [[UIImagePickerController alloc] init]; 160 | controller.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 161 | controller.delegate = self; 162 | [self presentViewController:controller animated:YES completion:nil]; 163 | } 164 | 165 | - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ 166 | 167 | UIImage *image = info[@"UIImagePickerControllerOriginalImage"]; 168 | 169 | [picker dismissViewControllerAnimated:YES completion:^{ 170 | HDragItem *item = [[HDragItem alloc] init]; 171 | item.image = image; 172 | item.backgroundColor = [UIColor purpleColor]; 173 | [self.itemList addItem:item]; 174 | dispatch_async(dispatch_get_main_queue(), ^{ 175 | [self updateHeaderViewHeight]; 176 | }); 177 | }]; 178 | } 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /HDragImageView/gif/微信朋友圈发布.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jethuang/HDragImageView/91aef3e465f1d29f74d9c781f7aef8ccf0dcc5e6/HDragImageView/gif/微信朋友圈发布.gif -------------------------------------------------------------------------------- /HDragImageView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HDragImageView 4 | // 5 | // Created by 黄江龙 on 2018/9/5. 6 | // Copyright © 2018年 huangjianglong. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HDragImageView 2 | 高仿微信发布朋友圈,选择图片时拖拽删除 组件 3 | ![image](https://github.com/Jethuang/HDragImageView/blob/master/HDragImageView/gif/%E5%BE%AE%E4%BF%A1%E6%9C%8B%E5%8F%8B%E5%9C%88%E5%8F%91%E5%B8%83.gif) 4 | --------------------------------------------------------------------------------