├── README.md └── WPAlertControl ├── WPAlertControl.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── Developer.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── Developer.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── WPAlertControl ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── WPAlertControl.h ├── WPAlertControl.m ├── WPView.h ├── WPView.m └── main.m ├── WPAlertControlTests ├── Info.plist └── WPAlertControlTests.m └── WPAlertControlUITests ├── Info.plist └── WPAlertControlUITests.m /README.md: -------------------------------------------------------------------------------- 1 | # WPAlertControl 2 | 上下左右中心,多层级全方位弹框 3 | Upper and lower center, multi-level all-round cartridge, easy to create, 4 | support multi-level push one line code creation to solve the project% 80 cartridge requirements 5 | 6 | * animateView 动画视图 animateView的size必须有值 7 | * begin 视图开始弹出的类型 8 | * endType 动画结束弹出的类型 9 | * constant 常量 默认0 -1==居中 动画结束时候的frame+上常量 可以微调动画结束后的frame 10 | * beginInterval 视图弹出的持续时间 11 | * endInterval 视图结束弹出的时间 12 | * masColor 蒙版的颜色 13 | * pan 是否支持拖动隐藏 14 | * rootControl alert弹出试图的根控制器 15 | * masClick 蒙版点击执行 return NO 蒙版不会消失 YES蒙版消失 默认YES 16 | * animateStatus alert弹框的当前状态 即将显示 -> 显示完成 -> 即将消失 -> 消失完成 17 | * alertLevel 当前动画的等级 默认为1 设置了pushAnimateView后会累加 18 | * items 菜单内容 19 | * index item 点击的索引 20 | * animateType 动画类型 21 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8BE27593224A0E32003E0612 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE27592224A0E32003E0612 /* AppDelegate.m */; }; 11 | 8BE27596224A0E32003E0612 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE27595224A0E32003E0612 /* ViewController.m */; }; 12 | 8BE27599224A0E32003E0612 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8BE27597224A0E32003E0612 /* Main.storyboard */; }; 13 | 8BE2759B224A0E34003E0612 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8BE2759A224A0E34003E0612 /* Assets.xcassets */; }; 14 | 8BE2759E224A0E34003E0612 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8BE2759C224A0E34003E0612 /* LaunchScreen.storyboard */; }; 15 | 8BE275A1224A0E34003E0612 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE275A0224A0E34003E0612 /* main.m */; }; 16 | 8BE275AB224A0E34003E0612 /* WPAlertControlTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE275AA224A0E34003E0612 /* WPAlertControlTests.m */; }; 17 | 8BE275B6224A0E34003E0612 /* WPAlertControlUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE275B5224A0E34003E0612 /* WPAlertControlUITests.m */; }; 18 | 8BE275C7224A0E5E003E0612 /* WPAlertControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE275C5224A0E5D003E0612 /* WPAlertControl.m */; }; 19 | 8BE275C8224A0E5E003E0612 /* WPView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE275C6224A0E5E003E0612 /* WPView.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 8BE275A7224A0E34003E0612 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 8BE27586224A0E32003E0612 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 8BE2758D224A0E32003E0612; 28 | remoteInfo = WPAlertControl; 29 | }; 30 | 8BE275B2224A0E34003E0612 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 8BE27586224A0E32003E0612 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 8BE2758D224A0E32003E0612; 35 | remoteInfo = WPAlertControl; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 8BE2758E224A0E32003E0612 /* WPAlertControl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WPAlertControl.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 8BE27591224A0E32003E0612 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 42 | 8BE27592224A0E32003E0612 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 43 | 8BE27594224A0E32003E0612 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 44 | 8BE27595224A0E32003E0612 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 45 | 8BE27598224A0E32003E0612 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 46 | 8BE2759A224A0E34003E0612 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 47 | 8BE2759D224A0E34003E0612 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 48 | 8BE2759F224A0E34003E0612 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 8BE275A0224A0E34003E0612 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 50 | 8BE275A6224A0E34003E0612 /* WPAlertControlTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WPAlertControlTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 8BE275AA224A0E34003E0612 /* WPAlertControlTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WPAlertControlTests.m; sourceTree = ""; }; 52 | 8BE275AC224A0E34003E0612 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 8BE275B1224A0E34003E0612 /* WPAlertControlUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WPAlertControlUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 8BE275B5224A0E34003E0612 /* WPAlertControlUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WPAlertControlUITests.m; sourceTree = ""; }; 55 | 8BE275B7224A0E34003E0612 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 8BE275C3224A0E5D003E0612 /* WPAlertControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPAlertControl.h; sourceTree = ""; }; 57 | 8BE275C4224A0E5D003E0612 /* WPView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPView.h; sourceTree = ""; }; 58 | 8BE275C5224A0E5D003E0612 /* WPAlertControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPAlertControl.m; sourceTree = ""; }; 59 | 8BE275C6224A0E5E003E0612 /* WPView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPView.m; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 8BE2758B224A0E32003E0612 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | 8BE275A3224A0E34003E0612 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 8BE275AE224A0E34003E0612 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | 8BE27585224A0E32003E0612 = { 88 | isa = PBXGroup; 89 | children = ( 90 | 8BE27590224A0E32003E0612 /* WPAlertControl */, 91 | 8BE275A9224A0E34003E0612 /* WPAlertControlTests */, 92 | 8BE275B4224A0E34003E0612 /* WPAlertControlUITests */, 93 | 8BE2758F224A0E32003E0612 /* Products */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | 8BE2758F224A0E32003E0612 /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 8BE2758E224A0E32003E0612 /* WPAlertControl.app */, 101 | 8BE275A6224A0E34003E0612 /* WPAlertControlTests.xctest */, 102 | 8BE275B1224A0E34003E0612 /* WPAlertControlUITests.xctest */, 103 | ); 104 | name = Products; 105 | sourceTree = ""; 106 | }; 107 | 8BE27590224A0E32003E0612 /* WPAlertControl */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 8BE275C3224A0E5D003E0612 /* WPAlertControl.h */, 111 | 8BE275C5224A0E5D003E0612 /* WPAlertControl.m */, 112 | 8BE275C4224A0E5D003E0612 /* WPView.h */, 113 | 8BE275C6224A0E5E003E0612 /* WPView.m */, 114 | 8BE27591224A0E32003E0612 /* AppDelegate.h */, 115 | 8BE27592224A0E32003E0612 /* AppDelegate.m */, 116 | 8BE27594224A0E32003E0612 /* ViewController.h */, 117 | 8BE27595224A0E32003E0612 /* ViewController.m */, 118 | 8BE27597224A0E32003E0612 /* Main.storyboard */, 119 | 8BE2759A224A0E34003E0612 /* Assets.xcassets */, 120 | 8BE2759C224A0E34003E0612 /* LaunchScreen.storyboard */, 121 | 8BE2759F224A0E34003E0612 /* Info.plist */, 122 | 8BE275A0224A0E34003E0612 /* main.m */, 123 | ); 124 | path = WPAlertControl; 125 | sourceTree = ""; 126 | }; 127 | 8BE275A9224A0E34003E0612 /* WPAlertControlTests */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 8BE275AA224A0E34003E0612 /* WPAlertControlTests.m */, 131 | 8BE275AC224A0E34003E0612 /* Info.plist */, 132 | ); 133 | path = WPAlertControlTests; 134 | sourceTree = ""; 135 | }; 136 | 8BE275B4224A0E34003E0612 /* WPAlertControlUITests */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 8BE275B5224A0E34003E0612 /* WPAlertControlUITests.m */, 140 | 8BE275B7224A0E34003E0612 /* Info.plist */, 141 | ); 142 | path = WPAlertControlUITests; 143 | sourceTree = ""; 144 | }; 145 | /* End PBXGroup section */ 146 | 147 | /* Begin PBXNativeTarget section */ 148 | 8BE2758D224A0E32003E0612 /* WPAlertControl */ = { 149 | isa = PBXNativeTarget; 150 | buildConfigurationList = 8BE275BA224A0E34003E0612 /* Build configuration list for PBXNativeTarget "WPAlertControl" */; 151 | buildPhases = ( 152 | 8BE2758A224A0E32003E0612 /* Sources */, 153 | 8BE2758B224A0E32003E0612 /* Frameworks */, 154 | 8BE2758C224A0E32003E0612 /* Resources */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | ); 160 | name = WPAlertControl; 161 | productName = WPAlertControl; 162 | productReference = 8BE2758E224A0E32003E0612 /* WPAlertControl.app */; 163 | productType = "com.apple.product-type.application"; 164 | }; 165 | 8BE275A5224A0E34003E0612 /* WPAlertControlTests */ = { 166 | isa = PBXNativeTarget; 167 | buildConfigurationList = 8BE275BD224A0E34003E0612 /* Build configuration list for PBXNativeTarget "WPAlertControlTests" */; 168 | buildPhases = ( 169 | 8BE275A2224A0E34003E0612 /* Sources */, 170 | 8BE275A3224A0E34003E0612 /* Frameworks */, 171 | 8BE275A4224A0E34003E0612 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | 8BE275A8224A0E34003E0612 /* PBXTargetDependency */, 177 | ); 178 | name = WPAlertControlTests; 179 | productName = WPAlertControlTests; 180 | productReference = 8BE275A6224A0E34003E0612 /* WPAlertControlTests.xctest */; 181 | productType = "com.apple.product-type.bundle.unit-test"; 182 | }; 183 | 8BE275B0224A0E34003E0612 /* WPAlertControlUITests */ = { 184 | isa = PBXNativeTarget; 185 | buildConfigurationList = 8BE275C0224A0E34003E0612 /* Build configuration list for PBXNativeTarget "WPAlertControlUITests" */; 186 | buildPhases = ( 187 | 8BE275AD224A0E34003E0612 /* Sources */, 188 | 8BE275AE224A0E34003E0612 /* Frameworks */, 189 | 8BE275AF224A0E34003E0612 /* Resources */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | 8BE275B3224A0E34003E0612 /* PBXTargetDependency */, 195 | ); 196 | name = WPAlertControlUITests; 197 | productName = WPAlertControlUITests; 198 | productReference = 8BE275B1224A0E34003E0612 /* WPAlertControlUITests.xctest */; 199 | productType = "com.apple.product-type.bundle.ui-testing"; 200 | }; 201 | /* End PBXNativeTarget section */ 202 | 203 | /* Begin PBXProject section */ 204 | 8BE27586224A0E32003E0612 /* Project object */ = { 205 | isa = PBXProject; 206 | attributes = { 207 | LastUpgradeCheck = 1010; 208 | ORGANIZATIONNAME = Developer; 209 | TargetAttributes = { 210 | 8BE2758D224A0E32003E0612 = { 211 | CreatedOnToolsVersion = 10.1; 212 | }; 213 | 8BE275A5224A0E34003E0612 = { 214 | CreatedOnToolsVersion = 10.1; 215 | TestTargetID = 8BE2758D224A0E32003E0612; 216 | }; 217 | 8BE275B0224A0E34003E0612 = { 218 | CreatedOnToolsVersion = 10.1; 219 | TestTargetID = 8BE2758D224A0E32003E0612; 220 | }; 221 | }; 222 | }; 223 | buildConfigurationList = 8BE27589224A0E32003E0612 /* Build configuration list for PBXProject "WPAlertControl" */; 224 | compatibilityVersion = "Xcode 9.3"; 225 | developmentRegion = en; 226 | hasScannedForEncodings = 0; 227 | knownRegions = ( 228 | en, 229 | Base, 230 | ); 231 | mainGroup = 8BE27585224A0E32003E0612; 232 | productRefGroup = 8BE2758F224A0E32003E0612 /* Products */; 233 | projectDirPath = ""; 234 | projectRoot = ""; 235 | targets = ( 236 | 8BE2758D224A0E32003E0612 /* WPAlertControl */, 237 | 8BE275A5224A0E34003E0612 /* WPAlertControlTests */, 238 | 8BE275B0224A0E34003E0612 /* WPAlertControlUITests */, 239 | ); 240 | }; 241 | /* End PBXProject section */ 242 | 243 | /* Begin PBXResourcesBuildPhase section */ 244 | 8BE2758C224A0E32003E0612 /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | 8BE2759E224A0E34003E0612 /* LaunchScreen.storyboard in Resources */, 249 | 8BE2759B224A0E34003E0612 /* Assets.xcassets in Resources */, 250 | 8BE27599224A0E32003E0612 /* Main.storyboard in Resources */, 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | }; 254 | 8BE275A4224A0E34003E0612 /* Resources */ = { 255 | isa = PBXResourcesBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | ); 259 | runOnlyForDeploymentPostprocessing = 0; 260 | }; 261 | 8BE275AF224A0E34003E0612 /* Resources */ = { 262 | isa = PBXResourcesBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | /* End PBXResourcesBuildPhase section */ 269 | 270 | /* Begin PBXSourcesBuildPhase section */ 271 | 8BE2758A224A0E32003E0612 /* Sources */ = { 272 | isa = PBXSourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | 8BE27596224A0E32003E0612 /* ViewController.m in Sources */, 276 | 8BE275A1224A0E34003E0612 /* main.m in Sources */, 277 | 8BE27593224A0E32003E0612 /* AppDelegate.m in Sources */, 278 | 8BE275C7224A0E5E003E0612 /* WPAlertControl.m in Sources */, 279 | 8BE275C8224A0E5E003E0612 /* WPView.m in Sources */, 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | }; 283 | 8BE275A2224A0E34003E0612 /* Sources */ = { 284 | isa = PBXSourcesBuildPhase; 285 | buildActionMask = 2147483647; 286 | files = ( 287 | 8BE275AB224A0E34003E0612 /* WPAlertControlTests.m in Sources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | 8BE275AD224A0E34003E0612 /* Sources */ = { 292 | isa = PBXSourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | 8BE275B6224A0E34003E0612 /* WPAlertControlUITests.m in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | /* End PBXSourcesBuildPhase section */ 300 | 301 | /* Begin PBXTargetDependency section */ 302 | 8BE275A8224A0E34003E0612 /* PBXTargetDependency */ = { 303 | isa = PBXTargetDependency; 304 | target = 8BE2758D224A0E32003E0612 /* WPAlertControl */; 305 | targetProxy = 8BE275A7224A0E34003E0612 /* PBXContainerItemProxy */; 306 | }; 307 | 8BE275B3224A0E34003E0612 /* PBXTargetDependency */ = { 308 | isa = PBXTargetDependency; 309 | target = 8BE2758D224A0E32003E0612 /* WPAlertControl */; 310 | targetProxy = 8BE275B2224A0E34003E0612 /* PBXContainerItemProxy */; 311 | }; 312 | /* End PBXTargetDependency section */ 313 | 314 | /* Begin PBXVariantGroup section */ 315 | 8BE27597224A0E32003E0612 /* Main.storyboard */ = { 316 | isa = PBXVariantGroup; 317 | children = ( 318 | 8BE27598224A0E32003E0612 /* Base */, 319 | ); 320 | name = Main.storyboard; 321 | sourceTree = ""; 322 | }; 323 | 8BE2759C224A0E34003E0612 /* LaunchScreen.storyboard */ = { 324 | isa = PBXVariantGroup; 325 | children = ( 326 | 8BE2759D224A0E34003E0612 /* Base */, 327 | ); 328 | name = LaunchScreen.storyboard; 329 | sourceTree = ""; 330 | }; 331 | /* End PBXVariantGroup section */ 332 | 333 | /* Begin XCBuildConfiguration section */ 334 | 8BE275B8224A0E34003E0612 /* Debug */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ALWAYS_SEARCH_USER_PATHS = NO; 338 | CLANG_ANALYZER_NONNULL = YES; 339 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 340 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 341 | CLANG_CXX_LIBRARY = "libc++"; 342 | CLANG_ENABLE_MODULES = YES; 343 | CLANG_ENABLE_OBJC_ARC = YES; 344 | CLANG_ENABLE_OBJC_WEAK = YES; 345 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 346 | CLANG_WARN_BOOL_CONVERSION = YES; 347 | CLANG_WARN_COMMA = YES; 348 | CLANG_WARN_CONSTANT_CONVERSION = YES; 349 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 350 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 351 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 352 | CLANG_WARN_EMPTY_BODY = YES; 353 | CLANG_WARN_ENUM_CONVERSION = YES; 354 | CLANG_WARN_INFINITE_RECURSION = YES; 355 | CLANG_WARN_INT_CONVERSION = YES; 356 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 357 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 358 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 359 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 360 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 361 | CLANG_WARN_STRICT_PROTOTYPES = YES; 362 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 363 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 364 | CLANG_WARN_UNREACHABLE_CODE = YES; 365 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 366 | CODE_SIGN_IDENTITY = "iPhone Developer"; 367 | COPY_PHASE_STRIP = NO; 368 | DEBUG_INFORMATION_FORMAT = dwarf; 369 | ENABLE_STRICT_OBJC_MSGSEND = YES; 370 | ENABLE_TESTABILITY = YES; 371 | GCC_C_LANGUAGE_STANDARD = gnu11; 372 | GCC_DYNAMIC_NO_PIC = NO; 373 | GCC_NO_COMMON_BLOCKS = YES; 374 | GCC_OPTIMIZATION_LEVEL = 0; 375 | GCC_PREPROCESSOR_DEFINITIONS = ( 376 | "DEBUG=1", 377 | "$(inherited)", 378 | ); 379 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 380 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 381 | GCC_WARN_UNDECLARED_SELECTOR = YES; 382 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 383 | GCC_WARN_UNUSED_FUNCTION = YES; 384 | GCC_WARN_UNUSED_VARIABLE = YES; 385 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 386 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 387 | MTL_FAST_MATH = YES; 388 | ONLY_ACTIVE_ARCH = YES; 389 | SDKROOT = iphoneos; 390 | }; 391 | name = Debug; 392 | }; 393 | 8BE275B9224A0E34003E0612 /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | ALWAYS_SEARCH_USER_PATHS = NO; 397 | CLANG_ANALYZER_NONNULL = YES; 398 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 399 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 400 | CLANG_CXX_LIBRARY = "libc++"; 401 | CLANG_ENABLE_MODULES = YES; 402 | CLANG_ENABLE_OBJC_ARC = YES; 403 | CLANG_ENABLE_OBJC_WEAK = YES; 404 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 405 | CLANG_WARN_BOOL_CONVERSION = YES; 406 | CLANG_WARN_COMMA = YES; 407 | CLANG_WARN_CONSTANT_CONVERSION = YES; 408 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 409 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 410 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 411 | CLANG_WARN_EMPTY_BODY = YES; 412 | CLANG_WARN_ENUM_CONVERSION = YES; 413 | CLANG_WARN_INFINITE_RECURSION = YES; 414 | CLANG_WARN_INT_CONVERSION = YES; 415 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 416 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 417 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 418 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 419 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 420 | CLANG_WARN_STRICT_PROTOTYPES = YES; 421 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 422 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 423 | CLANG_WARN_UNREACHABLE_CODE = YES; 424 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 425 | CODE_SIGN_IDENTITY = "iPhone Developer"; 426 | COPY_PHASE_STRIP = NO; 427 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 428 | ENABLE_NS_ASSERTIONS = NO; 429 | ENABLE_STRICT_OBJC_MSGSEND = YES; 430 | GCC_C_LANGUAGE_STANDARD = gnu11; 431 | GCC_NO_COMMON_BLOCKS = YES; 432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 433 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 434 | GCC_WARN_UNDECLARED_SELECTOR = YES; 435 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 436 | GCC_WARN_UNUSED_FUNCTION = YES; 437 | GCC_WARN_UNUSED_VARIABLE = YES; 438 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 439 | MTL_ENABLE_DEBUG_INFO = NO; 440 | MTL_FAST_MATH = YES; 441 | SDKROOT = iphoneos; 442 | VALIDATE_PRODUCT = YES; 443 | }; 444 | name = Release; 445 | }; 446 | 8BE275BB224A0E34003E0612 /* Debug */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 450 | CODE_SIGN_STYLE = Automatic; 451 | DEVELOPMENT_TEAM = YSZFMHLD4Y; 452 | INFOPLIST_FILE = WPAlertControl/Info.plist; 453 | LD_RUNPATH_SEARCH_PATHS = ( 454 | "$(inherited)", 455 | "@executable_path/Frameworks", 456 | ); 457 | PRODUCT_BUNDLE_IDENTIFIER = com.alert.WPAlertControl; 458 | PRODUCT_NAME = "$(TARGET_NAME)"; 459 | TARGETED_DEVICE_FAMILY = "1,2"; 460 | }; 461 | name = Debug; 462 | }; 463 | 8BE275BC224A0E34003E0612 /* Release */ = { 464 | isa = XCBuildConfiguration; 465 | buildSettings = { 466 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 467 | CODE_SIGN_STYLE = Automatic; 468 | DEVELOPMENT_TEAM = YSZFMHLD4Y; 469 | INFOPLIST_FILE = WPAlertControl/Info.plist; 470 | LD_RUNPATH_SEARCH_PATHS = ( 471 | "$(inherited)", 472 | "@executable_path/Frameworks", 473 | ); 474 | PRODUCT_BUNDLE_IDENTIFIER = com.alert.WPAlertControl; 475 | PRODUCT_NAME = "$(TARGET_NAME)"; 476 | TARGETED_DEVICE_FAMILY = "1,2"; 477 | }; 478 | name = Release; 479 | }; 480 | 8BE275BE224A0E34003E0612 /* Debug */ = { 481 | isa = XCBuildConfiguration; 482 | buildSettings = { 483 | BUNDLE_LOADER = "$(TEST_HOST)"; 484 | CODE_SIGN_STYLE = Automatic; 485 | DEVELOPMENT_TEAM = YSZFMHLD4Y; 486 | INFOPLIST_FILE = WPAlertControlTests/Info.plist; 487 | LD_RUNPATH_SEARCH_PATHS = ( 488 | "$(inherited)", 489 | "@executable_path/Frameworks", 490 | "@loader_path/Frameworks", 491 | ); 492 | PRODUCT_BUNDLE_IDENTIFIER = com.alert.WPAlertControlTests; 493 | PRODUCT_NAME = "$(TARGET_NAME)"; 494 | TARGETED_DEVICE_FAMILY = "1,2"; 495 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WPAlertControl.app/WPAlertControl"; 496 | }; 497 | name = Debug; 498 | }; 499 | 8BE275BF224A0E34003E0612 /* Release */ = { 500 | isa = XCBuildConfiguration; 501 | buildSettings = { 502 | BUNDLE_LOADER = "$(TEST_HOST)"; 503 | CODE_SIGN_STYLE = Automatic; 504 | DEVELOPMENT_TEAM = YSZFMHLD4Y; 505 | INFOPLIST_FILE = WPAlertControlTests/Info.plist; 506 | LD_RUNPATH_SEARCH_PATHS = ( 507 | "$(inherited)", 508 | "@executable_path/Frameworks", 509 | "@loader_path/Frameworks", 510 | ); 511 | PRODUCT_BUNDLE_IDENTIFIER = com.alert.WPAlertControlTests; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | TARGETED_DEVICE_FAMILY = "1,2"; 514 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WPAlertControl.app/WPAlertControl"; 515 | }; 516 | name = Release; 517 | }; 518 | 8BE275C1224A0E34003E0612 /* Debug */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | CODE_SIGN_STYLE = Automatic; 522 | DEVELOPMENT_TEAM = YSZFMHLD4Y; 523 | INFOPLIST_FILE = WPAlertControlUITests/Info.plist; 524 | LD_RUNPATH_SEARCH_PATHS = ( 525 | "$(inherited)", 526 | "@executable_path/Frameworks", 527 | "@loader_path/Frameworks", 528 | ); 529 | PRODUCT_BUNDLE_IDENTIFIER = com.alert.WPAlertControlUITests; 530 | PRODUCT_NAME = "$(TARGET_NAME)"; 531 | TARGETED_DEVICE_FAMILY = "1,2"; 532 | TEST_TARGET_NAME = WPAlertControl; 533 | }; 534 | name = Debug; 535 | }; 536 | 8BE275C2224A0E34003E0612 /* Release */ = { 537 | isa = XCBuildConfiguration; 538 | buildSettings = { 539 | CODE_SIGN_STYLE = Automatic; 540 | DEVELOPMENT_TEAM = YSZFMHLD4Y; 541 | INFOPLIST_FILE = WPAlertControlUITests/Info.plist; 542 | LD_RUNPATH_SEARCH_PATHS = ( 543 | "$(inherited)", 544 | "@executable_path/Frameworks", 545 | "@loader_path/Frameworks", 546 | ); 547 | PRODUCT_BUNDLE_IDENTIFIER = com.alert.WPAlertControlUITests; 548 | PRODUCT_NAME = "$(TARGET_NAME)"; 549 | TARGETED_DEVICE_FAMILY = "1,2"; 550 | TEST_TARGET_NAME = WPAlertControl; 551 | }; 552 | name = Release; 553 | }; 554 | /* End XCBuildConfiguration section */ 555 | 556 | /* Begin XCConfigurationList section */ 557 | 8BE27589224A0E32003E0612 /* Build configuration list for PBXProject "WPAlertControl" */ = { 558 | isa = XCConfigurationList; 559 | buildConfigurations = ( 560 | 8BE275B8224A0E34003E0612 /* Debug */, 561 | 8BE275B9224A0E34003E0612 /* Release */, 562 | ); 563 | defaultConfigurationIsVisible = 0; 564 | defaultConfigurationName = Release; 565 | }; 566 | 8BE275BA224A0E34003E0612 /* Build configuration list for PBXNativeTarget "WPAlertControl" */ = { 567 | isa = XCConfigurationList; 568 | buildConfigurations = ( 569 | 8BE275BB224A0E34003E0612 /* Debug */, 570 | 8BE275BC224A0E34003E0612 /* Release */, 571 | ); 572 | defaultConfigurationIsVisible = 0; 573 | defaultConfigurationName = Release; 574 | }; 575 | 8BE275BD224A0E34003E0612 /* Build configuration list for PBXNativeTarget "WPAlertControlTests" */ = { 576 | isa = XCConfigurationList; 577 | buildConfigurations = ( 578 | 8BE275BE224A0E34003E0612 /* Debug */, 579 | 8BE275BF224A0E34003E0612 /* Release */, 580 | ); 581 | defaultConfigurationIsVisible = 0; 582 | defaultConfigurationName = Release; 583 | }; 584 | 8BE275C0224A0E34003E0612 /* Build configuration list for PBXNativeTarget "WPAlertControlUITests" */ = { 585 | isa = XCConfigurationList; 586 | buildConfigurations = ( 587 | 8BE275C1224A0E34003E0612 /* Debug */, 588 | 8BE275C2224A0E34003E0612 /* Release */, 589 | ); 590 | defaultConfigurationIsVisible = 0; 591 | defaultConfigurationName = Release; 592 | }; 593 | /* End XCConfigurationList section */ 594 | }; 595 | rootObject = 8BE27586224A0E32003E0612 /* Project object */; 596 | } 597 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl.xcodeproj/project.xcworkspace/xcuserdata/Developer.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenping-office/WPAlertControl/ec0ef729235250a380c32bf2d387e0526b0a838a/WPAlertControl/WPAlertControl.xcodeproj/project.xcworkspace/xcuserdata/Developer.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl.xcodeproj/xcuserdata/Developer.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl.xcodeproj/xcuserdata/Developer.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WPAlertControl.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/26. 6 | // Copyright © 2019 Developer. 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 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/26. 6 | // Copyright © 2019 Developer. 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 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/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 | } -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/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 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/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 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/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 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/26. 6 | // Copyright © 2019 Developer. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/25. 6 | // Copyright © 2019 Developer. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "WPAlertControl.h" 11 | #import "WPView.h" 12 | 13 | @interface ViewController () 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 23 | 24 | // 快速创建一个item弹框 items 可以是 @[@"string",@"string"] 也可以是 @[@[@"string"],@[@"string"]] 25 | //[WPAlertControl alertItemsForRootControl:<#(UIViewController *)#> animateType:<#(WPAlertAnimateType)#> items:<#(NSArray *)#> index:<#^NSArray *(NSInteger index, NSUInteger alertLevel, WPAlertControl *alertControl)index#>] 26 | // 到中心只需要设置 constant == -1 27 | [self itemsAlert]; 28 | }]; 29 | view1.text = @"item弹框"; 30 | 31 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 32 | [self bottemAlert]; 33 | }]; 34 | view2.text = @"底部弹框"; 35 | 36 | WPView *view3 = [WPView viewWithTapClick:^(id other) { 37 | [self rightAlert]; 38 | }]; 39 | view3.text = @"右边弹框"; 40 | 41 | WPView *view4 = [WPView viewWithTapClick:^(id other) { 42 | [self centerAlert]; 43 | }]; 44 | view4.text = @"中心弹框"; 45 | 46 | WPView *view5 = [WPView viewWithTapClick:^(id other) { 47 | [self leftAlert]; 48 | }]; 49 | view5.text = @"左边弹框"; 50 | 51 | WPView *view6 = [WPView viewWithTapClick:^(id other) { 52 | [self topAlert]; 53 | }]; 54 | view6.text = @"顶部弹框"; 55 | 56 | view1.backgroundColor = [UIColor purpleColor]; 57 | view2.backgroundColor = [UIColor purpleColor]; 58 | view3.backgroundColor = [UIColor purpleColor]; 59 | view4.backgroundColor = [UIColor purpleColor]; 60 | view5.backgroundColor = [UIColor purpleColor]; 61 | view6.backgroundColor = [UIColor purpleColor]; 62 | 63 | view1.frame = CGRectMake(50, 50, 100, 100); 64 | view2.frame = CGRectMake(self.view.frame.size.width - 150, view1.frame.origin.y, 100, 100); 65 | view3.frame = CGRectMake(50, 200, 100, 100); 66 | view4.frame = CGRectMake(view2.frame.origin.x, view3.frame.origin.y, 100, 100); 67 | view5.frame = CGRectMake(view1.frame.origin.x, 350, 100, 100); 68 | view6.frame = CGRectMake(view4.frame.origin.x, view5.frame.origin.y, 100, 100); 69 | 70 | [self.view addSubview:view1]; 71 | [self.view addSubview:view2]; 72 | [self.view addSubview:view3]; 73 | [self.view addSubview:view4]; 74 | [self.view addSubview:view5]; 75 | [self.view addSubview:view6]; 76 | 77 | // [WPAlertControl alertForView:<#(UIView *)#> begin:<#(WPAlertBeginType)#> end:<#(WPAlertEndType)#> animateType:<#(WPAlertAnimateType)#> constant:<#(CGFloat)#> animageBeginInterval:<#(CGFloat)#> animageEndInterval:<#(CGFloat)#> maskColor:<#(UIColor *)#> pan:<#(BOOL)#> rootControl:<#(UIViewController *)#> maskClick:<#^BOOL(NSInteger index, NSUInteger alertLevel, WPAlertControl *alertControl)click#> animateStatus:<#^(WPAlertShowStatus status, WPAlertControl *alertControl)animateStatus#>] 78 | } 79 | 80 | - (void)moveCenter 81 | { 82 | CGSize screenSize = [UIScreen mainScreen].bounds.size; 83 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 84 | 85 | [WPAlertControl alertHiddenForRootControl:self completion:^(WPAlertShowStatus status, WPAlertControl *alertControl) { 86 | 87 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 88 | [WPAlertControl alertHiddenForRootControl:self completion:nil]; 89 | }]; 90 | view2.frame = CGRectMake(0, 0, screenSize.width, 300); 91 | view2.backgroundColor = [UIColor blueColor]; 92 | [alertControl setPushView:view2]; 93 | 94 | }]; 95 | 96 | }]; 97 | view1.frame = CGRectMake(0, 0, screenSize.width, 150); 98 | view1.backgroundColor = [UIColor redColor]; 99 | 100 | [WPAlertControl alertForView:view1 begin:WPAlertBeginBottem end:WPAlertEndBottem animateType:WPAlertAnimateDefault constant:-1 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:NO rootControl:self maskClick:nil animateStatus:nil]; 101 | } 102 | 103 | - (void)centerAlert 104 | { 105 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 106 | 107 | [WPAlertControl alertHiddenForRootControl:self completion:^(WPAlertShowStatus status, WPAlertControl *alertControl) { 108 | 109 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 110 | [WPAlertControl alertHiddenForRootControl:self completion:nil]; 111 | }]; 112 | view2.frame = CGRectMake(0, 0, 200,200 ); 113 | view2.backgroundColor = [UIColor blueColor]; 114 | [alertControl setPushView:view2]; 115 | 116 | }]; 117 | 118 | }]; 119 | view1.frame = CGRectMake(0, 0, 150, 150); 120 | view1.backgroundColor = [UIColor redColor]; 121 | 122 | [WPAlertControl alertForView:view1 begin:WPAlertBeginCenter end:WPAlertEndCenter animateType:WPAlertAnimateBounce constant:0 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:NO rootControl:self maskClick:nil animateStatus:nil]; 123 | } 124 | 125 | - (void)bottemAlert 126 | { 127 | CGSize screenSize = [UIScreen mainScreen].bounds.size; 128 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 129 | 130 | [WPAlertControl alertHiddenForRootControl:self completion:^(WPAlertShowStatus status, WPAlertControl *alertControl) { 131 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 132 | [WPAlertControl alertHiddenForRootControl:self completion:nil]; 133 | }]; 134 | view2.frame = CGRectMake(0, 0, screenSize.width, 300); 135 | view2.backgroundColor = [UIColor blueColor]; 136 | [alertControl setPushView:view2]; 137 | }]; 138 | }]; 139 | view1.frame = CGRectMake(0, 0, screenSize.width, 150); 140 | view1.backgroundColor = [UIColor redColor]; 141 | 142 | [WPAlertControl alertForView:view1 begin:WPAlertBeginBottem end:WPAlertEndBottem animateType:WPAlertAnimateDefault constant:0 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:YES rootControl:self maskClick:nil animateStatus:nil]; 143 | } 144 | 145 | - (void)rightAlert 146 | { 147 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 148 | 149 | [WPAlertControl alertHiddenForRootControl:self completion:^(WPAlertShowStatus status, WPAlertControl *alertControl) { 150 | 151 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 152 | [WPAlertControl alertHiddenForRootControl:self completion:nil]; 153 | }]; 154 | view2.frame = CGRectMake(0, 0, 150, 150); 155 | view2.backgroundColor = [UIColor blueColor]; 156 | 157 | [alertControl setPushView:view2 begin:WPAlertBeginBottem end:WPAlertEndCenter animateType:WPAlertAnimateDefault pan:NO constant:0]; 158 | }]; 159 | 160 | }]; 161 | view1.frame = CGRectMake(0, 0, 200, 200); 162 | view1.backgroundColor = [UIColor redColor]; 163 | 164 | [WPAlertControl alertForView:view1 begin:WPAlertBeginRight end:WPAlertEndBottem animateType:WPAlertAnimateBounce constant:-1 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:NO rootControl:self maskClick:nil animateStatus:nil]; 165 | } 166 | 167 | - (void)leftAlert 168 | { 169 | 170 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 171 | 172 | [WPAlertControl alertHiddenForRootControl:self completion:^(WPAlertShowStatus status, WPAlertControl *alertControl) { 173 | 174 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 175 | [WPAlertControl alertHiddenForRootControl:self completion:nil]; 176 | }]; 177 | view2.frame = CGRectMake(0, 0, 150, 150); 178 | view2.backgroundColor = [UIColor blueColor]; 179 | [alertControl setPushView:view2]; 180 | }]; 181 | 182 | }]; 183 | view1.frame = CGRectMake(0, 0, 200, 200); 184 | view1.backgroundColor = [UIColor redColor]; 185 | 186 | [WPAlertControl alertForView:view1 begin:WPAlertBeginLeft end:WPAlertEndRight animateType:WPAlertAnimateBounce constant:-1 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:NO rootControl:self maskClick:nil animateStatus:nil]; 187 | } 188 | 189 | - (void)topAlert 190 | { 191 | CGSize screenSize = [UIScreen mainScreen].bounds.size; 192 | WPView *view1 = [WPView viewWithTapClick:^(id other) { 193 | 194 | [WPAlertControl alertHiddenForRootControl:self completion:^(WPAlertShowStatus status, WPAlertControl *alertControl) { 195 | 196 | WPAlertItem *item1 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 197 | cell.textLabel.text = @"男"; 198 | cell.detailTextLabel.text = @"子标题"; 199 | cell.detailTextLabel.textColor = [UIColor redColor]; 200 | }]; 201 | 202 | WPAlertItem *item2 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 203 | cell.textLabel.text = @"女"; 204 | cell.detailTextLabel.text = @"子标题"; 205 | }]; 206 | WPAlertGroup *group = [WPAlertGroup groupForTitle:@"请问您性别?" items:@[item1,item2]]; 207 | 208 | [alertControl setPushItems:@[group] pushItemsClick:^NSArray *(NSInteger index, NSUInteger alertLevel, WPAlertControl *alertControl) { 209 | 210 | WPView *view2 = [WPView viewWithTapClick:^(id other) { 211 | [WPAlertControl alertHiddenForRootControl:self completion:nil]; 212 | }]; 213 | view2.frame = CGRectMake(0, 0, screenSize.width*0.5, 150); 214 | view2.backgroundColor = [UIColor blueColor]; 215 | 216 | [alertControl setPushView:view2 begin:WPAlertBeginCenter end:WPAlertEndCenter animateType:WPAlertAnimateBounce pan:YES constant:0]; 217 | 218 | return nil; 219 | }]; 220 | 221 | }]; 222 | 223 | }]; 224 | view1.frame = CGRectMake(0, 0, screenSize.width, 200); 225 | view1.backgroundColor = [UIColor redColor]; 226 | 227 | [WPAlertControl alertForView:view1 begin:WPAlertBeginTop end:WPAlertEndTop animateType:WPAlertAnimateDefault constant:0 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:NO rootControl:self maskClick:nil animateStatus:nil]; 228 | } 229 | 230 | - (void)itemsAlert 231 | { 232 | WPAlertItem *item1 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 233 | cell.textLabel.text = @"男"; 234 | cell.detailTextLabel.text = @"子标题"; 235 | cell.detailTextLabel.textColor = [UIColor redColor]; 236 | }]; 237 | 238 | WPAlertItem *item2 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 239 | cell.textLabel.text = @"女"; 240 | cell.detailTextLabel.text = @"子标题"; 241 | }]; 242 | WPAlertGroup *group = [WPAlertGroup groupForTitle:@"请问您性别?" items:@[item1,item2]]; 243 | 244 | [WPAlertControl alertForItems:@[group] index:^NSArray *(NSInteger index, NSUInteger alertLevel, WPAlertControl *alertControl) { 245 | return [self groupsForAlertLeve:alertLevel index:index]; 246 | } begin:WPAlertBeginBottem end:WPAlertEndBottem animateType:WPAlertAnimateDefault constant:0 animageBeginInterval:0.3 animageEndInterval:0.3 maskColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3] pan:NO rootControl:self maskClick:nil animateStatus:nil]; 247 | 248 | } 249 | 250 | - (NSArray *)groupsForAlertLeve:(NSUInteger)level index:(NSUInteger)index 251 | { 252 | 253 | if (level == 1) { // 第一次弹框 254 | if (index == 0) { // 选择了男 255 | WPAlertItem *i0 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 256 | cell.textLabel.text = @"撸代码"; 257 | }]; 258 | WPAlertItem *i1 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 259 | cell.textLabel.text = @"睡觉"; 260 | }]; 261 | WPAlertItem *i2 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 262 | cell.textLabel.text = @"打游戏"; 263 | }]; 264 | WPAlertGroup *g = [WPAlertGroup group:@[i0,i1,i2]]; 265 | g.groupView.text = @"请问您喜欢什么?"; 266 | return @[g]; 267 | 268 | }else if (index==1){ // 选择了女 269 | WPAlertItem *i0 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 270 | cell.textLabel.text = @"买衣服"; 271 | }]; 272 | 273 | WPAlertItem *i1 = [WPAlertItem itemSettingCell:^(WPAlertControlCell *cell) { 274 | cell.textLabel.text = @"吃喝"; 275 | cell.detailTextLabel.text = @"子标题"; 276 | }]; 277 | 278 | WPAlertGroup *g = [WPAlertGroup group:@[i0,i1]]; 279 | g.groupView.text = @"请问您喜欢什么?"; 280 | return @[g]; 281 | } 282 | }else if (level == 2){ // 第二次弹框 283 | 284 | WPAlertItem *item = [WPAlertItem item:@"弹框"]; 285 | 286 | WPAlertGroup *g = [WPAlertGroup group:@[item]]; 287 | g.groupView.text = @"多组弹框"; 288 | g.groupView.textColor = [UIColor blueColor]; 289 | WPAlertGroup *g1 = [WPAlertGroup group:@[item,item]]; 290 | g1.groupView.text = @"支持多层级弹框"; 291 | g1.groupView.textColor = [UIColor redColor]; 292 | return @[g,g1]; 293 | } 294 | 295 | return nil; 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/WPAlertControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // WPAlertControl.h 3 | // Rider 4 | // 5 | // Created by Developer on 16/3/22. 6 | // Copyright © 2016年 Developer. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // 隐藏弹框 12 | #define WPAlertHidden(target) [WPAlertControl alertHiddenForRootControl:(target) completion:nil] 13 | 14 | /** 开始枚举类型 */ 15 | typedef NS_ENUM(NSUInteger, WPAlertBeginType){ 16 | WPAlertBeginLeft, 17 | WPAlertBeginRight, 18 | WPAlertBeginTop, 19 | WPAlertBeginBottem, 20 | WPAlertBeginCenter, // 中心弹出类型动画 21 | } ; 22 | 23 | /** 结束枚举类型 */ 24 | typedef NS_ENUM(NSUInteger, WPAlertEndType){ 25 | WPAlertEndLeft, 26 | WPAlertEndRight, 27 | WPAlertEndTop, 28 | WPAlertEndBottem, 29 | WPAlertEndCenter, 30 | }; 31 | 32 | /** 蒙版显示状态 */ 33 | typedef NS_ENUM(NSUInteger, WPAlertShowStatus){ 34 | WPAnimateWillAppear, // 即将显示 35 | WPAnimateDidAppear, // 显示完成 36 | WPAnimateWillDisappear,// 即将消失 37 | WPAnimateDidDisappear, // 消失完成 38 | }; 39 | 40 | /** 动画类型 */ 41 | typedef NS_ENUM(NSUInteger, WPAlertAnimateType){ 42 | WPAlertAnimateDefault, // 默认 43 | WPAlertAnimateBounce, // 弹跳动画 44 | }; 45 | 46 | @class WPAlertControl,WPAlertItem,WPAlertGroup,WPAlertControlCell; 47 | typedef BOOL(^MaskClickBlock)(NSInteger index,NSUInteger alertLevel,WPAlertControl *alertControl); 48 | typedef void(^AlertAnimateStatus)(WPAlertShowStatus status,WPAlertControl *alertControl); 49 | typedef NSArray * (^ItemClick)(NSInteger index,NSUInteger alertLevel,WPAlertControl *alertControl); 50 | typedef void(^setttingControlCell)(WPAlertControlCell *cell); 51 | 52 | #define alertTimeBeginInterval 0.3 53 | #define alertTimeEndInterval 0.4 54 | #define alertDefaultMaskColor [UIColor colorWithRed:0 green:0 blue:0 alpha:0.2] 55 | 56 | @interface WPAlertControl : UIViewController 57 | 58 | /** 创建一个弹框 59 | * animateView 动画视图 animateView的size必须有值 60 | * begin 视图开始弹出的类型 61 | * endType 动画结束弹出的类型 62 | * constant 常量 默认0 -1==居中 动画结束时候的frame+上常量 可以微调动画结束后的frame 63 | * beginInterval 视图弹出的持续时间 64 | * endInterval 视图结束弹出的时间 65 | * masColor 蒙版的颜色 66 | * pan 是否支持拖动隐藏 67 | * rootControl alert弹出试图的根控制器 68 | * masClick 蒙版点击执行 return YES 蒙版不会消失 NO蒙版消失 默认YES 69 | * animateStatus alert弹框的当前状态 即将显示 -> 显示完成 -> 即将消失 -> 消失完成 70 | * alertLevel 当前动画的等级 默认为1 设置了pushAnimateView后会累加 71 | * animateType 动画类型 72 | */ 73 | + (instancetype)alertForView:(UIView *)animateView begin:(WPAlertBeginType)type end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType constant:(CGFloat)constant animageBeginInterval:(CGFloat)beginInterval animageEndInterval:(CGFloat)endInterval maskColor:(UIColor *)color pan:(BOOL)pan rootControl:(UIViewController *)rootControl maskClick:(MaskClickBlock)click animateStatus:(AlertAnimateStatus)animateStatus; 74 | 75 | /** 创建一个item选择弹框 76 | * items 菜单内容 77 | * index item 点击的索引 78 | * constant 常量 默认0 -1==居中 动画结束时候的frame+上常量 可以微调动画结束后的frame 当begin==end的时候有效 79 | * beginInterval 视图弹出的持续时间 80 | * endInterval 视图结束弹出的时间 81 | * masColor 蒙版的颜色 82 | * pan 是否支持拖动隐藏 83 | * rootControl alert弹出试图的根控制器 84 | * masClick 蒙版点击执行 return NO蒙版不会消失 YES蒙版消失 默认YES 85 | * animateStatus alert弹框的当前状态 即将显示 -> 显示完成 -> 即将消失 -> 消失完成 86 | * alertLevel 当前动画的等级 默认为1 设置了pushAnimateView后会累加 87 | */ 88 | + (instancetype)alertForItems:(NSArray *)items index:(ItemClick)index begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType constant:(CGFloat)constant animageBeginInterval:(CGFloat)beginInterval animageEndInterval:(CGFloat)endInterval maskColor:(UIColor *)color pan:(BOOL)pan rootControl:(UIViewController *)rootControl maskClick:(MaskClickBlock)click animateStatus:(AlertAnimateStatus)animateStatus; 89 | 90 | /** 弹框消失 */ 91 | + (void)alertHiddenForRootControl:(UIViewController *)control completion:(AlertAnimateStatus)completion; 92 | 93 | /** 获得当前的弹框控制器 */ 94 | + (instancetype)currentAlertControFor:(UIViewController *)rootControl; 95 | 96 | /** 设置下个Items */ 97 | - (void)setPushItems:(NSArray *)items pushItemsClick:(ItemClick)click; 98 | 99 | /** 设置下个视图 */ 100 | - (void)setPushView:(UIView *)pushView; 101 | 102 | /** 设置下个视图 */ 103 | - (void)setPushView:(UIView *)pushView begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType; 104 | 105 | /** 设置下个视图 */ 106 | - (void)setPushView:(UIView *)pushView begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType pan:(BOOL)pan constant:(CGFloat)constant; 107 | 108 | /** 设置下个视图 */ 109 | - (void)setPushView:(UIView *)pushView begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType pan:(BOOL)pan constant:(CGFloat)constant animageBeginInterval:(CGFloat)beginInterval animageEndInterval:(CGFloat)endInterval; 110 | 111 | 112 | @end 113 | 114 | /** 扩展创建方法 */ 115 | @interface WPAlertControl (WPExtension) 116 | /** 创建一个items弹框 items 可以是 @[@"string",@"string"] 也可以是二维数组 @[@[@"string",@"string"],@[@"string",@"string"]]*/ 117 | + (instancetype)alertItemsForRootControl:(UIViewController *)rootControl animateType:(WPAlertAnimateType)animateType items:(NSArray *)items index:(ItemClick)index; 118 | @end 119 | 120 | @interface WPAlertGroup : NSObject 121 | + (instancetype)group:(NSArray*)items; 122 | + (instancetype)groupForTitle:(NSString *)title items:(NSArray*)items; 123 | @property (nonatomic,strong) NSArray *items; 124 | @property (nonatomic,strong) UILabel *groupView; 125 | @property (nonatomic,assign) CGFloat groupHeight; 126 | @end 127 | 128 | @interface WPAlertItem : NSObject 129 | @property (nonatomic,assign) CGFloat cellHeight; 130 | 131 | + (instancetype)itemSettingCell:(setttingControlCell)cellBlock; 132 | + (instancetype)item:(NSString *)title; 133 | 134 | @property (nonatomic,copy) NSString *title; 135 | @property (nonatomic,assign) UITableViewCellSelectionStyle style; 136 | 137 | @property (nonatomic,copy) setttingControlCell settingCell; 138 | 139 | @end 140 | 141 | @interface WPAlertControlCell : UITableViewCell 142 | @property (nonatomic,strong) WPAlertItem *item; 143 | @end 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/WPAlertControl.m: -------------------------------------------------------------------------------- 1 | #import "WPAlertControl.h" 2 | 3 | #define WPRGB(r, g, b) [UIColor colorWithRed:(r) / 255.f green:(g) / 255.f blue:(b) / 255.f alpha:1.f] 4 | #define WPFont28 [UIFont systemFontOfSize:14] 5 | #define iphoneXPadding 20 6 | #define groupNormalHeight 6.0 7 | #define kDevice_Is_control_iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) 8 | 9 | @interface WPAlertControl () ; 10 | /** 是否已经显示 */ 11 | @property (nonatomic,assign) BOOL isShow; 12 | /** 蒙板按钮 */ 13 | @property (nonatomic,weak) UIButton *mask; 14 | /** 动画视图 */ 15 | @property (nonatomic,weak) UIView *animateView; 16 | /** 动画类型 */ 17 | @property (nonatomic,assign) WPAlertBeginType beginType; 18 | /** 结束动画类型 */ 19 | @property (nonatomic,assign) WPAlertEndType endType; 20 | /** 结束开始点 */ 21 | @property (nonatomic,assign) CGPoint beginPoint; 22 | /** 动画结束开始点 */ 23 | @property (nonatomic,assign) CGPoint endPoint; 24 | /** 常量 -1 == 居中*/ 25 | @property (nonatomic,assign) CGFloat constant; 26 | /** 结束动画以后的frame */ 27 | @property (nonatomic,assign) CGRect endFrame; 28 | /** 结束动画以后的不动的frame */ 29 | @property (nonatomic,assign) CGRect endConstantFrame; 30 | /** 显示弹框的状态block */ 31 | @property (nonatomic,copy) AlertAnimateStatus animateStatus; 32 | /** 弹框隐藏的时候调用 */ 33 | @property (nonatomic,copy) AlertAnimateStatus complete; 34 | /** 蒙板点击调用 */ 35 | @property (nonatomic,copy) MaskClickBlock maskClick; 36 | /** 动画类型 */ 37 | @property (nonatomic,assign) WPAlertAnimateType animateType; 38 | /** push结束动画 中间变量*/ 39 | @property (nonatomic,assign) WPAlertEndType pushEndType; 40 | /** item模式数组 */ 41 | @property (nonatomic,strong) NSArray *items; 42 | /** item模式数组 */ 43 | @property (nonatomic,strong) NSArray *pushItems; 44 | /** item点击掉用 */ 45 | @property (nonatomic,copy) ItemClick itemBlock; 46 | /** 菜单等级 */ 47 | @property (nonatomic,assign) NSUInteger alertLevel; 48 | /** 蒙版开始显示时的颜色 */ 49 | @property (nonatomic,strong) UIColor *maskBeginColor; 50 | /** 蒙版显示完以后的颜色 */ 51 | @property (nonatomic,strong) UIColor *maskEndColor; 52 | /** 是否需要设置形变 */ 53 | @property (nonatomic,assign) BOOL isTransform; 54 | /** 是否需要拖拽手势 */ 55 | @property (nonatomic,assign) BOOL isPan; 56 | /** 动画开始持续的时间 */ 57 | @property (nonatomic,assign) CGFloat animageBeginInterval; 58 | /** 动画结束持续时间 */ 59 | @property (nonatomic,assign) CGFloat animageEndInterval; 60 | /** 下个动画视图 */ 61 | @property (nonatomic,strong) UIView *pushAnimateView; 62 | @end 63 | 64 | @implementation WPAlertControl (WPExtension) 65 | + (instancetype)alertItemsForRootControl:(UIViewController *)rootControl animateType:(WPAlertAnimateType)animateType items:(NSArray *)items index:(ItemClick)index 66 | { 67 | if (!rootControl) { 68 | rootControl = [UIApplication sharedApplication].keyWindow.rootViewController; 69 | } 70 | 71 | NSMutableArray *groups = [NSMutableArray array]; 72 | if (items.count) { 73 | NSObject *obj = items.lastObject; 74 | if ([obj isKindOfClass:[NSString class]]) { 75 | NSMutableArray *itemsG = [NSMutableArray array]; 76 | 77 | for (NSString *string in items) { 78 | [itemsG addObject:[WPAlertItem item:string]]; 79 | } 80 | 81 | WPAlertGroup *g0 = [WPAlertGroup group:itemsG]; 82 | [groups addObject:g0]; 83 | 84 | }else if ([obj isKindOfClass:[NSArray class]]){ 85 | 86 | for (NSArray *array in items) { 87 | NSMutableArray *itemsG = [NSMutableArray array]; 88 | for (NSString *string in array) { 89 | [itemsG addObject:[WPAlertItem item:string]]; 90 | } 91 | [groups addObject:[WPAlertGroup group:itemsG]]; 92 | } 93 | } 94 | } 95 | 96 | return [self alertForItems:groups index:index begin:WPAlertBeginBottem end:WPAlertEndBottem animateType:animateType constant:0 animageBeginInterval:alertTimeBeginInterval animageEndInterval:alertTimeEndInterval maskColor:nil pan:YES rootControl:rootControl maskClick:nil animateStatus:nil]; 97 | } 98 | @end 99 | 100 | @implementation WPAlertControl 101 | 102 | + (instancetype)alertForView:(UIView *)inputView begin:(WPAlertBeginType)type end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType constant:(CGFloat)constant animageBeginInterval:(CGFloat)beginInterval animageEndInterval:(CGFloat)endInterval maskColor:(UIColor *)maskColor pan:(BOOL)pan rootControl:(UIViewController *)rootControl maskClick:(MaskClickBlock)click animateStatus:(AlertAnimateStatus)animateStatus 103 | { 104 | WPAlertControl *controller = [WPAlertControl new]; 105 | controller.animageBeginInterval = beginInterval; 106 | controller.animageEndInterval = endInterval; 107 | controller.maskEndColor = maskColor; 108 | controller.isPan = pan; 109 | controller.beginType = type; 110 | controller.endType = endType; 111 | controller.constant = constant; 112 | controller.maskClick = click; 113 | controller.animateStatus = animateStatus; 114 | controller.animateView = inputView; 115 | controller.animateType = animateType; 116 | controller.view.frame = rootControl.view.bounds; 117 | [rootControl presentViewController:controller animated:NO completion:nil]; 118 | return controller; 119 | } 120 | 121 | + (instancetype)alertForItems:(NSArray *)items index:(ItemClick)index begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType constant:(CGFloat)constant animageBeginInterval:(CGFloat)beginInterval animageEndInterval:(CGFloat)endInterval maskColor:(UIColor *)maskColor pan:(BOOL)pan rootControl:(UIViewController *)rootControl maskClick:(MaskClickBlock)click animateStatus:(AlertAnimateStatus)animateStatus 122 | { 123 | WPAlertControl *control = [WPAlertControl new]; 124 | control.animageBeginInterval = beginInterval; 125 | control.animageEndInterval = endInterval; 126 | control.maskEndColor = maskColor; 127 | control.isPan = pan; 128 | control.beginType = beginType; 129 | control.endType = endType; 130 | control.items = items; 131 | control.itemBlock = index; 132 | control.animateStatus = animateStatus; 133 | control.maskClick = click; 134 | control.constant = constant; 135 | control.animateType = animateType; 136 | control.view.frame = rootControl.view.bounds; 137 | [rootControl presentViewController:control animated:NO completion:nil]; 138 | return control; 139 | } 140 | 141 | + (void)alertHiddenForRootControl:(UIViewController *)control completion:(AlertAnimateStatus)completion 142 | { 143 | UIViewController *aerltControl = control.presentedViewController; 144 | 145 | if ([aerltControl.class isSubclassOfClass:[WPAlertControl class]] ) { 146 | WPAlertControl *alert = (WPAlertControl *)aerltControl; 147 | alert.pushAnimateView = nil; 148 | alert.pushItems = nil; 149 | alert.complete = completion; 150 | [alert animateForShow:NO]; 151 | } 152 | } 153 | 154 | + (instancetype)currentAlertControFor:(UIViewController *)rootControl 155 | { 156 | return (WPAlertControl *)rootControl.presentedViewController; 157 | } 158 | 159 | #pragma mark UITableViewDataSource 160 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 161 | { 162 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 163 | 164 | if (self.items[indexPath.section].items[indexPath.row].style == UITableViewCellSelectionStyleNone)return; 165 | 166 | NSInteger index = 0; 167 | 168 | if (indexPath.section) { 169 | for (int i = 0; i 0) { 272 | return _animageBeginInterval; 273 | }else{ 274 | return 0; 275 | } 276 | } 277 | 278 | - (CGFloat)animageEndInterval{ 279 | if (_animageEndInterval > 0) { 280 | return _animageEndInterval; 281 | }else{ 282 | return 0; 283 | } 284 | } 285 | 286 | /** 蒙版点击 */ 287 | - (void)maskTouch:(UIButton *)mask 288 | { 289 | self.pushAnimateView = nil; 290 | self.pushItems = nil; 291 | 292 | if (self.maskClick) { 293 | 294 | BOOL isMask = self.maskClick(-1,self.alertLevel ,self); 295 | if (isMask) { 296 | if(self.isShow) return; 297 | [self beginAnimateIsImplementBlock:YES]; 298 | }else{ 299 | [self endAnimate]; 300 | } 301 | }else{ 302 | 303 | [self endAnimate]; 304 | } 305 | } 306 | 307 | - (void)beginAnimateIsImplementBlock:(BOOL)isImplement 308 | { 309 | self.alertLevel++; 310 | 311 | if (self.animateType == WPAlertAnimateDefault) { 312 | [self animateDefaultBeginIsImplementBlock:isImplement]; 313 | 314 | }else if (self.animateType == WPAlertAnimateBounce){ 315 | [self animateBounceBeginIsImplementBlock:isImplement]; 316 | } 317 | } 318 | 319 | - (void)endAnimate 320 | { 321 | if (self.animateType == WPAlertAnimateDefault) { 322 | [self animateDefaultEnd]; 323 | 324 | }else if(self.animateType == WPAlertAnimateBounce){ 325 | [self animateBounceEnd]; 326 | } 327 | } 328 | 329 | /** 开始动画 */ 330 | - (void)animateForShow:(BOOL)show 331 | { 332 | if (show) { 333 | 334 | // 已经显示就返回 335 | if (self.isShow) return; 336 | 337 | if (self.animateStatus) { 338 | self.animateStatus(WPAnimateWillAppear,self); 339 | } 340 | 341 | if (!self.isShow) { 342 | self.mask.userInteractionEnabled = NO; 343 | [self beginAnimateIsImplementBlock:YES]; 344 | } 345 | }else{ 346 | // 设置显示状态 347 | if (self.animateStatus) { 348 | self.animateStatus(WPAnimateWillDisappear,self); 349 | } 350 | 351 | // 即将结束调用 352 | if (self.complete) { 353 | self.complete(WPAnimateWillDisappear,self); 354 | } 355 | 356 | self.mask.userInteractionEnabled = YES; 357 | 358 | [self endAnimate]; 359 | } 360 | } 361 | 362 | /** 默认开始动画 */ 363 | - (void)animateDefaultBeginIsImplementBlock:(BOOL)isImplement 364 | { 365 | 366 | [UIView animateWithDuration:self.animageBeginInterval animations:^{ 367 | if (self.beginType == WPAlertEndCenter) { 368 | self.animateView.transform = CGAffineTransformIdentity; 369 | self.animateView.alpha = 1; 370 | }else{ 371 | // self.animateView.origin = self.beginPoint; 372 | self.animateView.frame = CGRectMake(self.beginPoint.x, self.beginPoint.y, self.animateView.frame.size.width, self.animateView.frame.size.height); 373 | } 374 | self.mask.backgroundColor = self.maskEndColor; 375 | } completion:^(BOOL finished) { 376 | self.endFrame = self.animateView.frame; 377 | self.endConstantFrame = self.animateView.frame; 378 | self.isShow = YES; 379 | self.mask.userInteractionEnabled = YES; 380 | if (self.animateStatus && self.isShow) { 381 | if (isImplement) { 382 | self.animateStatus(WPAnimateDidAppear,self); 383 | } 384 | } 385 | self.pushAnimateView = nil; 386 | }]; 387 | } 388 | 389 | /** 默认结束动画 */ 390 | - (void)animateDefaultEnd 391 | { 392 | [self animateBounceEnd]; 393 | } 394 | 395 | /** 弹跳开始动画 */ 396 | - (void)animateBounceBeginIsImplementBlock:(BOOL)isImplement 397 | { 398 | if (self.isTransform) { 399 | self.animateView.transform = CGAffineTransformMakeScale(0.2, 0.2); 400 | }else{ 401 | 402 | } 403 | 404 | [UIView animateWithDuration:self.animageBeginInterval delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:UIViewAnimationOptionCurveLinear animations:^{ 405 | 406 | if (self.beginType == WPAlertEndCenter) { 407 | self.animateView.transform = CGAffineTransformIdentity; 408 | self.animateView.alpha = 1; 409 | }else{ 410 | // self.animateView.origin = self.beginPoint; 411 | self.animateView.frame = CGRectMake(self.beginPoint.x, self.beginPoint.y, self.animateView.frame.size.width, self.animateView.frame.size.height); 412 | } 413 | self.mask.backgroundColor = self.maskEndColor; 414 | 415 | } completion:^(BOOL finished) { 416 | self.endFrame = self.animateView.frame; 417 | self.endConstantFrame = self.animateView.frame; 418 | self.isShow = YES; 419 | self.mask.userInteractionEnabled = YES; 420 | if (self.animateStatus && self.isShow) { 421 | if (isImplement) { 422 | self.animateStatus(WPAnimateDidAppear,self); 423 | } 424 | } 425 | self.pushAnimateView = nil; 426 | }]; 427 | } 428 | 429 | /** 弹跳结束动画 */ 430 | - (void)animateBounceEnd 431 | { 432 | [UIView animateWithDuration:self.animageEndInterval animations:^{ 433 | if (self.endType == WPAlertEndCenter) { 434 | self.animateView.transform = CGAffineTransformMakeScale(0.01f, 0.01f); 435 | self.animateView.alpha = 0; 436 | }else{ 437 | self.animateView.frame = CGRectMake(self.endPoint.x, self.endPoint.y, self.animateView.frame.size.width, self.animateView.frame.size.height); 438 | } 439 | 440 | if (!self.pushAnimateView && !self.pushItems.count) { // 当push动画视图没有的时候才改变颜色 441 | self.mask.backgroundColor = self.maskBeginColor; 442 | } 443 | } completion:^(BOOL finished) { 444 | self.mask.userInteractionEnabled = NO; 445 | [self.animateView removeFromSuperview]; 446 | self.endType = self.pushEndType; 447 | if (self.pushAnimateView) { 448 | self.animateView = self.pushAnimateView; 449 | 450 | // 选择动画类型 重新开启动画 451 | [self beginAnimateIsImplementBlock:YES]; 452 | 453 | }else if (self.pushItems.count){ 454 | 455 | self.items = self.pushItems; 456 | 457 | // 选择动画类型 重新开启动画 458 | [self beginAnimateIsImplementBlock:YES]; 459 | 460 | }else{ 461 | 462 | if (self.animateStatus) { 463 | self.animateStatus(WPAnimateDidDisappear,self); 464 | } 465 | 466 | if (self.complete) { 467 | self.complete(WPAnimateDidDisappear,self); 468 | } 469 | [self dismissViewControllerAnimated:NO completion:nil]; 470 | } 471 | }]; 472 | } 473 | 474 | - (void)setPushView:(UIView *)pushView 475 | { 476 | self.pushAnimateView = pushView; 477 | } 478 | 479 | - (void)setPushView:(UIView *)pushView begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType 480 | { 481 | self.beginType = beginType; 482 | self.pushEndType = endType; 483 | self.animateType = animateType; 484 | self.pushAnimateView = pushView; 485 | } 486 | 487 | - (void)setPushView:(UIView *)pushView begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType pan:(BOOL)pan constant:(CGFloat)constant 488 | { 489 | self.constant = constant; 490 | self.isPan = pan; 491 | [self setPushView:pushView begin:beginType end:endType animateType:animateType]; 492 | } 493 | 494 | - (void)setPushView:(UIView *)pushView begin:(WPAlertBeginType)beginType end:(WPAlertEndType)endType animateType:(WPAlertAnimateType)animateType pan:(BOOL)pan constant:(CGFloat)constant animageBeginInterval:(CGFloat)beginInterval animageEndInterval:(CGFloat)endInterval 495 | { 496 | self.animageBeginInterval = beginInterval; 497 | self.animageEndInterval = endInterval; 498 | [self setPushView:pushView begin:beginType end:endType animateType:animateType pan:pan constant:constant]; 499 | } 500 | 501 | - (void)setAnimateView:(UIView *)animateView 502 | { 503 | _animateView = animateView; 504 | 505 | [self.view addSubview:animateView]; 506 | 507 | CGFloat w = animateView.frame.size.width; 508 | CGFloat h = animateView.frame.size.height; 509 | 510 | CGFloat maxW = [UIApplication sharedApplication].windows.lastObject.frame.size.width; 511 | CGFloat maxH = [UIApplication sharedApplication].windows.lastObject.frame.size.height; 512 | CGFloat constant = self.constant; 513 | 514 | if (constant == -1) { 515 | if (self.beginType == WPAlertBeginLeft || self.beginType == WPAlertBeginRight) { 516 | if (self.beginType == WPAlertBeginLeft) { 517 | constant = (maxW-w) * 0.5; 518 | }else{ 519 | constant = - (maxW-w) * 0.5; 520 | } 521 | }else if (self.beginType == WPAlertBeginTop || self.beginType == WPAlertBeginBottem){ 522 | if (self.beginType == WPAlertBeginTop) { 523 | constant = (maxH -h) * 0.5; 524 | }else{ 525 | constant = - (maxH -h) * 0.5; 526 | } 527 | } 528 | } 529 | 530 | // 开始动画计算 531 | if (self.beginType == WPAlertBeginLeft) { // 左边动画 532 | animateView.frame = CGRectMake(-animateView.frame.size.width, (maxH-h) * 0.5, animateView.frame.size.width, animateView.frame.size.height); 533 | self.beginPoint = CGPointMake(0+constant, animateView.frame.origin.y); 534 | 535 | } else if (self.beginType == WPAlertBeginRight){ // 右边动画 536 | animateView.frame = CGRectMake(maxW, (maxH-h)*0.5, animateView.frame.size.width, animateView.frame.size.height); 537 | self.beginPoint = CGPointMake(maxW-w+constant, animateView.frame.origin.y); 538 | 539 | } else if (self.beginType == WPAlertBeginTop){ // 上动画 540 | animateView.frame = CGRectMake((maxW-w)*0.5, -h, animateView.frame.size.width, animateView.frame.size.height); 541 | self.beginPoint = CGPointMake(animateView.frame.origin.x, 0+constant); 542 | 543 | } else if (self.beginType == WPAlertBeginBottem){ // 底部动画 544 | animateView.frame = CGRectMake((maxW-w) * 0.5, maxH, animateView.frame.size.width, animateView.frame.size.height); 545 | self.beginPoint = CGPointMake(animateView.frame.origin.x,maxH-h+constant); 546 | 547 | } else if (self.beginType == WPAlertBeginCenter){ // 中心动画 548 | self.beginPoint = CGPointMake((maxW-animateView.frame.size.width) * 0.5, (maxH-animateView.frame.size.height) * 0.5); 549 | animateView.frame = CGRectMake(self.beginPoint.x, self.beginPoint.y, animateView.frame.size.width, animateView.frame.size.height); 550 | animateView.alpha = 0; 551 | animateView.layer.masksToBounds = NO; 552 | animateView.layer.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4].CGColor; 553 | animateView.layer.shadowRadius = 20; 554 | animateView.layer.shadowOpacity = 1; 555 | animateView.layer.shadowOffset = CGSizeMake(0, 10); 556 | self.isTransform = YES; 557 | } 558 | 559 | // 结束动画计算 560 | if (self.endType == WPAlertEndLeft) { 561 | self.endPoint = CGPointMake(-h, self.beginPoint.y); 562 | } else if (self.endType == WPAlertEndRight){ 563 | self.endPoint = CGPointMake(maxW, self.beginPoint.y); 564 | } else if (self.endType == WPAlertEndTop){ 565 | self.endPoint = CGPointMake(self.beginPoint.x, -h); 566 | } else if (self.endType == WPAlertEndBottem){ 567 | self.endPoint = CGPointMake(self.beginPoint.x, maxH); 568 | }else if (self.endType == WPAlertEndCenter){ 569 | self.endPoint = self.view.center; 570 | } 571 | 572 | if (self.isPan) { 573 | // 添加手势 574 | UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGRAct:)]; 575 | [animateView addGestureRecognizer:panGR]; 576 | 577 | } 578 | } 579 | 580 | - (void)setItems:(NSArray *)items 581 | { 582 | _items = items; 583 | 584 | UITableView *tableView = [UITableView new]; 585 | tableView.separatorInset = UIEdgeInsetsZero; 586 | tableView.backgroundColor = [UIColor clearColor]; 587 | tableView.tableFooterView = [UIView new]; 588 | tableView.showsVerticalScrollIndicator = NO; 589 | 590 | UIView *footView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 100)]; 591 | footView.backgroundColor = [UIColor whiteColor]; 592 | tableView.tableFooterView = footView; 593 | 594 | for (WPAlertGroup *group in items) { 595 | 596 | if(group.groupHeight == groupNormalHeight){ 597 | if(group.groupView.text.length){ 598 | group.groupHeight = 20.0; 599 | } 600 | } 601 | } 602 | 603 | if(items.firstObject.groupView.text.length){ 604 | items.firstObject.groupHeight = 20; 605 | }else if(items.firstObject.groupHeight == groupNormalHeight){ 606 | items.firstObject.groupHeight = 0; 607 | } 608 | 609 | // 计算高度 610 | CGFloat h = 0; 611 | for (int a = 0; a *)items pushItemsClick:(ItemClick)click 636 | { 637 | self.beginType = WPAlertBeginBottem; 638 | self.pushEndType = WPAlertEndBottem; 639 | self.isPan = NO; 640 | self.pushItems = items; 641 | self.itemBlock = click; 642 | } 643 | 644 | - (void)setPushItems:(NSArray *)pushItems 645 | { 646 | NSMutableArray *groups = [NSMutableArray array]; 647 | NSObject *obj = pushItems.lastObject; 648 | if ([obj isKindOfClass:[NSString class]]) { 649 | NSMutableArray *itemsG = [NSMutableArray array]; 650 | 651 | for (NSString *string in pushItems) { 652 | [itemsG addObject:[WPAlertItem item:string]]; 653 | } 654 | 655 | WPAlertGroup *g0 = [WPAlertGroup group:itemsG]; 656 | [groups addObject:g0]; 657 | 658 | }else if ([obj isKindOfClass:[NSArray class]]){ 659 | 660 | for (NSArray *array in pushItems) { 661 | NSMutableArray *itemsG = [NSMutableArray array]; 662 | for (NSString *string in array) { 663 | [itemsG addObject:[WPAlertItem item:string]]; 664 | } 665 | [groups addObject:[WPAlertGroup group:itemsG]]; 666 | } 667 | }else{ 668 | groups = [NSMutableArray arrayWithArray:pushItems]; 669 | } 670 | 671 | BOOL isEqual = NO; 672 | 673 | // 检测是否是相同的item 674 | if (groups.count == self.items.count) { 675 | 676 | for (int i = 0; i=0) return; 713 | // 调整位置 714 | self.animateView.frame = CGRectMake(self.endFrame.origin.x + point.x, self.endFrame.origin.y, self.animateView.frame.size.width, self.animateView.frame.size.height); 715 | 716 | }else if (self.endType == WPAlertEndRight && self.beginType == WPAlertBeginRight){ 717 | if (point.x<=0) return; 718 | // 调整位置 719 | self.animateView.frame = CGRectMake(self.endFrame.origin.x + point.x,self.endFrame.origin.y , self.animateView.frame.size.width, self.animateView.frame.size.height); 720 | }else if (self.endType == WPAlertEndTop && self.beginType == WPAlertBeginTop){ // 从上面弹出来的时候 721 | if (point.y>=0) return; 722 | self.animateView.frame = CGRectMake(self.endConstantFrame.origin.x, self.endFrame.origin.y+point.y, self.endConstantFrame.size.width, self.endConstantFrame.size.height); 723 | }else if (self.endType == WPAlertEndBottem && self.beginType == WPAlertBeginBottem){ 724 | if (point.y<=0) return; 725 | self.animateView.frame = CGRectMake(self.endConstantFrame.origin.x, self.endFrame.origin.y+point.y, self.endConstantFrame.size.width, self.endConstantFrame.size.height); 726 | } 727 | 728 | // 结束拖动以后 729 | if(recongnizer.state == UIGestureRecognizerStateEnded || recongnizer.state == UIGestureRecognizerStateCancelled){ 730 | self.endFrame = self.animateView.frame; 731 | CGFloat pad = 0.5; 732 | CGFloat moveX = 0; // 移动的量 733 | CGFloat moveY = 0; // 移动的量 734 | 735 | if (self.endType == WPAlertEndLeft && self.beginType == WPAlertBeginLeft) { // 左边的动画 736 | moveX = self.endConstantFrame.origin.x - self.endFrame.origin.x; 737 | 738 | // 判断当前在哪个点上 739 | if (moveX < self.endConstantFrame.size.width * pad) { // 复位 740 | [self beginAnimateIsImplementBlock:NO]; 741 | }else{ // 结束弹框 742 | [self endAnimate]; 743 | } 744 | 745 | }else if (self.endType == WPAlertEndRight && self.beginType == WPAlertBeginRight){ // 右边动画 746 | moveX = point.x; 747 | 748 | // 判断当前在哪个点上 749 | if (moveX < self.endConstantFrame.size.width * pad) { // 复位 750 | [self beginAnimateIsImplementBlock:NO]; 751 | }else{ // 结束弹框 752 | 753 | [self endAnimate]; 754 | } 755 | }else if (self.endType == WPAlertEndTop && self.beginType == WPAlertBeginTop){ 756 | moveY = CGRectGetMaxY(self.endConstantFrame) + point.y; 757 | 758 | // 判断当前在哪个点上 759 | if (moveY > CGRectGetMaxY(self.endConstantFrame) * pad) { // 复位 760 | [self beginAnimateIsImplementBlock:NO]; 761 | }else{ // 结束弹框 762 | [self endAnimate]; 763 | } 764 | }else if (self.endType == WPAlertEndBottem && self.beginType == WPAlertEndBottem){ 765 | moveY = point.y; 766 | 767 | if (moveY < self.endConstantFrame.size.height * pad) { 768 | [self beginAnimateIsImplementBlock:NO]; 769 | }else{ 770 | [self endAnimate]; 771 | } 772 | } 773 | 774 | } 775 | } 776 | 777 | - (void)viewDidLayoutSubviews 778 | { 779 | [super viewDidLayoutSubviews]; 780 | 781 | self.mask.frame = self.view.frame; 782 | } 783 | 784 | @end 785 | 786 | @implementation WPAlertGroup 787 | + (instancetype)group:(NSArray *)items 788 | { 789 | WPAlertGroup *group = [self new]; 790 | group.items = items; 791 | return group; 792 | } 793 | 794 | + (instancetype)groupForTitle:(NSString *)title items:(NSArray *)items 795 | { 796 | WPAlertGroup *group = [self group:items]; 797 | group.groupView.text = title; 798 | return group; 799 | } 800 | 801 | -(instancetype)init 802 | { 803 | if ([super init]) { 804 | UILabel *view = [UILabel new]; 805 | view.textAlignment = NSTextAlignmentCenter; 806 | view.font = [UIFont systemFontOfSize:14]; 807 | view.backgroundColor = WPRGB(238,238,238); 808 | self.groupView = view; 809 | self.groupHeight = groupNormalHeight; 810 | } 811 | return self; 812 | } 813 | 814 | @end 815 | 816 | @implementation WPAlertItem 817 | + (instancetype)item:(NSString *)title 818 | { 819 | WPAlertItem *item = [self new]; 820 | item.title = title; 821 | return item; 822 | } 823 | 824 | + (instancetype)itemSettingCell:(setttingControlCell)cellBlock 825 | { 826 | WPAlertItem *item = [self new]; 827 | item.settingCell = cellBlock; 828 | return item; 829 | } 830 | 831 | - (instancetype)init 832 | { 833 | if ([super init]) { 834 | self.cellHeight = 44.0; 835 | } 836 | return self; 837 | } 838 | 839 | @end 840 | 841 | @implementation WPAlertControlCell 842 | 843 | - (void)setItem:(WPAlertItem *)item 844 | { 845 | _item = item; 846 | 847 | self.textLabel.text = item.title; 848 | !item.settingCell ?: item.settingCell(self); 849 | item.style = self.selectionStyle; 850 | if(self.textLabel.text.length){ 851 | item.title = self.textLabel.text; 852 | } 853 | } 854 | 855 | - (void)layoutSubviews 856 | { 857 | [super layoutSubviews]; 858 | 859 | 860 | self.textLabel.frame = CGRectMake((self.frame.size.width - self.textLabel.frame.size.width) * 0.5, self.textLabel.frame.origin.y, self.textLabel.frame.size.width, self.textLabel.frame.size.height); 861 | self.detailTextLabel.frame = CGRectMake((self.frame.size.width - self.detailTextLabel.frame.size.width) * 0.5, self.detailTextLabel.frame.origin.y, self.detailTextLabel.frame.size.width, self.detailTextLabel.frame.size.height); 862 | } 863 | @end 864 | 865 | 866 | 867 | 868 | 869 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/WPView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WPView.h 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/25. 6 | // Copyright © 2019 Developer. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void (^block)(id other); 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface WPView : UILabel 16 | + (instancetype)viewWithTapClick:(block)tap; 17 | 18 | @property (nonatomic,copy) block tap; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/WPView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WPView.m 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/25. 6 | // Copyright © 2019 Developer. All rights reserved. 7 | // 8 | 9 | #import "WPView.h" 10 | 11 | @implementation WPView 12 | 13 | + (instancetype)viewWithTapClick:(block)tap 14 | { 15 | WPView *view = [self new]; 16 | view.tap = tap; 17 | return view; 18 | } 19 | - (instancetype)initWithFrame:(CGRect)frame 20 | { 21 | if ([super initWithFrame:frame]) { 22 | self.textAlignment = NSTextAlignmentCenter; 23 | self.textColor = [UIColor whiteColor]; 24 | self.userInteractionEnabled = YES; 25 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)]; 26 | [self addGestureRecognizer:tap]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)click:(UIGestureRecognizer *)gesture 32 | { 33 | !self.tap ?:self.tap(gesture.view); 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControl/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WPAlertControl 4 | // 5 | // Created by Developer on 2019/3/26. 6 | // Copyright © 2019 Developer. 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 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControlTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControlTests/WPAlertControlTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WPAlertControlTests.m 3 | // WPAlertControlTests 4 | // 5 | // Created by Developer on 2019/3/26. 6 | // Copyright © 2019 Developer. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WPAlertControlTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WPAlertControlTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControlUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /WPAlertControl/WPAlertControlUITests/WPAlertControlUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // WPAlertControlUITests.m 3 | // WPAlertControlUITests 4 | // 5 | // Created by Developer on 2019/3/26. 6 | // Copyright © 2019 Developer. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WPAlertControlUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation WPAlertControlUITests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | 20 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 24 | [[[XCUIApplication alloc] init] launch]; 25 | 26 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 27 | } 28 | 29 | - (void)tearDown { 30 | // Put teardown code here. This method is called after the invocation of each test method in the class. 31 | } 32 | 33 | - (void)testExample { 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | @end 39 | --------------------------------------------------------------------------------