├── .DS_Store ├── Example ├── .DS_Store ├── SPAlertController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ ├── leshengping.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ ├── libo.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── shengping_le.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── leshengping.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ │ ├── libo.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ │ └── shengping_le.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── SPAlertController │ ├── .DS_Store │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── publish_0.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_0@2x.png │ │ │ └── publish_0@3x.png │ │ ├── publish_1.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_1@2x.png │ │ │ └── publish_1@3x.png │ │ ├── publish_10.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_10@2x.png │ │ │ └── publish_10@3x.png │ │ ├── publish_11.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_11@2x.png │ │ │ └── publish_11@3x.png │ │ ├── publish_2.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_2@2x.png │ │ │ └── publish_2@3x.png │ │ ├── publish_3.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_3@2x.png │ │ │ └── publish_3@3x.png │ │ ├── publish_4.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_4@2x.png │ │ │ └── publish_4@3x.png │ │ ├── publish_5.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_5@2x.png │ │ │ └── publish_5@3x.png │ │ ├── publish_6.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_6@2x.png │ │ │ └── publish_6@3x.png │ │ ├── publish_7.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_7@2x.png │ │ │ └── publish_7@3x.png │ │ ├── publish_8.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_8@2x.png │ │ │ └── publish_8@3x.png │ │ ├── publish_9.imageset │ │ │ ├── Contents.json │ │ │ ├── publish_9@2x.png │ │ │ └── publish_9@3x.png │ │ ├── success.imageset │ │ │ ├── Contents.json │ │ │ └── 勾.png │ │ ├── telephone.imageset │ │ │ ├── Contents.json │ │ │ ├── telephone@2x.png │ │ │ └── telephone@3x.png │ │ ├── video.imageset │ │ │ ├── Contents.json │ │ │ ├── video@2x.png │ │ │ └── video@3x.png │ │ ├── wechatLogo.imageset │ │ │ ├── Contents.json │ │ │ ├── wechatLogo@2x.png │ │ │ └── wechatLogo@3x.png │ │ ├── zhiwen.imageset │ │ │ ├── Contents.json │ │ │ ├── zhiwen@2x.png │ │ │ └── zhiwen@3x.png │ │ ├── 减号.imageset │ │ │ ├── Contents.json │ │ │ ├── 减号-1.png │ │ │ ├── 减号-2.png │ │ │ └── 减号.png │ │ ├── 加号.imageset │ │ │ ├── Contents.json │ │ │ ├── 加号-1.png │ │ │ ├── 加号-3.png │ │ │ └── 加号-4.png │ │ ├── 取消.imageset │ │ │ ├── Contents.json │ │ │ ├── 叉-1.png │ │ │ ├── 叉-2.png │ │ │ └── 叉-3.png │ │ └── 苹果logo.imageset │ │ │ ├── Contents.json │ │ │ └── 苹果logo.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── CustomViews │ │ ├── CustomView1 │ │ │ ├── SPTextView.h │ │ │ ├── SPTextView.m │ │ │ ├── SendAlertView.h │ │ │ ├── SendAlertView.m │ │ │ └── SendAlertView.xib │ │ ├── CustomView17 │ │ │ ├── HCSStarRatingView.h │ │ │ ├── HCSStarRatingView.m │ │ │ ├── ScoreView.h │ │ │ └── ScoreView.m │ │ ├── CustomView2 │ │ │ ├── MyView.h │ │ │ ├── MyView.m │ │ │ ├── MyView.xib │ │ │ ├── PassWordView.h │ │ │ └── PassWordView.m │ │ ├── CustomView3 │ │ │ ├── ShoppingCartCell.h │ │ │ ├── ShoppingCartCell.m │ │ │ ├── ShoppingCartCell.xib │ │ │ ├── ShoppingCartItem.h │ │ │ ├── ShoppingCartItem.m │ │ │ ├── ShoppingCartView.h │ │ │ └── ShoppingCartView.m │ │ ├── CustomView4 │ │ │ ├── CommodityListView.h │ │ │ └── CommodityListView.m │ │ ├── CustomView5 │ │ │ ├── PickerView.h │ │ │ └── PickerView.m │ │ ├── CustomView6 │ │ │ ├── MyCenterView.h │ │ │ └── MyCenterView.m │ │ └── CustomView7 │ │ │ ├── PopView.h │ │ │ ├── PopView.m │ │ │ ├── SPButton.h │ │ │ └── SPButton.m │ ├── Images │ │ ├── image0.jpg │ │ ├── image1.jpg │ │ ├── image2.jpg │ │ ├── image3.jpg │ │ ├── image4.jpg │ │ ├── image5.jpg │ │ ├── image6.jpg │ │ ├── image7.jpg │ │ ├── image8.jpg │ │ ├── image9.jpg │ │ ├── send0.jpeg │ │ ├── send1.jpeg │ │ ├── 背景1.jpg │ │ └── 背景2.jpg │ ├── Info.plist │ ├── SPAlertController │ │ ├── SPAlertController.h │ │ └── SPAlertController.m │ ├── UIColor+DarkMode.h │ ├── UIColor+DarkMode.m │ ├── ViewController.h │ └── ViewController.m ├── SPAlertControllerTests │ ├── Info.plist │ ├── SPAlertControllerTests.m │ └── main.m └── SPAlertControllerUITests │ ├── Info.plist │ └── SPAlertControllerUITests.m ├── Images ├── .DS_Store ├── 3006981-0b23494c3ba2a6fc.jpg ├── 3006981-3cd4a2b6ff4da206.jpg ├── 3006981-41170beb443f32f0.jpg ├── 3006981-6f3752d49e579460.jpg ├── 3006981-9544748007937417.jpg ├── 3006981-9ed0416190e155dc.jpg ├── 3006981-a12eae25bc1061d6.jpg ├── 3006981-b35b79b657815756.jpg ├── 3CB7E93FDA241F253BFE156D0B4AA7E2.jpg ├── 6AAAA07F90853F52CA6166D815F619A9.jpg └── F4FB539593B4CC499E65735E4F1E8227.jpg ├── LICENSE ├── README.md ├── SPAlertController.podspec └── SPAlertController ├── SPAlertController.h └── SPAlertController.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/.DS_Store -------------------------------------------------------------------------------- /Example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/.DS_Store -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/project.xcworkspace/xcuserdata/leshengping.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController.xcodeproj/project.xcworkspace/xcuserdata/leshengping.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/project.xcworkspace/xcuserdata/libo.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController.xcodeproj/project.xcworkspace/xcuserdata/libo.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/project.xcworkspace/xcuserdata/shengping_le.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController.xcodeproj/project.xcworkspace/xcuserdata/shengping_le.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/xcuserdata/leshengping.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/xcuserdata/leshengping.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SPAlertController.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | SPAlertController.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/xcuserdata/libo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/xcuserdata/libo.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SPAlertController.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/xcuserdata/shengping_le.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Example/SPAlertController.xcodeproj/xcuserdata/shengping_le.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SPAlertController.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/SPAlertController/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/.DS_Store -------------------------------------------------------------------------------- /Example/SPAlertController/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/4. 6 | // Copyright © 2018 乐升平. 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 | -------------------------------------------------------------------------------- /Example/SPAlertController/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/4. 6 | // Copyright © 2018 乐升平. 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 | 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 | -------------------------------------------------------------------------------- /Example/SPAlertController/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 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_0@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_0@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_0.imageset/publish_0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_0.imageset/publish_0@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_0.imageset/publish_0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_0.imageset/publish_0@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_1@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_1@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_1.imageset/publish_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_1.imageset/publish_1@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_1.imageset/publish_1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_1.imageset/publish_1@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_10@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_10@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_10.imageset/publish_10@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_10.imageset/publish_10@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_10.imageset/publish_10@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_10.imageset/publish_10@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_11@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_11@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_11.imageset/publish_11@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_11.imageset/publish_11@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_11.imageset/publish_11@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_11.imageset/publish_11@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_2@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_2@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_2.imageset/publish_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_2.imageset/publish_2@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_2.imageset/publish_2@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_2.imageset/publish_2@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_3@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_3@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_3.imageset/publish_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_3.imageset/publish_3@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_3.imageset/publish_3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_3.imageset/publish_3@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_4@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_4@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_4.imageset/publish_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_4.imageset/publish_4@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_4.imageset/publish_4@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_4.imageset/publish_4@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_5@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_5@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_5.imageset/publish_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_5.imageset/publish_5@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_5.imageset/publish_5@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_5.imageset/publish_5@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_6@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_6@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_6.imageset/publish_6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_6.imageset/publish_6@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_6.imageset/publish_6@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_6.imageset/publish_6@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_7@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_7@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_7.imageset/publish_7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_7.imageset/publish_7@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_7.imageset/publish_7@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_7.imageset/publish_7@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_8@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_8@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_8.imageset/publish_8@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_8.imageset/publish_8@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_8.imageset/publish_8@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_8.imageset/publish_8@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "publish_9@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "publish_9@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_9.imageset/publish_9@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_9.imageset/publish_9@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/publish_9.imageset/publish_9@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/publish_9.imageset/publish_9@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/success.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "勾.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/success.imageset/勾.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/success.imageset/勾.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/telephone.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "telephone@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "telephone@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/telephone.imageset/telephone@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/telephone.imageset/telephone@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/telephone.imageset/telephone@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/telephone.imageset/telephone@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/video.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "video@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "video@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/video.imageset/video@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/video.imageset/video@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/video.imageset/video@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/video.imageset/video@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/wechatLogo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "wechatLogo@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "wechatLogo@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/wechatLogo.imageset/wechatLogo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/wechatLogo.imageset/wechatLogo@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/wechatLogo.imageset/wechatLogo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/wechatLogo.imageset/wechatLogo@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/zhiwen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "zhiwen@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "zhiwen@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/zhiwen.imageset/zhiwen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/zhiwen.imageset/zhiwen@2x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/zhiwen.imageset/zhiwen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/zhiwen.imageset/zhiwen@3x.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/减号.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "减号.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "减号-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "减号-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/减号.imageset/减号-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/减号.imageset/减号-1.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/减号.imageset/减号-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/减号.imageset/减号-2.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/减号.imageset/减号.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/减号.imageset/减号.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/加号.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "加号-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "加号-3.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "加号-4.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/加号.imageset/加号-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/加号.imageset/加号-1.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/加号.imageset/加号-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/加号.imageset/加号-3.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/加号.imageset/加号-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/加号.imageset/加号-4.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/取消.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "叉-1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "叉-2.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "叉-3.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/取消.imageset/叉-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/取消.imageset/叉-1.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/取消.imageset/叉-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/取消.imageset/叉-2.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/取消.imageset/叉-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/取消.imageset/叉-3.png -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/苹果logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "苹果logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/SPAlertController/Assets.xcassets/苹果logo.imageset/苹果logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Assets.xcassets/苹果logo.imageset/苹果logo.png -------------------------------------------------------------------------------- /Example/SPAlertController/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/SPAlertController/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView1/SPTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPTextView.h 3 | // SPTextView 4 | // 5 | // Created by 乐升平 on 2018/7/31. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // github地址:https://github.com/SPStore/SPTextView 8 | 9 | #import 10 | 11 | @interface SPTextView : UITextView 12 | 13 | /** 占位文字 */ 14 | @property (nonatomic, copy) NSString *placeholder; 15 | /** 占位文字的颜色 */ 16 | @property (nonatomic, strong) UIColor *placeholderColor; 17 | 18 | // 占位文字的字体永远跟textView的字体保持一致,因此该自定义控件不提供单独设置占位文字字体的属性,因为textView的光标高度依赖于textview的字体,如果占位文字跟textView的字体不一致,会导致光标跟占位文字无法对齐 19 | @end 20 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView1/SPTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPTextView.m 3 | // SPTextView 4 | // 5 | // Created by 乐升平 on 2018/7/31. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import "SPTextView.h" 10 | #import 11 | #import 12 | #import 13 | 14 | @interface SPTextView() 15 | @property(nonatomic, strong) UILabel *placeholderLabel; 16 | @end 17 | 18 | @implementation SPTextView 19 | 20 | @synthesize placeholder = _placeholder; 21 | @synthesize placeholderLabel = _placeholderLabel; 22 | @synthesize placeholderColor = _placeholderColor; 23 | 24 | - (void)initialize { 25 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self]; 26 | } 27 | 28 | - (void)dealloc { 29 | [_placeholderLabel removeFromSuperview]; 30 | _placeholderLabel = nil; 31 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 32 | } 33 | 34 | - (instancetype)init { 35 | self = [super init]; 36 | if (self) { 37 | [self initialize]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)awakeFromNib { 43 | [super awakeFromNib]; 44 | [self initialize]; 45 | } 46 | 47 | - (void)refreshPlaceholder { 48 | _placeholderLabel.alpha = ![self hasText]; 49 | 50 | [self setNeedsLayout]; 51 | [self layoutIfNeeded]; 52 | } 53 | 54 | - (void)setText:(NSString *)text { 55 | [super setText:text]; 56 | [self refreshPlaceholder]; 57 | } 58 | 59 | - (void)setAttributedText:(NSAttributedString *)attributedText { 60 | [super setAttributedText:attributedText]; 61 | [self refreshPlaceholder]; 62 | } 63 | 64 | - (void)setFont:(UIFont *)font { 65 | [super setFont:font]; 66 | self.placeholderLabel.font = self.font; 67 | 68 | [self setNeedsLayout]; 69 | [self layoutIfNeeded]; 70 | } 71 | 72 | - (void)setTextAlignment:(NSTextAlignment)textAlignment { 73 | [super setTextAlignment:textAlignment]; 74 | self.placeholderLabel.textAlignment = textAlignment; 75 | 76 | [self setNeedsLayout]; 77 | [self layoutIfNeeded]; 78 | } 79 | 80 | - (void)layoutSubviews { 81 | [super layoutSubviews]; 82 | self.placeholderLabel.frame = [self placeholderExpectedFrame]; 83 | } 84 | 85 | - (void)setPlaceholder:(NSString *)placeholder { 86 | _placeholder = placeholder; 87 | 88 | self.placeholderLabel.text = placeholder; 89 | [self refreshPlaceholder]; 90 | } 91 | 92 | - (void)setPlaceholderColor:(UIColor *)placeholderColor { 93 | _placeholderColor = placeholderColor; 94 | self.placeholderLabel.textColor = placeholderColor; 95 | } 96 | 97 | - (UIEdgeInsets)placeholderInsets { 98 | return UIEdgeInsetsMake(self.textContainerInset.top, self.textContainerInset.left + self.textContainer.lineFragmentPadding, self.textContainerInset.bottom, self.textContainerInset.right + self.textContainer.lineFragmentPadding); 99 | } 100 | 101 | - (CGRect)placeholderExpectedFrame { 102 | UIEdgeInsets placeholderInsets = [self placeholderInsets]; 103 | CGFloat maxWidth = CGRectGetWidth(self.frame)-placeholderInsets.left-placeholderInsets.right; 104 | 105 | CGSize expectedSize = [self.placeholderLabel sizeThatFits:CGSizeMake(maxWidth, CGRectGetHeight(self.frame)-placeholderInsets.top-placeholderInsets.bottom)]; 106 | 107 | return CGRectMake(placeholderInsets.left, placeholderInsets.top, maxWidth, expectedSize.height); 108 | } 109 | 110 | - (UILabel*)placeholderLabel { 111 | if (_placeholderLabel == nil) { 112 | _placeholderLabel = [[UILabel alloc] init]; 113 | _placeholderLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight); 114 | _placeholderLabel.lineBreakMode = NSLineBreakByWordWrapping; 115 | _placeholderLabel.numberOfLines = 0; 116 | _placeholderLabel.font = [UIFont systemFontOfSize:12]; // UITextView的默认字体是12pt 117 | _placeholderLabel.textAlignment = self.textAlignment; 118 | _placeholderLabel.backgroundColor = [UIColor clearColor]; 119 | _placeholderLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0]; 120 | _placeholderLabel.alpha = 0; 121 | [self addSubview:_placeholderLabel]; 122 | } 123 | 124 | return _placeholderLabel; 125 | } 126 | 127 | //When any text changes on textField, the delegate getter is called. At this time we refresh the textView's placeholder 128 | - (id)delegate { 129 | [self refreshPlaceholder]; 130 | return [super delegate]; 131 | } 132 | 133 | - (CGSize)intrinsicContentSize { 134 | if (self.hasText) { 135 | return [super intrinsicContentSize]; 136 | } 137 | 138 | UIEdgeInsets placeholderInsets = [self placeholderInsets]; 139 | CGSize newSize = [super intrinsicContentSize]; 140 | 141 | newSize.height = [self placeholderExpectedFrame].size.height + placeholderInsets.top + placeholderInsets.bottom; 142 | 143 | return newSize; 144 | } 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView1/SendAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SendAlertView.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/24. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SendAlertView : UIView 14 | 15 | + (instancetype)shareSendAlertView; 16 | 17 | @property (nonatomic, copy) UIImage *contentImage; 18 | 19 | @property (nonatomic, copy) void(^keyboardWillShow)(CGFloat value); 20 | @property (nonatomic, copy) void(^textViewHeightDidChange)(CGFloat offset); 21 | @property (nonatomic, copy) void(^textViewDidEndEditting)(void); 22 | 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView1/SendAlertView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SendAlertView.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/24. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import "SendAlertView.h" 10 | #import "SPTextView.h" 11 | #import "UIColor+DarkMode.h" 12 | 13 | @interface SendAlertView() 14 | @property (weak, nonatomic) IBOutlet UIImageView *userIconView; 15 | @property (weak, nonatomic) IBOutlet UILabel *nameLabel; 16 | @property (weak, nonatomic) IBOutlet UIImageView *contentImageView; 17 | @property (weak, nonatomic) IBOutlet SPTextView *textView; 18 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentHeightConstraint; 19 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeightConstraint; 20 | @property (nonatomic, assign) CGFloat textH; 21 | 22 | @end 23 | 24 | @implementation SendAlertView 25 | 26 | + (instancetype)shareSendAlertView { 27 | return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil] lastObject]; 28 | } 29 | 30 | - (void)awakeFromNib { 31 | [super awakeFromNib]; 32 | self.backgroundColor = [UIColor colorPairsWithLightColor:[UIColor whiteColor] darkColor:[UIColor colorWithRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0]]; 33 | self.userIconView.layer.cornerRadius = 4.0; 34 | self.userIconView.layer.masksToBounds = YES; 35 | self.textView.delegate = self; 36 | self.textView.layer.borderWidth = 0.5/[UIScreen mainScreen].scale; 37 | self.textView.layer.borderColor = [[UIColor grayColor] colorWithAlphaComponent:0.3].CGColor; 38 | self.textView.placeholder = @"给朋友留言"; 39 | self.textView.placeholderColor = [UIColor lightGrayColor]; 40 | self.textView.backgroundColor = [UIColor colorPairsWithLightColor:[UIColor colorWithRed:247.0 / 255.0 green:247.0 / 255.0 blue:247.0 / 255.0 alpha:1.0] darkColor:[UIColor colorWithRed:54.0 / 255.0 green:54.0 / 255.0 blue:54.0 / 255.0 alpha:1.0]]; 41 | _textH = ceil(self.textView.font.lineHeight) + self.textView.textContainerInset.top + self.textView.textContainerInset.bottom; 42 | 43 | } 44 | 45 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 46 | if (self = [super initWithCoder:aDecoder]) { 47 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 48 | } 49 | return self; 50 | } 51 | 52 | - (void)setContentImage:(UIImage *)contentImage { 53 | _contentImage = contentImage; 54 | self.contentImageView.image = contentImage; 55 | if (_contentImage) { 56 | CGFloat contentH; 57 | CGFloat imgRatio = _contentImage.size.height/_contentImage.size.width; 58 | CGFloat contentW = self.bounds.size.width-30; // 30是contentImageView的左右间距之和 59 | if (_contentImage.size.height < contentW) { 60 | contentH = _contentImage.size.height; 61 | } else { 62 | contentH = imgRatio * contentW; 63 | } 64 | if (contentH > [UIScreen mainScreen].bounds.size.height-300) { // 300是一个大概写的数字 65 | contentH = [UIScreen mainScreen].bounds.size.height-300; 66 | } 67 | // 更新图片的高度约束 68 | self.contentHeightConstraint.constant = contentH; 69 | } 70 | } 71 | 72 | - (void)textViewDidBeginEditing:(UITextView *)textView { 73 | 74 | } 75 | 76 | - (void)textViewDidChange:(UITextView *)textView { 77 | 78 | CGFloat maxHeight = textView.font.lineHeight * 3 + textView.textContainerInset.top + textView.textContainerInset.bottom; 79 | 80 | NSInteger height = ceilf([textView sizeThatFits:CGSizeMake(textView.bounds.size.width, MAXFLOAT)].height); 81 | 82 | if (_textH != height) { // 高度不一样,就改变了高度 83 | 84 | // 最大高度,可以滚动 85 | if (height > maxHeight && maxHeight > 0) { 86 | self.textView.scrollEnabled = YES; 87 | height = maxHeight; 88 | } else { 89 | self.textView.scrollEnabled = NO; 90 | } 91 | if (self.textViewHeightDidChange) { 92 | self.textViewHeightConstraint.constant = height; 93 | self.textViewHeightDidChange(height - _textH); 94 | } 95 | _textH = height; 96 | } 97 | } 98 | 99 | - (void)textViewDidEndEditing:(UITextView *)textView { 100 | if (self.textViewDidEndEditting) { 101 | self.textViewDidEndEditting(); 102 | } 103 | } 104 | 105 | - (void)keyboardWillShow:(NSNotification *)note { 106 | CGRect keyboardEndFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 107 | CGFloat keyboardEndY = keyboardEndFrame.origin.y; // 200 108 | CGFloat textViewMaxY = CGRectGetMaxY([self.textView.superview convertRect:self.textView.frame toView:nil]); 109 | CGFloat diff = textViewMaxY - keyboardEndY + 80; 110 | if (self.keyboardWillShow) { 111 | self.keyboardWillShow(diff); 112 | } 113 | } 114 | 115 | - (void)dealloc { 116 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView1/SendAlertView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView17/HCSStarRatingView.h: -------------------------------------------------------------------------------- 1 | // HCSStarRatingView.h 2 | // 3 | // Copyright (c) 2015 Hugo Sousa 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | @import UIKit; 24 | 25 | typedef BOOL(^HCSStarRatingViewShouldBeginGestureRecognizerBlock)(UIGestureRecognizer *gestureRecognizer); 26 | 27 | IB_DESIGNABLE 28 | @interface HCSStarRatingView : UIControl 29 | @property (nonatomic) IBInspectable NSUInteger maximumValue; 30 | @property (nonatomic) IBInspectable CGFloat minimumValue; 31 | @property (nonatomic) IBInspectable CGFloat value; 32 | @property (nonatomic) IBInspectable CGFloat spacing; 33 | @property (nonatomic) IBInspectable BOOL allowsHalfStars; 34 | @property (nonatomic) IBInspectable BOOL accurateHalfStars; 35 | @property (nonatomic) IBInspectable BOOL continuous; 36 | 37 | @property (nonatomic) BOOL shouldBecomeFirstResponder; 38 | 39 | // Optional: if `nil` method will return `NO`. 40 | @property (nonatomic, copy) HCSStarRatingViewShouldBeginGestureRecognizerBlock shouldBeginGestureRecognizerBlock; 41 | 42 | @property (nonatomic, strong) IBInspectable UIColor *starBorderColor; 43 | @property (nonatomic) IBInspectable CGFloat starBorderWidth; 44 | 45 | @property (nonatomic, strong) IBInspectable UIColor *emptyStarColor; 46 | 47 | @property (nonatomic, strong) IBInspectable UIImage *emptyStarImage; 48 | @property (nonatomic, strong) IBInspectable UIImage *halfStarImage; 49 | @property (nonatomic, strong) IBInspectable UIImage *filledStarImage; 50 | @end 51 | 52 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView17/HCSStarRatingView.m: -------------------------------------------------------------------------------- 1 | // HCSStarRatingView.m 2 | // 3 | // Copyright (c) 2015 Hugo Sousa 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "HCSStarRatingView.h" 24 | 25 | @interface HCSStarRatingView () 26 | @property (nonatomic, readonly) BOOL shouldUseImages; 27 | @end 28 | 29 | @implementation HCSStarRatingView { 30 | CGFloat _minimumValue; 31 | NSUInteger _maximumValue; 32 | CGFloat _value; 33 | UIColor *_starBorderColor; 34 | } 35 | 36 | @dynamic minimumValue; 37 | @dynamic maximumValue; 38 | @dynamic value; 39 | @dynamic shouldUseImages; 40 | @dynamic starBorderColor; 41 | 42 | #pragma mark - Initialization 43 | 44 | - (instancetype)initWithFrame:(CGRect)frame { 45 | self = [super initWithFrame:frame]; 46 | if (self) { 47 | [self _customInit]; 48 | } 49 | return self; 50 | } 51 | 52 | - (id)initWithCoder:(NSCoder *)aDecoder { 53 | self = [super initWithCoder:aDecoder]; 54 | if (self) { 55 | [self _customInit]; 56 | } 57 | return self; 58 | } 59 | 60 | - (void)_customInit { 61 | self.exclusiveTouch = YES; 62 | _minimumValue = 0; 63 | _maximumValue = 5; 64 | _value = 0; 65 | _spacing = 5.f; 66 | _continuous = YES; 67 | _starBorderWidth = 1.0f; 68 | _emptyStarColor = [UIColor clearColor]; 69 | 70 | [self _updateAppearanceForState:self.enabled]; 71 | } 72 | 73 | - (void)setNeedsLayout { 74 | [super setNeedsLayout]; 75 | [self setNeedsDisplay]; 76 | } 77 | 78 | #pragma mark - Properties 79 | 80 | - (UIColor *)backgroundColor { 81 | if ([super backgroundColor]) { 82 | return [super backgroundColor]; 83 | } else { 84 | return self.isOpaque ? [UIColor whiteColor] : [UIColor clearColor]; 85 | }; 86 | } 87 | 88 | - (CGFloat)minimumValue { 89 | return MAX(_minimumValue, 0); 90 | } 91 | 92 | - (void)setMinimumValue:(CGFloat)minimumValue { 93 | if (_minimumValue != minimumValue) { 94 | _minimumValue = minimumValue; 95 | [self setNeedsDisplay]; 96 | } 97 | } 98 | 99 | - (NSUInteger)maximumValue { 100 | return MAX(_minimumValue, _maximumValue); 101 | } 102 | 103 | - (void)setMaximumValue:(NSUInteger)maximumValue { 104 | if (_maximumValue != maximumValue) { 105 | _maximumValue = maximumValue; 106 | [self setNeedsDisplay]; 107 | [self invalidateIntrinsicContentSize]; 108 | } 109 | } 110 | 111 | - (CGFloat)value { 112 | return MIN(MAX(_value, _minimumValue), _maximumValue); 113 | } 114 | 115 | - (void)setValue:(CGFloat)value { 116 | [self setValue:value sendValueChangedAction:NO]; 117 | } 118 | 119 | - (void)setValue:(CGFloat)value sendValueChangedAction:(BOOL)sendAction { 120 | [self willChangeValueForKey:NSStringFromSelector(@selector(value))]; 121 | if (_value != value && value >= _minimumValue && value <= _maximumValue) { 122 | _value = value; 123 | if (sendAction) [self sendActionsForControlEvents:UIControlEventValueChanged]; 124 | [self setNeedsDisplay]; 125 | } 126 | [self didChangeValueForKey:NSStringFromSelector(@selector(value))]; 127 | } 128 | 129 | - (void)setSpacing:(CGFloat)spacing { 130 | _spacing = MAX(spacing, 0); 131 | [self setNeedsDisplay]; 132 | } 133 | 134 | - (void)setAllowsHalfStars:(BOOL)allowsHalfStars { 135 | if (_allowsHalfStars != allowsHalfStars) { 136 | _allowsHalfStars = allowsHalfStars; 137 | [self setNeedsDisplay]; 138 | } 139 | } 140 | 141 | - (void)setAccurateHalfStars:(BOOL)accurateHalfStars { 142 | if (_accurateHalfStars != accurateHalfStars) { 143 | _accurateHalfStars = accurateHalfStars; 144 | [self setNeedsDisplay]; 145 | } 146 | } 147 | 148 | - (void)setEmptyStarImage:(UIImage *)emptyStarImage { 149 | if (_emptyStarImage != emptyStarImage) { 150 | _emptyStarImage = emptyStarImage; 151 | [self setNeedsDisplay]; 152 | } 153 | } 154 | 155 | - (void)setHalfStarImage:(UIImage *)halfStarImage { 156 | if (_halfStarImage != halfStarImage) { 157 | _halfStarImage = halfStarImage; 158 | [self setNeedsDisplay]; 159 | } 160 | } 161 | 162 | - (void)setFilledStarImage:(UIImage *)filledStarImage { 163 | if (_filledStarImage != filledStarImage) { 164 | _filledStarImage = filledStarImage; 165 | [self setNeedsDisplay]; 166 | } 167 | } 168 | 169 | - (void)setEmptyStarColor:(UIColor *)emptyStarColor { 170 | if (_emptyStarColor != emptyStarColor) { 171 | _emptyStarColor = emptyStarColor; 172 | [self setNeedsDisplay]; 173 | } 174 | } 175 | 176 | - (void)setStarBorderColor:(UIColor *)starBorderColor { 177 | if (_starBorderColor != starBorderColor) { 178 | _starBorderColor = starBorderColor; 179 | [self setNeedsDisplay]; 180 | } 181 | } 182 | 183 | - (UIColor *)starBorderColor { 184 | if (_starBorderColor == nil) { 185 | return self.tintColor; 186 | } else { 187 | return _starBorderColor; 188 | } 189 | } 190 | 191 | - (void)setStarBorderWidth:(CGFloat)starBorderWidth { 192 | _starBorderWidth = MAX(0, starBorderWidth); 193 | [self setNeedsDisplay]; 194 | } 195 | 196 | 197 | - (BOOL)shouldUseImages { 198 | return (self.emptyStarImage!=nil && self.filledStarImage!=nil); 199 | } 200 | 201 | #pragma mark - State 202 | 203 | - (void)setEnabled:(BOOL)enabled 204 | { 205 | [self _updateAppearanceForState:enabled]; 206 | [super setEnabled:enabled]; 207 | } 208 | 209 | - (void)_updateAppearanceForState:(BOOL)enabled 210 | { 211 | self.alpha = enabled ? 1.f : .5f; 212 | } 213 | 214 | #pragma mark - Image Drawing 215 | 216 | - (void)_drawStarImageWithFrame:(CGRect)frame tintColor:(UIColor*)tintColor highlighted:(BOOL)highlighted { 217 | UIImage *image = highlighted ? self.filledStarImage : self.emptyStarImage; 218 | [self _drawImage:image frame:frame tintColor:tintColor]; 219 | } 220 | 221 | - (void)_drawHalfStarImageWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor { 222 | [self _drawAccurateHalfStarImageWithFrame:frame tintColor:tintColor progress:.5f]; 223 | } 224 | 225 | - (void)_drawAccurateHalfStarImageWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor progress:(CGFloat)progress { 226 | UIImage *image = self.halfStarImage; 227 | if (image == nil) { 228 | // first draw star outline 229 | [self _drawStarImageWithFrame:frame tintColor:tintColor highlighted:NO]; 230 | 231 | image = self.filledStarImage; 232 | CGRect imageFrame = CGRectMake(0, 0, image.size.width * image.scale * progress, image.size.height * image.scale); 233 | frame.size.width *= progress; 234 | CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, imageFrame); 235 | UIImage *halfImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation]; 236 | image = [halfImage imageWithRenderingMode:image.renderingMode]; 237 | CGImageRelease(imageRef); 238 | } 239 | [self _drawImage:image frame:frame tintColor:tintColor]; 240 | } 241 | 242 | - (void)_drawImage:(UIImage *)image frame:(CGRect)frame tintColor:(UIColor *)tintColor { 243 | if (image.renderingMode == UIImageRenderingModeAlwaysTemplate) { 244 | [tintColor setFill]; 245 | } 246 | [image drawInRect:frame]; 247 | } 248 | 249 | #pragma mark - Shape Drawing 250 | 251 | - (void)_drawStarShapeWithFrame:(CGRect)frame tintColor:(UIColor*)tintColor highlighted:(BOOL)highlighted { 252 | [self _drawAccurateHalfStarShapeWithFrame:frame tintColor:tintColor progress:highlighted ? 1.f : 0.f]; 253 | } 254 | 255 | - (void)_drawHalfStarShapeWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor { 256 | [self _drawAccurateHalfStarShapeWithFrame:frame tintColor:tintColor progress:.5f]; 257 | } 258 | 259 | - (void)_drawAccurateHalfStarShapeWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor progress:(CGFloat)progress { 260 | UIBezierPath* starShapePath = UIBezierPath.bezierPath; 261 | [starShapePath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.62723 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37309 * CGRectGetHeight(frame))]; 262 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.02500 * CGRectGetHeight(frame))]; 263 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.37292 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37309 * CGRectGetHeight(frame))]; 264 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.02500 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.39112 * CGRectGetHeight(frame))]; 265 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.30504 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.62908 * CGRectGetHeight(frame))]; 266 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.20642 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.97500 * CGRectGetHeight(frame))]; 267 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.78265 * CGRectGetHeight(frame))]; 268 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79358 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.97500 * CGRectGetHeight(frame))]; 269 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.69501 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.62908 * CGRectGetHeight(frame))]; 270 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.97500 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.39112 * CGRectGetHeight(frame))]; 271 | [starShapePath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.62723 * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.37309 * CGRectGetHeight(frame))]; 272 | [starShapePath closePath]; 273 | starShapePath.miterLimit = 4; 274 | 275 | CGFloat frameWidth = frame.size.width; 276 | CGRect rightRectOfStar = CGRectMake(frame.origin.x + progress * frameWidth, frame.origin.y, frameWidth - progress * frameWidth, frame.size.height); 277 | UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectInfinite]; 278 | [clipPath appendPath:[UIBezierPath bezierPathWithRect:rightRectOfStar]]; 279 | clipPath.usesEvenOddFillRule = YES; 280 | 281 | [_emptyStarColor setFill]; 282 | [starShapePath fill]; 283 | 284 | CGContextSaveGState(UIGraphicsGetCurrentContext()); { 285 | [clipPath addClip]; 286 | [tintColor setFill]; 287 | [starShapePath fill]; 288 | } 289 | CGContextRestoreGState(UIGraphicsGetCurrentContext()); 290 | 291 | [self.starBorderColor setStroke]; 292 | starShapePath.lineWidth = _starBorderWidth; 293 | [starShapePath stroke]; 294 | } 295 | 296 | #pragma mark - Drawing 297 | 298 | - (void)drawRect:(CGRect)rect { 299 | CGContextRef context = UIGraphicsGetCurrentContext(); 300 | CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor); 301 | CGContextFillRect(context, rect); 302 | 303 | CGFloat availableWidth = rect.size.width - (_spacing * (_maximumValue - 1)) - 2; 304 | CGFloat cellWidth = (availableWidth / _maximumValue); 305 | CGFloat starSide = (cellWidth <= rect.size.height) ? cellWidth : rect.size.height; 306 | starSide = (self.shouldUseImages) ? starSide : (starSide - _starBorderWidth); 307 | 308 | for (int idx = 0; idx < _maximumValue; idx++) { 309 | CGPoint center = CGPointMake(cellWidth*idx + cellWidth/2 + _spacing*idx + 1, rect.size.height/2); 310 | CGRect frame = CGRectMake(center.x - starSide/2, center.y - starSide/2, starSide, starSide); 311 | BOOL highlighted = (idx+1 <= ceilf(_value)); 312 | if (_allowsHalfStars && highlighted && (idx+1 > _value)) { 313 | if (_accurateHalfStars) { 314 | [self _drawAccurateStarWithFrame:frame tintColor:self.tintColor progress:_value - idx]; 315 | } 316 | else { 317 | [self _drawHalfStarWithFrame:frame tintColor:self.tintColor]; 318 | } 319 | } else { 320 | [self _drawStarWithFrame:frame tintColor:self.tintColor highlighted:highlighted]; 321 | } 322 | } 323 | } 324 | 325 | - (void)_drawStarWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor highlighted:(BOOL)highlighted { 326 | if (self.shouldUseImages) { 327 | [self _drawStarImageWithFrame:frame tintColor:tintColor highlighted:highlighted]; 328 | } else { 329 | [self _drawStarShapeWithFrame:frame tintColor:tintColor highlighted:highlighted]; 330 | } 331 | } 332 | 333 | - (void)_drawHalfStarWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor { 334 | if (self.shouldUseImages) { 335 | [self _drawHalfStarImageWithFrame:frame tintColor:tintColor]; 336 | } else { 337 | [self _drawHalfStarShapeWithFrame:frame tintColor:tintColor]; 338 | } 339 | } 340 | - (void)_drawAccurateStarWithFrame:(CGRect)frame tintColor:(UIColor *)tintColor progress:(CGFloat)progress { 341 | if (self.shouldUseImages) { 342 | [self _drawAccurateHalfStarImageWithFrame:frame tintColor:tintColor progress:progress]; 343 | } else { 344 | [self _drawAccurateHalfStarShapeWithFrame:frame tintColor:tintColor progress:progress]; 345 | } 346 | } 347 | #pragma mark - Touches 348 | 349 | - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 350 | if (self.isEnabled) { 351 | [super beginTrackingWithTouch:touch withEvent:event]; 352 | if (_shouldBecomeFirstResponder && ![self isFirstResponder]) { 353 | [self becomeFirstResponder]; 354 | } 355 | [self _handleTouch:touch]; 356 | return YES; 357 | } else { 358 | return NO; 359 | } 360 | } 361 | 362 | - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 363 | if (self.isEnabled) { 364 | [super continueTrackingWithTouch:touch withEvent:event]; 365 | [self _handleTouch:touch]; 366 | return YES; 367 | } else { 368 | return NO; 369 | } 370 | } 371 | 372 | - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 373 | [super endTrackingWithTouch:touch withEvent:event]; 374 | if (_shouldBecomeFirstResponder && [self isFirstResponder]) { 375 | [self resignFirstResponder]; 376 | } 377 | [self _handleTouch:touch]; 378 | if (!_continuous) { 379 | [self sendActionsForControlEvents:UIControlEventValueChanged]; 380 | } 381 | } 382 | 383 | - (void)cancelTrackingWithEvent:(UIEvent *)event { 384 | [super cancelTrackingWithEvent:event]; 385 | if (_shouldBecomeFirstResponder && [self isFirstResponder]) { 386 | [self resignFirstResponder]; 387 | } 388 | } 389 | 390 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 391 | if ([gestureRecognizer.view isEqual:self]) { 392 | return !self.isUserInteractionEnabled; 393 | } 394 | return self.shouldBeginGestureRecognizerBlock ? self.shouldBeginGestureRecognizerBlock(gestureRecognizer) : NO; 395 | } 396 | 397 | - (void)_handleTouch:(UITouch *)touch { 398 | CGFloat cellWidth = self.bounds.size.width / _maximumValue; 399 | CGPoint location = [touch locationInView:self]; 400 | CGFloat value = location.x / cellWidth; 401 | if (_allowsHalfStars) { 402 | if (_accurateHalfStars) { 403 | value = value; 404 | } 405 | else { 406 | if (value+.5f < ceilf(value)) { 407 | value = floor(value)+.5f; 408 | } else { 409 | value = ceilf(value); 410 | } 411 | } 412 | } else { 413 | value = ceilf(value); 414 | } 415 | [self setValue:value sendValueChangedAction:_continuous]; 416 | } 417 | 418 | #pragma mark - First responder 419 | 420 | - (BOOL)canBecomeFirstResponder { 421 | return _shouldBecomeFirstResponder; 422 | } 423 | 424 | #pragma mark - Intrinsic Content Size 425 | 426 | - (CGSize)intrinsicContentSize { 427 | CGFloat height = 44.f; 428 | return CGSizeMake(_maximumValue * height + (_maximumValue-1) * _spacing, height); 429 | } 430 | 431 | #pragma mark - Accessibility 432 | 433 | - (BOOL)isAccessibilityElement { 434 | return YES; 435 | } 436 | 437 | - (NSString *)accessibilityLabel { 438 | return [super accessibilityLabel] ?: NSLocalizedString(@"Rating", @"Accessibility label for star rating control."); 439 | } 440 | 441 | - (UIAccessibilityTraits)accessibilityTraits { 442 | return ([super accessibilityTraits] | UIAccessibilityTraitAdjustable); 443 | } 444 | 445 | - (NSString *)accessibilityValue { 446 | return [@(self.value) description]; 447 | } 448 | 449 | - (BOOL)accessibilityActivate { 450 | return YES; 451 | } 452 | 453 | - (void)accessibilityIncrement { 454 | CGFloat value = self.value + (self.allowsHalfStars ? .5f : 1.f); 455 | [self setValue:value sendValueChangedAction:YES]; 456 | } 457 | 458 | - (void)accessibilityDecrement { 459 | CGFloat value = self.value - (self.allowsHalfStars ? .5f : 1.f); 460 | [self setValue:value sendValueChangedAction:YES]; 461 | } 462 | 463 | @end 464 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView17/ScoreView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ScoreView.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/24. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ScoreView : UIView 14 | @property (nonatomic, copy) void(^finishButtonBlock)(void); 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView17/ScoreView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ScoreView.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/24. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import "ScoreView.h" 10 | #import "HCSStarRatingView.h" 11 | #import "UIColor+DarkMode.h" 12 | 13 | @interface ScoreView() 14 | 15 | @property (nonatomic, weak) HCSStarRatingView *starRatingView; 16 | @property (nonatomic, weak) UIView *line; 17 | @property (nonatomic, weak) UIButton *finishButton; 18 | @property (nonatomic, strong) NSMutableArray *subViewContraints; 19 | @end 20 | 21 | @implementation ScoreView 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame { 24 | if (self = [super initWithFrame:frame]) { 25 | 26 | self.backgroundColor = [UIColor alertBackgroundColor]; 27 | 28 | HCSStarRatingView *starRatingView = [[HCSStarRatingView alloc] init]; 29 | starRatingView.translatesAutoresizingMaskIntoConstraints = NO; 30 | starRatingView.maximumValue = 5; 31 | starRatingView.minimumValue = 0; 32 | starRatingView.value = 2; 33 | starRatingView.spacing = 20; 34 | starRatingView.tintColor = [UIColor colorWithRed:0.0 green:0.48 blue:1.0 alpha:1.0]; 35 | starRatingView.allowsHalfStars = YES; 36 | starRatingView.backgroundColor = [UIColor alertBackgroundColor]; 37 | [starRatingView addTarget:self action:@selector(starRatingViewDidChangeValue:) forControlEvents:UIControlEventValueChanged]; 38 | [self addSubview:starRatingView]; 39 | _starRatingView = starRatingView; 40 | 41 | UIView *line = [UIView new]; 42 | line.translatesAutoresizingMaskIntoConstraints = NO; 43 | line.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.3]; 44 | [self addSubview:line]; 45 | _line = line; 46 | 47 | UIButton *finishButton = [UIButton buttonWithType:UIButtonTypeCustom]; 48 | finishButton.translatesAutoresizingMaskIntoConstraints = NO; 49 | finishButton.backgroundColor = [UIColor alertBackgroundColor]; 50 | [finishButton setTitle:@"完成" forState:UIControlStateNormal]; 51 | [finishButton setTitleColor:[UIColor colorWithRed:0.0 green:0.48 blue:1.0 alpha:1.0] forState:UIControlStateNormal]; 52 | [finishButton addTarget:self action:@selector(finishButtonAction) forControlEvents:UIControlEventTouchUpInside]; 53 | [self addSubview:finishButton]; 54 | _finishButton = finishButton; 55 | } 56 | return self; 57 | } 58 | 59 | - (void)starRatingViewDidChangeValue:(HCSStarRatingView *)starRatingView { 60 | 61 | } 62 | 63 | - (void)finishButtonAction { 64 | if (self.finishButtonBlock) { 65 | self.finishButtonBlock(); 66 | } 67 | } 68 | 69 | - (void)updateConstraints { 70 | [super updateConstraints]; 71 | CGFloat lineH = 1.0/[UIScreen mainScreen].scale; 72 | 73 | HCSStarRatingView *starRatingView = self.starRatingView; 74 | UIView *line = self.line; 75 | UIButton *finishButton = self.finishButton; 76 | 77 | NSMutableArray *subViewContraints = [NSMutableArray array]; 78 | if (self.subViewContraints) { 79 | [NSLayoutConstraint deactivateConstraints:self.subViewContraints]; 80 | subViewContraints = nil; 81 | } 82 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:starRatingView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0f constant:40]]; 83 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:starRatingView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0f constant:-40]]; 84 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:starRatingView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0f constant:0]]; 85 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:starRatingView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:line attribute:NSLayoutAttributeTop multiplier:1.0f constant:0]]; 86 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:starRatingView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:50]]; 87 | 88 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0]]; 89 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0f constant:0]]; 90 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:finishButton attribute:NSLayoutAttributeTop multiplier:1.0f constant:0]]; 91 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:lineH]]; 92 | 93 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:finishButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0]]; 94 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:finishButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0f constant:0]]; 95 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:finishButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0]]; 96 | [subViewContraints addObject:[NSLayoutConstraint constraintWithItem:finishButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:50]]; 97 | [NSLayoutConstraint activateConstraints:subViewContraints]; 98 | self.subViewContraints = subViewContraints; 99 | } 100 | 101 | //- (void)layoutSubviews { 102 | // [super layoutSubviews]; 103 | // CGFloat lineH = 1.0/[UIScreen mainScreen].scale; 104 | // self.starRatingView.frame = CGRectMake((self.bounds.size.width-200)/2.0, 0, 200, (self.bounds.size.height - lineH) / 2.0); 105 | // self.line.frame = CGRectMake(0, CGRectGetMaxY(self.starRatingView.frame), self.bounds.size.width, lineH); 106 | // self.finishButton.frame = CGRectMake(0, CGRectGetMaxY(self.line.frame), self.bounds.size.width, (self.bounds.size.height - lineH) / 2.0); 107 | //} 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView2/MyView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyView.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PassWordView.h" 11 | 12 | @interface MyView : UIView 13 | 14 | + (instancetype)shareMyView; 15 | 16 | @property (weak, nonatomic) IBOutlet PassWordView *passwordView; 17 | @property (weak, nonatomic) IBOutlet UIButton *cancelButton; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView2/MyView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyView.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "MyView.h" 10 | #import "UIColor+DarkMode.h" 11 | 12 | @interface MyView() 13 | @property (weak, nonatomic) IBOutlet UIView *topView; 14 | @property (weak, nonatomic) IBOutlet UIView *infoView; 15 | 16 | @end 17 | 18 | @implementation MyView 19 | 20 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 21 | if (self = [super initWithCoder:aDecoder]) { 22 | } 23 | return self; 24 | } 25 | 26 | - (void)awakeFromNib { 27 | [super awakeFromNib]; 28 | 29 | self.backgroundColor = [UIColor colorPairsWithLightColor:[UIColor whiteColor] darkColor:[UIColor blackColor]]; 30 | 31 | self.passwordView.pointColor = [UIColor colorPairsWithLightColor:[UIColor blackColor] darkColor:[UIColor whiteColor]]; 32 | self.topView.backgroundColor = [UIColor alertBackgroundColor]; 33 | self.infoView.backgroundColor = [UIColor alertBackgroundColor]; 34 | } 35 | 36 | 37 | + (instancetype)shareMyView { 38 | return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil] lastObject]; 39 | } 40 | 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView2/MyView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView2/PassWordView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WCLPassWordView.h 3 | // Youqun 4 | // 5 | // Created by 乐升平 on 16/6/1. 6 | // Copyright © 2016年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | @class PassWordView; 11 | 12 | @protocol PassWordViewDelegate 13 | 14 | @optional 15 | /** 16 | * 监听输入的改变 17 | */ 18 | - (void)passWordDidChange:(PassWordView *)passWord; 19 | 20 | /** 21 | * 监听输入的完成时 22 | */ 23 | - (void)passWordCompleteInput:(PassWordView *)passWord; 24 | 25 | /** 26 | * 监听开始输入 27 | */ 28 | - (void)passWordBeginInput:(PassWordView *)passWord; 29 | 30 | 31 | @end 32 | 33 | IB_DESIGNABLE 34 | 35 | @interface PassWordView : UIView 36 | 37 | @property (assign, nonatomic) IBInspectable NSUInteger passWordNum;//密码的位数 38 | @property (assign, nonatomic) IBInspectable CGFloat squareWidth;//正方形的大小 39 | @property (assign, nonatomic) IBInspectable CGFloat pointRadius;//黑点的半径 40 | @property (strong, nonatomic) IBInspectable UIColor *pointColor;//黑点的颜色 41 | @property (strong, nonatomic) IBInspectable UIColor *rectColor;//边框的颜色 42 | @property (weak, nonatomic) IBOutlet id delegate; 43 | @property (strong, nonatomic, readonly) NSMutableString *textStore;//保存密码的字符串 44 | 45 | @end 46 | 47 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView2/PassWordView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WCLPassWordView.m 3 | // Youqun 4 | // 5 | // Created by 乐升平 on 16/6/1. 6 | // Copyright © 2016年 iDress. All rights reserved. 7 | // 8 | 9 | #import "PassWordView.h" 10 | 11 | @interface PassWordView () 12 | 13 | @property (strong, nonatomic) NSMutableString *textStore;// 保存密码的字符串 14 | 15 | @end 16 | 17 | @implementation PassWordView 18 | 19 | static NSString * const MONEYNUMBERS = @"0123456789"; 20 | 21 | - (instancetype)initWithCoder:(NSCoder *)coder { 22 | self = [super initWithCoder:coder]; 23 | if (self) { 24 | self.textStore = [NSMutableString string]; 25 | self.squareWidth = 45; 26 | self.passWordNum = 6; 27 | self.pointRadius = 6; 28 | self.backgroundColor = [self colorPairsWithLightColor:[UIColor whiteColor] 29 | darkColor:[UIColor colorWithRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0]]; 30 | self.rectColor = [self colorPairsWithLightColor:[UIColor colorWithRed:51.0/255.0 green:51.0/255.0 blue:51.0/255.0 alpha:1.0] darkColor:[UIColor redColor]]; 31 | self.pointColor = [self colorPairsWithLightColor:[UIColor colorWithRed:223.0/255.0 green:223.0/255.0 blue:223.0/255.0 alpha:1.0] darkColor:[UIColor yellowColor]]; 32 | [self becomeFirstResponder]; 33 | } 34 | return self; 35 | } 36 | 37 | /** 38 | * 设置正方形的边长 39 | */ 40 | - (void)setSquareWidth:(CGFloat)squareWidth { 41 | _squareWidth = squareWidth; 42 | [self setNeedsDisplay]; 43 | } 44 | 45 | /** 46 | * 设置键盘的类型 47 | */ 48 | - (UIKeyboardType)keyboardType { 49 | return UIKeyboardTypeNumberPad; 50 | } 51 | 52 | /** 53 | * 设置密码的位数 54 | */ 55 | - (void)setPassWordNum:(NSUInteger)passWordNum { 56 | _passWordNum = passWordNum; 57 | [self setNeedsDisplay]; 58 | } 59 | 60 | - (BOOL)becomeFirstResponder { 61 | if ([self.delegate respondsToSelector:@selector(passWordBeginInput:)]) { 62 | [self.delegate passWordBeginInput:self]; 63 | } 64 | return [super becomeFirstResponder]; 65 | } 66 | 67 | /** 68 | * 是否能成为第一响应者 69 | */ 70 | - (BOOL)canBecomeFirstResponder { 71 | return YES; 72 | } 73 | 74 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 75 | if (![self isFirstResponder]) { 76 | [self becomeFirstResponder]; 77 | } 78 | } 79 | 80 | #pragma mark - UIKeyInput 81 | /** 82 | * 用于显示的文本对象是否有任何文本 83 | */ 84 | - (BOOL)hasText { 85 | return self.textStore.length > 0; 86 | } 87 | 88 | /** 89 | * 插入文本 90 | */ 91 | - (void)insertText:(NSString *)text { 92 | if (self.textStore.length < self.passWordNum) { 93 | //判断是否是数字 94 | NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:MONEYNUMBERS] invertedSet]; 95 | NSString*filtered = [[text componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; 96 | BOOL basicTest = [text isEqualToString:filtered]; 97 | if(basicTest) { 98 | [self.textStore appendString:text]; 99 | if ([self.delegate respondsToSelector:@selector(passWordDidChange:)]) { 100 | [self.delegate passWordDidChange:self]; 101 | } 102 | if (self.textStore.length == self.passWordNum) { 103 | if ([self.delegate respondsToSelector:@selector(passWordCompleteInput:)]) { 104 | [self.delegate passWordCompleteInput:self]; 105 | } 106 | } 107 | [self setNeedsDisplay]; 108 | } 109 | } 110 | } 111 | 112 | /** 113 | * 删除文本 114 | */ 115 | - (void)deleteBackward { 116 | if (self.textStore.length > 0) { 117 | [self.textStore deleteCharactersInRange:NSMakeRange(self.textStore.length - 1, 1)]; 118 | if ([self.delegate respondsToSelector:@selector(passWordDidChange:)]) { 119 | [self.delegate passWordDidChange:self]; 120 | } 121 | } 122 | [self setNeedsDisplay]; 123 | } 124 | 125 | // Only override drawRect: if you perform custom drawing. 126 | - (void)drawRect:(CGRect)rect { 127 | CGFloat height = rect.size.height; 128 | CGFloat width = rect.size.width; 129 | CGFloat x = (width - self.squareWidth*self.passWordNum)/2.0; 130 | CGFloat y = (height - self.squareWidth)/2.0; 131 | CGContextRef context = UIGraphicsGetCurrentContext(); 132 | //画外框 133 | CGContextAddRect(context, CGRectMake( x, y, self.squareWidth * self.passWordNum, self.squareWidth)); 134 | CGContextSetLineWidth(context, 1); 135 | CGContextSetStrokeColorWithColor(context, self.rectColor.CGColor); 136 | CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor); 137 | //画竖条 138 | for (int i = 1; i <= self.passWordNum; i++) { 139 | CGContextMoveToPoint(context, x + i * self.squareWidth, y); 140 | CGContextAddLineToPoint(context, x + i * self.squareWidth, y + self.squareWidth); 141 | CGContextClosePath(context); 142 | } 143 | CGContextDrawPath(context, kCGPathFillStroke); 144 | CGContextSetFillColorWithColor(context, self.pointColor.CGColor); 145 | //画黑点 146 | for (int i = 1; i <= self.textStore.length; i++) { 147 | CGContextAddArc(context, x + i * self.squareWidth - self.squareWidth/2.0, y + self.squareWidth / 2, self.pointRadius, 0, M_PI * 2, YES); 148 | CGContextDrawPath(context, kCGPathFill); 149 | } 150 | } 151 | 152 | - (UIColor *)colorPairsWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor { 153 | if (@available(iOS 13.0, *)) { 154 | return [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) { 155 | if(traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { 156 | return darkColor; 157 | } else { 158 | return lightColor; 159 | } 160 | }]; 161 | } else { 162 | return lightColor; 163 | } 164 | } 165 | 166 | @end 167 | 168 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCartCell.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ShoppingCartItem; 12 | 13 | @interface ShoppingCartCell : UITableViewCell 14 | @property (nonatomic, strong) ShoppingCartItem *item; 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCartCell.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "ShoppingCartCell.h" 10 | #import "ShoppingCartItem.h" 11 | 12 | @interface ShoppingCartCell() 13 | @property (weak, nonatomic) IBOutlet UILabel *foodNmaeLabel; 14 | @property (weak, nonatomic) IBOutlet UILabel *priceLabel; 15 | @property (weak, nonatomic) IBOutlet UILabel *countLabel; 16 | 17 | @end 18 | 19 | @implementation ShoppingCartCell 20 | 21 | - (void)awakeFromNib { 22 | [super awakeFromNib]; 23 | // Initialization code 24 | 25 | } 26 | 27 | - (void)setItem:(ShoppingCartItem *)item { 28 | _item = item; 29 | self.foodNmaeLabel.text = item.foodName; 30 | self.priceLabel.text = [self finallyFoodPrice:item.price]; 31 | } 32 | 33 | - (IBAction)reduce:(UIButton *)sender { 34 | NSInteger i = [self.countLabel.text integerValue]; 35 | i--; 36 | if (i < 1) { 37 | i = 1; 38 | } else { 39 | self.item.price = self.item.price - self.item.price / (i+1); 40 | } 41 | self.countLabel.text = [NSString stringWithFormat:@"%zd",i]; 42 | self.priceLabel.text = [self finallyFoodPrice:self.item.price]; 43 | 44 | } 45 | 46 | - (IBAction)add:(UIButton *)sender { 47 | NSInteger i = [self.countLabel.text integerValue]; 48 | i++; 49 | self.item.price = self.item.price + self.item.price / (i-1); 50 | self.countLabel.text = [NSString stringWithFormat:@"%zd",i]; 51 | self.priceLabel.text = [self finallyFoodPrice:self.item.price]; 52 | } 53 | 54 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 55 | [super setSelected:selected animated:animated]; 56 | 57 | // Configure the view for the selected state 58 | } 59 | 60 | // 最终的价格 61 | - (NSString *)finallyFoodPrice:(float)price { 62 | 63 | // 新价格保留maxDecimalPlaces为位小数转成字符串 64 | NSString *priceString = [NSString stringWithFormat:@"%.5f",price]; 65 | // 通过小数点进行分割,然后取小数部分 66 | NSArray *parts = [priceString componentsSeparatedByString:@"."]; 67 | if (parts.count > 1) { 68 | // 取小数部分 69 | NSString *dot = parts[1]; 70 | 71 | if ([dot hasSuffix:@"00000"]) { 72 | return [NSString stringWithFormat:@"¥%.0f",price]; 73 | } else if ([dot hasSuffix:@"0000"]) { 74 | return [NSString stringWithFormat:@"¥%.1f",price]; 75 | } else if ([dot hasSuffix:@"000"]) { 76 | return [NSString stringWithFormat:@"¥%.2f",price]; 77 | } else if ([dot hasSuffix:@"00"]) { 78 | return [NSString stringWithFormat:@"¥%.3f",price]; 79 | } else if ([dot hasSuffix:@"0"]) { 80 | return [NSString stringWithFormat:@"¥%.4f",price]; 81 | } else { 82 | return priceString; 83 | } 84 | } 85 | return nil; 86 | } 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 35 | 44 | 51 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCartItem.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ShoppingCartItem : NSObject 12 | @property (nonatomic, copy) NSString *foodName; 13 | @property (nonatomic, assign) double price; 14 | @end 15 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCartItem.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "ShoppingCartItem.h" 10 | 11 | @implementation ShoppingCartItem 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCartView.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ShoppingCartView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView3/ShoppingCartView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ShoppingCartView.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/21. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "ShoppingCartView.h" 10 | #import "ShoppingCartCell.h" 11 | #import "ShoppingCartItem.h" 12 | #import "UIColor+DarkMode.h" 13 | 14 | @interface ShoppingCartView() 15 | @property (nonatomic, strong) UITableView *tableView; 16 | @property (nonatomic, strong) NSMutableArray *dataSource; 17 | @property (nonatomic, strong) UILabel *topLabel; 18 | @end 19 | 20 | @implementation ShoppingCartView 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame { 23 | if (self = [super initWithFrame:frame]) { 24 | 25 | [self initialize]; 26 | 27 | } 28 | return self; 29 | } 30 | 31 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 32 | if (self = [super initWithCoder:aDecoder]) { 33 | [self initialize]; 34 | } 35 | return self; 36 | } 37 | 38 | - (void)initialize { 39 | 40 | self.backgroundColor = [UIColor colorPairsWithLightColor:[UIColor colorWithRed:244.0 / 255.0 green:244.0 / 255.0 blue:244.0 / 255.0 alpha:1.0] 41 | darkColor:[UIColor colorWithRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0]]; 42 | 43 | [self addSubview:self.topLabel]; 44 | [self addSubview:self.tableView]; 45 | 46 | NSArray *dataArr = [self getData]; 47 | 48 | for (int i = 0; i < dataArr.count; i++) { 49 | ShoppingCartItem *item = [[ShoppingCartItem alloc] init]; 50 | [item setValuesForKeysWithDictionary:dataArr[i]]; 51 | [self.dataSource addObject:item]; 52 | } 53 | } 54 | 55 | - (void)hideTopView { 56 | 57 | } 58 | 59 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 60 | return self.dataSource.count; 61 | } 62 | 63 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 64 | 65 | ShoppingCartCell *cell = [tableView dequeueReusableCellWithIdentifier:@"shoppingCartCell" forIndexPath:indexPath]; 66 | cell.item = self.dataSource[indexPath.row]; 67 | return cell; 68 | 69 | } 70 | 71 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 72 | return 50; 73 | } 74 | 75 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 76 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 77 | NSLog(@"----点到了cell"); 78 | } 79 | 80 | - (UITableView *)tableView { 81 | if (!_tableView) { 82 | _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 83 | _tableView.dataSource = self; 84 | _tableView.delegate = self; 85 | _tableView.showsVerticalScrollIndicator = NO; 86 | [_tableView registerNib:[UINib nibWithNibName:NSStringFromClass([ShoppingCartCell class]) bundle:nil] forCellReuseIdentifier:@"shoppingCartCell"]; 87 | } 88 | return _tableView; 89 | } 90 | 91 | - (UILabel *)topLabel { 92 | if (!_topLabel) { 93 | _topLabel = [[UILabel alloc] init]; 94 | _topLabel.textAlignment = NSTextAlignmentCenter; 95 | _topLabel.text = @"购物车"; 96 | } 97 | return _topLabel; 98 | } 99 | 100 | - (NSMutableArray *)dataSource { 101 | 102 | if (!_dataSource) { 103 | _dataSource = [NSMutableArray array]; 104 | } 105 | return _dataSource; 106 | } 107 | 108 | - (void)layoutSubviews { 109 | [super layoutSubviews]; 110 | 111 | CGFloat topLabelY = 0.; 112 | if (@available(iOS 11.0, *)) { 113 | topLabelY = self.safeAreaInsets.top; 114 | } else { 115 | topLabelY = 20; 116 | } 117 | self.topLabel.frame = CGRectMake(0, topLabelY, self.bounds.size.width, 44); 118 | CGFloat tableViewY = CGRectGetMaxY(self.topLabel.frame); 119 | self.tableView.frame = CGRectMake(0, tableViewY, self.frame.size.width, self.frame.size.height-tableViewY); 120 | 121 | } 122 | 123 | - (NSArray *)getData { 124 | NSArray *dataArr = @[@{ 125 | @"foodName":@"鱼香肉丝", 126 | @"price":@(21.5), 127 | }, 128 | @{ 129 | @"foodName":@"辣椒炒肉", 130 | @"price":@(18), 131 | }, 132 | @{ 133 | @"foodName":@"梅干菜", 134 | @"price":@(20.1), 135 | }, 136 | @{ 137 | @"foodName":@"西红柿蛋汤", 138 | @"price":@(12.306), 139 | }, 140 | @{ 141 | @"foodName":@"红烧鲫鱼", 142 | @"price":@(35.8), 143 | }, 144 | @{ 145 | @"foodName":@"啤酒鸭", 146 | @"price":@(29), 147 | }, 148 | @{ 149 | @"foodName":@"宫爆鸡丁", 150 | @"price":@(28), 151 | }, 152 | @{ 153 | @"foodName":@"湖南一碗香", 154 | @"price":@(37.5), 155 | }, 156 | @{ 157 | @"foodName":@"鸡汤", 158 | @"price":@(16), 159 | }, 160 | @{ 161 | @"foodName":@"鸽子汤", 162 | @"price":@(18.5), 163 | }, 164 | @{ 165 | @"foodName":@"王老吉", 166 | @"price":@(8), 167 | }, 168 | @{ 169 | @"foodName":@"米饭", 170 | @"price":@(2), 171 | }, 172 | ]; 173 | 174 | return dataArr; 175 | } 176 | 177 | @end 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView4/CommodityListView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommodityListView.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/22. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CommodityListView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView4/CommodityListView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CommodityListView.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 17/10/22. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "CommodityListView.h" 10 | #import "UIColor+DarkMode.h" 11 | 12 | @interface CommodityListView() 13 | @property (nonatomic, weak) UIScrollView *scrollView; 14 | @property (nonatomic, strong) NSMutableArray *imageViews; 15 | @end 16 | 17 | @implementation CommodityListView 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame { 20 | if (self = [super initWithFrame:frame]) { 21 | [self initialize]; 22 | } 23 | return self; 24 | } 25 | 26 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 27 | if (self = [super initWithCoder:aDecoder]) { 28 | [self initialize]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)initialize { 34 | 35 | self.backgroundColor = [UIColor alertBackgroundColor]; 36 | 37 | NSArray *images = @[@"image0.jpg",@"image1.jpg",@"image2.jpg",@"image3.jpg",@"image4.jpg",@"image5.jpg",@"image6.jpg",@"image7.jpg",@"image8.jpg",@"image9.jpg"]; 38 | 39 | UIScrollView *scrollView = [[UIScrollView alloc] init]; 40 | scrollView.backgroundColor = [UIColor alertBackgroundColor]; 41 | scrollView.showsVerticalScrollIndicator = NO; 42 | [self addSubview:scrollView]; 43 | _scrollView = scrollView; 44 | 45 | for (int i = 0; i < images.count; i++) { 46 | UIImageView *imageView = [[UIImageView alloc] init]; 47 | imageView.image = [UIImage imageNamed:images[i]]; 48 | imageView.backgroundColor = [UIColor redColor]; 49 | [scrollView addSubview:imageView]; 50 | [self.imageViews addObject:imageView]; 51 | } 52 | } 53 | 54 | - (NSMutableArray *)imageViews { 55 | 56 | if (!_imageViews) { 57 | _imageViews = [NSMutableArray array]; 58 | 59 | } 60 | return _imageViews; 61 | } 62 | 63 | 64 | - (void)layoutSubviews { 65 | [super layoutSubviews]; 66 | self.scrollView.frame = self.bounds; 67 | 68 | CGFloat imageViewW = self.bounds.size.width/2-20; 69 | CGFloat imageViewH = self.bounds.size.height; 70 | CGFloat imageViewY = 0; 71 | if (@available(iOS 11.0, *)) { 72 | imageViewY = self.safeAreaInsets.top; 73 | } 74 | UIImageView *lastImageView; 75 | for (int i = 0; i < self.imageViews.count; i++) { 76 | UIImageView *imageView = self.imageViews[i]; 77 | imageView.frame = CGRectMake((imageViewW +10) * i, imageViewY, imageViewW, imageViewH); 78 | if (i == self.imageViews.count-1) { 79 | lastImageView = imageView; 80 | } 81 | } 82 | self.scrollView.contentSize = CGSizeMake(CGRectGetMaxX(lastImageView.frame), 0); 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView5/PickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PickerView.h 3 | // SPAlertController 4 | // 5 | // Created by Libo on 2017/11/15. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PickerView : UIView 12 | 13 | @property (nonatomic, copy) void(^cancelClickedBlock)(void); 14 | @property (nonatomic, copy) void(^doneClickedBlock)(void); 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView5/PickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyTitleView.m 3 | // SPAlertController 4 | // 5 | // Created by Libo on 2017/11/5. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "PickerView.h" 10 | #import "UIColor+DarkMode.h" 11 | 12 | @interface PickerView() 13 | 14 | @property (nonatomic, strong) UIPickerView *pickerView; 15 | @property (nonatomic, strong) UIToolbar *toolbar; 16 | 17 | @end 18 | 19 | @implementation PickerView 20 | 21 | - (instancetype)initWithFrame:(CGRect)frame { 22 | if (self = [super initWithFrame:frame]) { 23 | [self initialize]; 24 | } 25 | return self; 26 | } 27 | 28 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 29 | if (self = [super initWithCoder:aDecoder]) { 30 | [self initialize]; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)initialize { 36 | [self addSubview:self.toolbar]; 37 | [self addSubview:self.pickerView]; 38 | } 39 | 40 | - (void)doneClick { 41 | if (self.doneClickedBlock) { 42 | self.doneClickedBlock(); 43 | } 44 | } 45 | 46 | - (void)cancelClick { 47 | if (self.cancelClickedBlock) { 48 | self.cancelClickedBlock(); 49 | } 50 | } 51 | 52 | - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 53 | return 1; 54 | } 55 | 56 | - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 57 | return 2; 58 | } 59 | 60 | - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 61 | return @[@"男",@"女"][row]; 62 | } 63 | 64 | - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 65 | UILabel *pickerLabel = (UILabel *)view; 66 | if (!pickerLabel) { 67 | pickerLabel = [[UILabel alloc] init]; 68 | pickerLabel.adjustsFontSizeToFitWidth = YES; 69 | pickerLabel.textAlignment = NSTextAlignmentCenter; 70 | [pickerLabel setFont:[UIFont boldSystemFontOfSize:18]]; 71 | } 72 | pickerLabel.text = [self pickerView:pickerView titleForRow:row forComponent:component]; 73 | return pickerLabel; 74 | } 75 | 76 | - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { 77 | return 50; 78 | } 79 | 80 | - (UIPickerView *)pickerView { 81 | if (!_pickerView) { 82 | _pickerView = [[UIPickerView alloc] init]; 83 | _pickerView.delegate = self; 84 | _pickerView.dataSource = self; 85 | _pickerView.backgroundColor = [UIColor colorPairsWithLightColor:[UIColor colorWithRed:239.0 / 255.0 green:239.0 / 255.0 blue:239.0 / 255.0 alpha:1.0] darkColor:[UIColor colorWithRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0]]; 86 | } 87 | return _pickerView; 88 | } 89 | 90 | - (UIToolbar *)toolbar { 91 | 92 | if (!_toolbar) { 93 | UIBarButtonItem *doneBBI = [[UIBarButtonItem alloc] 94 | initWithTitle:@"确定" 95 | style:UIBarButtonItemStyleDone 96 | target:self 97 | action:@selector(doneClick)]; 98 | 99 | UIBarButtonItem *cancelBBI = [[UIBarButtonItem alloc] initWithTitle:@"取消" style:UIBarButtonItemStylePlain target:self action:@selector(cancelClick)]; 100 | UIBarButtonItem *flexibleBBI = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 101 | _toolbar = [[UIToolbar alloc] init]; 102 | // 设置tollbar的背景色 103 | _toolbar.barTintColor = [UIColor alertBackgroundColor]; 104 | NSArray *toolbarItems = [NSArray arrayWithObjects:cancelBBI, flexibleBBI, doneBBI, nil]; 105 | [_toolbar setItems:toolbarItems]; 106 | } 107 | return _toolbar; 108 | } 109 | 110 | - (void)layoutSubviews { 111 | [super layoutSubviews]; 112 | self.toolbar.frame = CGRectMake(0, 0, self.bounds.size.width, 40); 113 | self.pickerView.frame = CGRectMake(0, CGRectGetMaxY(self.toolbar.frame), self.bounds.size.width, self.bounds.size.height-40); 114 | } 115 | 116 | @end 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView6/MyCenterView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyCenterView.h 3 | // SPAlertController 4 | // 5 | // Created by Libo on 2017/11/5. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MyCenterView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView6/MyCenterView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyCenterView.m 3 | // SPAlertController 4 | // 5 | // Created by Libo on 2017/11/5. 6 | // Copyright © 2017年 iDress. All rights reserved. 7 | // 8 | 9 | #import "MyCenterView.h" 10 | 11 | @interface MyCenterView() 12 | @property (nonatomic, strong) UITableView *tableView; 13 | 14 | @end 15 | 16 | @implementation MyCenterView 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame { 19 | if (self = [super initWithFrame:frame]) { 20 | [self initialize]; 21 | } 22 | return self; 23 | } 24 | 25 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 26 | if (self = [super initWithCoder:aDecoder]) { 27 | [self initialize]; 28 | } 29 | return self; 30 | } 31 | 32 | - (void)initialize { 33 | [self addSubview:self.tableView]; 34 | } 35 | 36 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 37 | return 10; 38 | } 39 | 40 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 41 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myCell"]; 42 | if (cell == nil) { 43 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"myCell"]; 44 | } 45 | cell.textLabel.text = [NSString stringWithFormat:@"第%zd行",indexPath.row]; 46 | cell.textLabel.font = [UIFont systemFontOfSize:14]; 47 | cell.detailTextLabel.text = @"这是自定义tableView"; 48 | cell.detailTextLabel.font = [UIFont systemFontOfSize:12]; 49 | return cell; 50 | } 51 | 52 | - (UITableView *)tableView { 53 | 54 | if (!_tableView) { 55 | _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; 56 | _tableView.dataSource = self; 57 | _tableView.delegate = self; 58 | } 59 | return _tableView; 60 | } 61 | 62 | - (void)layoutSubviews { 63 | [super layoutSubviews]; 64 | self.tableView.frame = self.bounds; 65 | } 66 | 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView7/PopView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PopView.h 3 | // SPAlertController 4 | // 5 | // Created by Libo on 2018/12/23. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface PopView : UIView 14 | 15 | - (instancetype)initWithImages:(NSArray *)images 16 | titles:(NSArray *)titles 17 | clickedButtonBlock:(void(^)(NSInteger index))clickedButtonBlock 18 | cancelBlock:(void(^)(PopView *popView))cancelBlock; 19 | 20 | @property (nonatomic, copy) void(^tapBackgroundBlock)(PopView *popView); 21 | 22 | - (void)open; 23 | 24 | - (void)close; 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView7/PopView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PopView.m 3 | // SPAlertController 4 | // 5 | // Created by Libo on 2018/12/23. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import "PopView.h" 10 | #import "SPButton.h" // SPButton的github地址:https://github.com/SPStore/SPButton 11 | 12 | static NSInteger const kColumnCount = 4; // 每一页的列数 13 | static NSInteger const kRowCount = 2; // 每一页的行数 14 | static CGFloat const kColSpacing = 15; // 列间距 15 | static CGFloat const kRowSpacing = 20; // 行间距 16 | static NSTimeInterval kAnimationDuration = 0.7; // 动画总时长 17 | static NSTimeInterval kDelay = 0.0618; // 按钮接着上一个按钮的延时时间 18 | 19 | @interface PopView() 20 | @property (nonatomic, strong) UIScrollView *scrollView; 21 | @property (nonatomic, strong) UIPageControl *pageControl; 22 | @property (nonatomic, strong) UIButton *cancelButton; 23 | @property (nonatomic, strong) UIView *line; 24 | @property (nonatomic, copy) void (^clickedButtonBlock)(NSInteger); 25 | @property (nonatomic, copy) void (^cancelBlock)(PopView *popView); 26 | @end 27 | 28 | @implementation PopView 29 | { 30 | NSInteger buttonCount; 31 | } 32 | 33 | - (instancetype)initWithImages:(NSArray *)images 34 | titles:(NSArray *)titles 35 | clickedButtonBlock:(void (^)(NSInteger))clickedButtonBlock 36 | cancelBlock:(void (^)(PopView *popView))cancelBlock { 37 | 38 | _clickedButtonBlock = clickedButtonBlock; 39 | _cancelBlock = cancelBlock; 40 | 41 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)]; 42 | [self addGestureRecognizer:tap]; 43 | 44 | CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; 45 | CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; 46 | 47 | if (self = [self initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight)]) { 48 | buttonCount = MIN(images.count, titles.count); 49 | for (int i = 0; i < buttonCount; i++) { 50 | SPButton *button = [[SPButton alloc] initWithImagePosition:SPButtonImagePositionTop]; 51 | [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal]; 52 | [button setTitle:titles[i] forState:UIControlStateNormal]; 53 | button.titleLabel.font = [UIFont systemFontOfSize:14]; 54 | [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; 55 | button.imageView.contentMode = UIViewContentModeScaleAspectFit; 56 | button.imageTitleSpace = 5; 57 | [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; 58 | button.tag = i+100; 59 | [self.scrollView addSubview:button]; 60 | } 61 | } 62 | return self; 63 | } 64 | 65 | - (instancetype)initWithFrame:(CGRect)frame { 66 | if (self = [super initWithFrame:frame]) { 67 | 68 | } 69 | return self; 70 | } 71 | 72 | - (void)open { 73 | 74 | for (int i = 0; i < buttonCount; i++) { 75 | SPButton *button = [self.scrollView viewWithTag:i + 100]; 76 | CGFloat buttonH = button.bounds.size.height; 77 | CGFloat totalH = (buttonH * kRowCount + kRowSpacing * (kRowCount - 1)); 78 | CGFloat buttonEndY = button.frame.origin.y - totalH - buttonH; 79 | // delay参数计算出来的意思是:每一列比它的上一列延时kDelay秒 80 | [UIView animateWithDuration:kAnimationDuration 81 | delay:i % kColumnCount * kDelay 82 | usingSpringWithDamping:0.6 83 | initialSpringVelocity:0 84 | options:UIViewAnimationOptionCurveEaseIn animations:^{ 85 | CGRect buttonFrame = button.frame; 86 | buttonFrame.origin.y = buttonEndY; 87 | button.frame = buttonFrame; 88 | } completion:^(BOOL finished) { 89 | }]; 90 | } 91 | } 92 | 93 | - (void)close { 94 | for (int i = 0; i < buttonCount; i++) { 95 | SPButton *button = [self.scrollView viewWithTag:i+100]; 96 | CGFloat buttonH = button.bounds.size.height; 97 | CGFloat totalH = (buttonH * kRowCount + kRowSpacing * (kRowCount - 1)); 98 | CGFloat buttonBeginY = button.frame.origin.y + buttonH + totalH; 99 | 100 | // delay参数计算出来的意思是:第一行每个按钮都比第二行的每个按钮延时0.1秒,同时每列比它的下一列延时kDelay秒 101 | [UIView animateWithDuration:kAnimationDuration 102 | delay:(1 - i / kColumnCount) / 10.0 + (kDelay * kColumnCount - i % kColumnCount * kDelay - kDelay) 103 | usingSpringWithDamping:0.6 104 | initialSpringVelocity:0 105 | options:UIViewAnimationOptionCurveEaseOut animations:^{ 106 | CGRect buttonFrame = button.frame; 107 | buttonFrame.origin.y = buttonBeginY; 108 | button.frame = buttonFrame; 109 | } completion:^(BOOL finished) { 110 | [self removeFromSuperview]; 111 | }]; 112 | } 113 | } 114 | 115 | - (void)buttonAction:(UIButton *)sender { 116 | if (self.clickedButtonBlock) { 117 | self.clickedButtonBlock(sender.tag-100); 118 | } 119 | } 120 | 121 | - (void)tapAction { 122 | if (self.tapBackgroundBlock) { 123 | self.tapBackgroundBlock(self); 124 | } 125 | } 126 | 127 | - (void)cancelButtonAction { 128 | if (self.cancelBlock) { 129 | self.cancelBlock(self); 130 | } 131 | } 132 | 133 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 134 | CGFloat offsetX = scrollView.contentOffset.x; 135 | self.pageControl.currentPage = (NSInteger)(offsetX / self.bounds.size.width + 0.5); 136 | } 137 | 138 | - (void)layoutSubviews { 139 | [super layoutSubviews]; 140 | 141 | CGFloat bottom = 0; 142 | if (@available(iOS 11.0, *)) { 143 | bottom = self.safeAreaInsets.bottom; 144 | } 145 | 146 | CGFloat superWidth = self.frame.size.width; 147 | CGFloat superHeight = self.frame.size.height; 148 | 149 | CGFloat cancelButtonW = superWidth; 150 | CGFloat cancelButtonH = 40; 151 | CGFloat cancelButtonX = 0; 152 | CGFloat cancelButtonY = superHeight-cancelButtonH-bottom; 153 | self.cancelButton.frame = CGRectMake(cancelButtonX, cancelButtonY, cancelButtonW, cancelButtonH); 154 | 155 | CGFloat lineW = superWidth; 156 | CGFloat lineH = 1.0/[UIScreen mainScreen].scale; 157 | CGFloat lineX = 0; 158 | CGFloat lineY = superHeight-cancelButtonH-lineH-bottom; 159 | self.line.frame = CGRectMake(lineX, lineY, lineW, lineH); 160 | 161 | CGFloat scrollViewH = superHeight-cancelButtonH-lineH-bottom; 162 | self.scrollView.frame = CGRectMake(0, 0, superWidth, scrollViewH); 163 | self.pageControl.frame = CGRectMake(0, superHeight-cancelButtonH-lineH-bottom-30, superWidth, 30); 164 | 165 | // 先计算好每个按钮的动画前的frame,等执行动画的时候只要改变y值即可 166 | NSInteger buttonCountEveryPage = kColumnCount * kRowCount; // 每一页的按钮个数 167 | NSInteger pageCount = (buttonCount-1) / buttonCountEveryPage + 1; // 总页数 168 | self.pageControl.numberOfPages = pageCount; 169 | 170 | for (int i = 0; i < buttonCount; i++) { 171 | SPButton *button = [self.scrollView viewWithTag:i+100]; 172 | NSInteger page = i / buttonCountEveryPage; // 第几页 173 | NSInteger row = (i - buttonCountEveryPage * page) / kColumnCount; // 第几页的第几行 174 | NSInteger col = i % kColumnCount; // 第几列 175 | CGFloat buttonW = (superWidth - kColSpacing * (kColumnCount + 1)) / kColumnCount; 176 | CGFloat buttonH = MIN(buttonW, button.currentImage.size.width)+30; 177 | CGFloat buttonX = kColSpacing + (buttonW + kColSpacing) * col + page * superWidth; 178 | CGFloat buttonBeginY = scrollViewH + (buttonH + kRowSpacing) * row; 179 | button.frame = CGRectMake(buttonX, buttonBeginY, buttonW, buttonH); 180 | } 181 | self.scrollView.contentSize = CGSizeMake(superWidth * pageCount, 0); 182 | } 183 | 184 | - (UIScrollView *)scrollView { 185 | 186 | if (!_scrollView) { 187 | _scrollView = [[UIScrollView alloc] init]; 188 | _scrollView.showsVerticalScrollIndicator = NO; 189 | _scrollView.showsHorizontalScrollIndicator = NO; 190 | _scrollView.scrollsToTop = NO; 191 | _scrollView.bounces = NO; 192 | _scrollView.pagingEnabled = YES; 193 | _scrollView.delegate = self; 194 | [self addSubview:_scrollView]; 195 | } 196 | return _scrollView; 197 | } 198 | 199 | - (UIPageControl *)pageControl { 200 | if (!_pageControl) { 201 | _pageControl = [[UIPageControl alloc] init]; 202 | _pageControl.currentPageIndicatorTintColor = [UIColor orangeColor]; 203 | _pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; 204 | [self addSubview:_pageControl]; 205 | } 206 | return _pageControl; 207 | } 208 | 209 | - (UIButton *)cancelButton { 210 | 211 | if (!_cancelButton) { 212 | _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; 213 | _cancelButton.backgroundColor = [UIColor clearColor]; 214 | [_cancelButton setImage:[UIImage imageNamed:@"取消"] forState:UIControlStateNormal]; 215 | [_cancelButton addTarget:self action:@selector(cancelButtonAction) forControlEvents:UIControlEventTouchUpInside]; 216 | [self addSubview:_cancelButton]; 217 | } 218 | return _cancelButton; 219 | } 220 | 221 | - (UIView *)line { 222 | 223 | if (!_line) { 224 | _line = [[UIView alloc] init]; 225 | _line.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3]; 226 | [self addSubview:_line]; 227 | } 228 | return _line; 229 | } 230 | 231 | @end 232 | -------------------------------------------------------------------------------- /Example/SPAlertController/CustomViews/CustomView7/SPButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPButton.h 3 | // SPButton 4 | // 5 | // Created by 乐升平 on 2018/11/20. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // github:https://github.com/SPStore/SPButton 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | 14 | typedef NS_ENUM(NSInteger, SPButtonImagePosition) { 15 | SPButtonImagePositionLeft = 0, // 图片在文字左侧 16 | SPButtonImagePositionRight = 1, // 图片在文字右侧 17 | SPButtonImagePositionTop = 2, // 图片在文字上侧 18 | SPButtonImagePositionBottom = 3 // 图片在文字下侧 19 | }; 20 | 21 | IB_DESIGNABLE 22 | @interface SPButton : UIButton 23 | 24 | - (instancetype)initWithImagePosition:(SPButtonImagePosition)imagePosition; 25 | 26 | #if TARGET_INTERFACE_BUILDER // storyBoard/xib中设置 27 | @property (nonatomic,assign) IBInspectable NSInteger imagePosition; // 图片位置 28 | @property (nonatomic, assign) IBInspectable CGFloat imageTitleSpace; // 图片和文字之间的间距 29 | #else // 纯代码设置 30 | @property (nonatomic) SPButtonImagePosition imagePosition; // 图片位置 31 | @property (nonatomic, assign) CGFloat imageTitleSpace; // 图片和文字之间的间距 32 | #endif 33 | 34 | 35 | @end 36 | 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image0.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image1.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image2.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image3.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image4.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image5.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image6.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image7.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image8.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/image9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/image9.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/send0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/send0.jpeg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/send1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/send1.jpeg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/背景1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/背景1.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/Images/背景2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Example/SPAlertController/Images/背景2.jpg -------------------------------------------------------------------------------- /Example/SPAlertController/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 | $(MARKETING_VERSION) 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 | -------------------------------------------------------------------------------- /Example/SPAlertController/SPAlertController/SPAlertController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPAlertController.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 18/10/12. https://github.com/SPStore/SPAlertController 6 | // Copyright © 2018-2019 leshengping (lesp163@163.com). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef NS_ENUM(NSInteger, SPAlertControllerStyle) { 14 | SPAlertControllerStyleActionSheet = 0, // 从单侧弹出(顶/左/底/右) 15 | SPAlertControllerStyleAlert, // 从中间弹出 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, SPAlertAnimationType) { 19 | SPAlertAnimationTypeDefault = 0, // 默认动画,如果是SPAlertControllerStyleActionSheet样式,默认动画等效于SPAlertAnimationTypeFromBottom,如果是SPAlertControllerStyleAlert样式,默认动画等效于SPAlertAnimationTypeShrink 20 | SPAlertAnimationTypeFromBottom, // 从底部弹出 21 | SPAlertAnimationTypeFromTop, // 从顶部弹出 22 | SPAlertAnimationTypeFromRight, // 从右边弹出 23 | SPAlertAnimationTypeFromLeft, // 从左边弹出 24 | 25 | SPAlertAnimationTypeShrink, // 收缩动画 26 | SPAlertAnimationTypeExpand, // 发散动画 27 | SPAlertAnimationTypeFade, // 渐变动画 28 | 29 | SPAlertAnimationTypeNone, // 无动画 30 | SPAlertAnimationTypeAlpha NS_ENUM_DEPRECATED_IOS(8_0, 8_0, "Use SPAlertAnimationTypeFade instead"), // 渐变动画 31 | SPAlertAnimationTypeRaiseUp NS_ENUM_DEPRECATED_IOS(8_0, 8_0, "Use SPAlertAnimationTypeFromBottom instead"), // 从底部弹出 32 | SPAlertAnimationTypeDropDown NS_ENUM_DEPRECATED_IOS(8_0, 8_0, "Use SPAlertAnimationTypeFromTop instead"), // 从顶部弹出 33 | }; 34 | 35 | typedef NS_ENUM(NSInteger, SPAlertActionStyle) { 36 | SPAlertActionStyleDefault = 0, // 默认样式 37 | SPAlertActionStyleCancel, // 取消样式,字体加粗 38 | SPAlertActionStyleDestructive // 红色字体样式 39 | }; 40 | 41 | // ===================================================== SPAlertAction ===================================================== 42 | 43 | @interface SPAlertAction : NSObject 44 | 45 | + (instancetype)actionWithTitle:(nullable NSString *)title style:(SPAlertActionStyle)style handler:(void (^ __nullable)(SPAlertAction *action))handler; 46 | 47 | /** action的标题 */ 48 | @property(nullable, nonatomic, copy) NSString *title; 49 | /** action的富文本标题 */ 50 | @property(nullable, nonatomic, copy) NSAttributedString *attributedTitle; 51 | /** action的图标,位于title的左边 */ 52 | @property(nullable, nonatomic, copy) UIImage *image; 53 | /** title跟image之间的间距 */ 54 | @property (nonatomic, assign) CGFloat imageTitleSpacing; 55 | /** 渲染颜色,当外部的图片使用了UIImageRenderingModeAlwaysTemplate时,使用该属性可改变图片的颜色 */ 56 | @property (nonatomic, strong) UIColor *tintColor; 57 | /** 是否能点击,默认为YES */ 58 | @property(nonatomic, getter=isEnabled) BOOL enabled; 59 | /** action的标题颜色,这个颜色只是普通文本的颜色,富文本颜色需要用NSForegroundColorAttributeName */ 60 | @property(nonatomic, strong) UIColor *titleColor; 61 | /** action的标题字体,如果文字太长显示不全,会自动改变字体自适应按钮宽度,最多压缩文字为原来的0.5倍封顶 */ 62 | @property(nonatomic, strong) UIFont *titleFont; 63 | /** action的标题的内边距,如果在不改变字体的情况下想增大action的高度,可以设置该属性的top和bottom值,默认UIEdgeInsetsMake(0, 15, 0, 15) */ 64 | @property(nonatomic, assign) UIEdgeInsets titleEdgeInsets; 65 | 66 | /** 样式 */ 67 | @property(nonatomic, readonly) SPAlertActionStyle style; 68 | 69 | @end 70 | 71 | // ===================================================== SPAlertController ===================================================== 72 | 73 | @protocol SPAlertControllerDelegate; 74 | @interface SPAlertController : UIViewController 75 | 76 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle; 77 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 78 | 79 | - (void)addAction:(SPAlertAction *)action; 80 | @property (nonatomic, readonly) NSArray *actions; 81 | 82 | /* 添加文本输入框 83 | * 一旦添加后就会回调一次(仅回调一次,因此可以在这个block块里面自由定制textFiled,如设置textField的属性,设置代理,添加addTarget,监听通知等); 84 | */ 85 | - (void)addTextFieldWithConfigurationHandler:(void (^ __nullable)(UITextField *textField))configurationHandler; 86 | @property(nullable, nonatomic, readonly) NSArray *textFields; 87 | 88 | /** 主标题 */ 89 | @property(nullable, nonatomic, copy) NSString *title; 90 | /** 副标题 */ 91 | @property(nullable, nonatomic, copy) NSString *message; 92 | /** 主标题(富文本) */ 93 | @property(nullable, nonatomic, copy) NSAttributedString *attributedTitle; 94 | /** 副标题(富文本) */ 95 | @property(nullable, nonatomic, copy) NSAttributedString *attributedMessage; 96 | /** 头部图标,位置处于title之上,大小取决于图片本身大小 */ 97 | @property(nullable,nonatomic, copy) UIImage *image; 98 | 99 | /** 主标题颜色 */ 100 | @property(nonatomic, strong) UIColor *titleColor; 101 | /** 主标题字体,默认18,加粗 */ 102 | @property(nonatomic, strong) UIFont *titleFont; 103 | /** 副标题颜色 */ 104 | @property(nonatomic, strong) UIColor *messageColor; 105 | /** 副标题字体,默认16,未加粗 */ 106 | @property(nonatomic, strong) UIFont *messageFont; 107 | /** 对齐方式(包括主标题和副标题) */ 108 | @property(nonatomic, assign) NSTextAlignment textAlignment; 109 | /** 头部图标的限制大小,默认无穷大 */ 110 | @property (nonatomic, assign) CGSize imageLimitSize; 111 | /** 图片的tintColor,当外部的图片使用了UIImageRenderingModeAlwaysTemplate时,该属性可起到作用 */ 112 | @property (nonatomic, strong) UIColor *imageTintColor; 113 | 114 | /* 115 | * action水平排列还是垂直排列 116 | * actionSheet样式下:默认为UILayoutConstraintAxisVertical(垂直排列), 如果设置为UILayoutConstraintAxisHorizontal(水平排列),则除去取消样式action之外的其余action将水平排列 117 | * alert样式下:当actions的个数大于2,或者某个action的title显示不全时为UILayoutConstraintAxisVertical(垂直排列),否则默认为UILayoutConstraintAxisHorizontal(水平排列),此样式下设置该属性可以修改所有action的排列方式 118 | * 不论哪种样式,只要外界设置了该属性,永远以外界设置的优先 119 | */ 120 | @property(nonatomic) UILayoutConstraintAxis actionAxis; 121 | 122 | /* 距离屏幕边缘的最小间距 123 | * alert样式下该属性是指对话框四边与屏幕边缘之间的距离,此样式下默认值随设备变化,actionSheet样式下是指弹出边的对立边与屏幕之间的距离,比如如果从右边弹出,那么该属性指的就是对话框左边与屏幕之间的距离,此样式下默认值为70 124 | */ 125 | @property(nonatomic, assign) CGFloat minDistanceToEdges; 126 | 127 | /** SPAlertControllerStyleAlert样式下默认6.0f,SPAlertControllerStyleActionSheet样式下默认13.0f,去除半径设置为0即可 */ 128 | @property(nonatomic, assign) CGFloat cornerRadius; 129 | 130 | /** 对话框的偏移量,y值为正向下偏移,为负向上偏移;x值为正向右偏移,为负向左偏移,该属性只对SPAlertControllerStyleAlert样式有效,键盘的frame改变会自动偏移,如果手动设置偏移只会取手动设置的 */ 131 | @property(nonatomic, assign) CGPoint offsetForAlert; 132 | /** 设置alert样式下的偏移量,动画为NO则跟属性offsetForAlert等效 */ 133 | - (void)setOffsetForAlert:(CGPoint)offsetForAlert animated:(BOOL)animated; 134 | 135 | /** 是否需要对话框拥有毛玻璃,默认为YES */ 136 | @property(nonatomic, assign) BOOL needDialogBlur; 137 | 138 | /** 是否单击背景退出对话框,默认为YES */ 139 | @property(nonatomic, assign) BOOL tapBackgroundViewDismiss; 140 | 141 | @property(nonatomic, weak) id delegate; 142 | 143 | @property(nonatomic, readonly) SPAlertControllerStyle preferredStyle; 144 | @property(nonatomic, readonly) SPAlertAnimationType animationType; 145 | 146 | /** 设置action与下一个action之间的间距, action仅限于非取消样式,必须在'-addAction:'之后设置,iOS11或iOS11以上才能使用 */ 147 | - (void)setCustomSpacing:(CGFloat)spacing afterAction:(SPAlertAction *)action API_AVAILABLE(ios(11.0)); 148 | - (CGFloat)customSpacingAfterAction:(SPAlertAction *)action API_AVAILABLE(ios(11.0)); 149 | 150 | /** 设置蒙层的外观样式,可通过alpha调整透明度 */ 151 | - (void)setBackgroundViewAppearanceStyle:(UIBlurEffectStyle)style alpha:(CGFloat)alpha; 152 | 153 | // 插入一个组件view,位置处于头部和action部分之间,要求头部和action部分同时存在 154 | - (void)insertComponentView:(nonnull UIView *)componentView; 155 | 156 | 157 | // ---------------------------------------------- custom ----------------------------------------------------- 158 | /** 159 | 创建控制器(自定义整个对话框) 160 | 161 | @param customAlertView 整个对话框的自定义view 162 | @param preferredStyle 对话框样式 163 | @param animationType 动画类型 164 | @return 控制器对象 165 | */ 166 | + (instancetype)alertControllerWithCustomAlertView:(nonnull UIView *)customAlertView preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 167 | /** 168 | 创建控制器(自定义对话框的头部) 169 | 170 | @param customHeaderView 头部自定义view 171 | @param preferredStyle 对话框样式 172 | @param animationType 动画类型 173 | @return 控制器对象 174 | */ 175 | + (instancetype)alertControllerWithCustomHeaderView:(nonnull UIView *)customHeaderView preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 176 | /** 177 | 创建控制器(自定义对话框的action部分) 178 | 179 | @param customActionSequenceView action部分的自定义view 180 | @param title 大标题 181 | @param message 副标题 182 | @param preferredStyle 对话框样式 183 | @param animationType 动画类型 184 | @return 控制器对象 185 | */ 186 | + (instancetype)alertControllerWithCustomActionSequenceView:(nonnull UIView *)customActionSequenceView title:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 187 | 188 | /** 更新自定义view的size,比如屏幕旋转,自定义view的大小发生了改变,可通过该方法更新size */ 189 | - (void)updateCustomViewSize:(CGSize)size; 190 | 191 | @property(nonatomic, assign) CGFloat cornerRadiusForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use cornerRadius instead"); 192 | @property (nonatomic, assign) CGFloat maxTopMarginForActionSheet NS_DEPRECATED_IOS(8_0, 8_0,"Use minDistanceToEdges instead"); 193 | @property(nonatomic, assign) CGFloat maxMarginForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use minDistanceToEdges instead"); 194 | @property(nonatomic, assign) NSInteger maxNumberOfActionHorizontalArrangementForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use actionAxis instead"); 195 | @property(nonatomic, assign) CGFloat offsetYForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use offsetForAlert instead"); 196 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customView:(nullable UIView *)customView NS_DEPRECATED_IOS(8_0, 8_0,"Use +alertControllerWithCustomAlertView:preferredStyle:animationType:"); 197 | + (instancetype)alertControllerWithPreferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customHeaderView:(nullable UIView *)customHeaderView NS_DEPRECATED_IOS(8_0, 8_0,"Use +alertControllerWithCustomHeaderView:preferredStyle:animationType:"); 198 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customCenterView:(nullable UIView *)customCenterView NS_DEPRECATED_IOS(8_0, 8_0,"Use -insertComponentView:"); 199 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customFooterView:(nullable UIView *)customFooterView NS_DEPRECATED_IOS(8_0, 8_0,"Use +alertControllerWithCustomActionSequenceView:title:message:preferredStyle:animationType:"); 200 | @end 201 | 202 | @protocol SPAlertControllerDelegate 203 | @optional; 204 | - (void)willPresentAlertController:(SPAlertController *)alertController; // 将要present 205 | - (void)didPresentAlertController:(SPAlertController *)alertController; // 已经present 206 | - (void)willDismissAlertController:(SPAlertController *)alertController; // 将要dismiss 207 | - (void)didDismissAlertController:(SPAlertController *)alertController; // 已经dismiss 208 | 209 | 210 | - (void)sp_alertControllerWillShow:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -willPresentAlertController:"); 211 | - (void)sp_alertControllerDidShow:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -DidPresentAlertController:"); 212 | - (void)sp_alertControllerWillHide:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -willDismissAlertController:"); 213 | - (void)sp_alertControllerDidHide:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -DidDismissAlertController:"); 214 | @end 215 | 216 | @interface SPAlertPresentationController : UIPresentationController 217 | @end 218 | 219 | @interface SPAlertAnimation : NSObject 220 | + (instancetype)animationIsPresenting:(BOOL)presenting; 221 | @end 222 | 223 | NS_ASSUME_NONNULL_END 224 | -------------------------------------------------------------------------------- /Example/SPAlertController/UIColor+DarkMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+DarkMode.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2020/4/26. 6 | // Copyright © 2020 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface UIColor (DarkMode) 14 | 15 | + (UIColor *)alertBackgroundColor; 16 | 17 | /// 创建颜色对 18 | /// @param lightColor iOS13以下的系统显示的颜色或未开启深色模式下显示的颜色 19 | /// @param darkColor 深色模式下显示的颜色 20 | + (UIColor *) colorPairsWithLightColor:(UIColor *) lightColor darkColor:(UIColor *) darkColor; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /Example/SPAlertController/UIColor+DarkMode.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+DarkMode.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2020/4/26. 6 | // Copyright © 2020 乐升平. All rights reserved. 7 | // 8 | 9 | #import "UIColor+DarkMode.h" 10 | 11 | @implementation UIColor (DarkMode) 12 | 13 | + (UIColor *)alertBackgroundColor { 14 | return [self colorPairsWithLightColor:[[UIColor whiteColor] colorWithAlphaComponent:0.7] 15 | darkColor:[UIColor colorWithRed:44.0 / 255.0 green:44.0 / 255.0 blue:44.0 / 255.0 alpha:1.0]]; 16 | } 17 | 18 | + (UIColor *)colorPairsWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor { 19 | if (@available(iOS 13.0, *)) { 20 | return [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) { 21 | if(traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { 22 | return darkColor; 23 | } else { 24 | return lightColor; 25 | } 26 | }]; 27 | } else { 28 | return lightColor; 29 | } 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Example/SPAlertController/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/4. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/SPAlertControllerTests/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 | -------------------------------------------------------------------------------- /Example/SPAlertControllerTests/SPAlertControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPAlertControllerTests.m 3 | // SPAlertControllerTests 4 | // 5 | // Created by 乐升平 on 2018/12/4. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SPAlertControllerTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation SPAlertControllerTests 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 | -------------------------------------------------------------------------------- /Example/SPAlertControllerTests/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 2018/12/4. 6 | // Copyright © 2018 乐升平. 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 | -------------------------------------------------------------------------------- /Example/SPAlertControllerUITests/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 | -------------------------------------------------------------------------------- /Example/SPAlertControllerUITests/SPAlertControllerUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SPAlertControllerUITests.m 3 | // SPAlertControllerUITests 4 | // 5 | // Created by 乐升平 on 2018/12/4. 6 | // Copyright © 2018 乐升平. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SPAlertControllerUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation SPAlertControllerUITests 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 | -------------------------------------------------------------------------------- /Images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/.DS_Store -------------------------------------------------------------------------------- /Images/3006981-0b23494c3ba2a6fc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-0b23494c3ba2a6fc.jpg -------------------------------------------------------------------------------- /Images/3006981-3cd4a2b6ff4da206.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-3cd4a2b6ff4da206.jpg -------------------------------------------------------------------------------- /Images/3006981-41170beb443f32f0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-41170beb443f32f0.jpg -------------------------------------------------------------------------------- /Images/3006981-6f3752d49e579460.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-6f3752d49e579460.jpg -------------------------------------------------------------------------------- /Images/3006981-9544748007937417.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-9544748007937417.jpg -------------------------------------------------------------------------------- /Images/3006981-9ed0416190e155dc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-9ed0416190e155dc.jpg -------------------------------------------------------------------------------- /Images/3006981-a12eae25bc1061d6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-a12eae25bc1061d6.jpg -------------------------------------------------------------------------------- /Images/3006981-b35b79b657815756.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3006981-b35b79b657815756.jpg -------------------------------------------------------------------------------- /Images/3CB7E93FDA241F253BFE156D0B4AA7E2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/3CB7E93FDA241F253BFE156D0B4AA7E2.jpg -------------------------------------------------------------------------------- /Images/6AAAA07F90853F52CA6166D815F619A9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/6AAAA07F90853F52CA6166D815F619A9.jpg -------------------------------------------------------------------------------- /Images/F4FB539593B4CC499E65735E4F1E8227.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SPStore/SPAlertController/b472fd0338825b485c3b3d46cb68e5a2f0022414/Images/F4FB539593B4CC499E65735E4F1E8227.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2018-2019 leshengping (lesp163@163.com) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 重大更新:4.0.0版本适配深色模式 2 | # SPAlertController 3 | [![Build Status](http://img.shields.io/travis/SPStore/SPAlertController.svg?style=flat)](https://travis-ci.org/SPStore/SPAlertController) 4 | [![Pod Version](http://img.shields.io/cocoapods/v/SPAlertController.svg?style=flat)](http://cocoadocs.org/docsets/SPAlertController/) 5 | [![Pod Platform](http://img.shields.io/cocoapods/p/SPAlertController.svg?style=flat)](http://cocoadocs.org/docsets/SPAlertController/) 6 | ![Language](https://img.shields.io/badge/language-Object--C-ff69b4.svg) 7 | [![Pod License](http://img.shields.io/cocoapods/l/SPAlertController.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0.html) 8 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/SPStore/SPAlertController) 9 | # 目录 10 | * [CocoaPods](#CocoaPods)  11 | * [使用示例](#使用示例) 12 | * [API及属性详解](#API及属性详解) 13 | * [自定义View](#自定义View) 14 | * [深色模式预览](#深色模式预览) 15 | * [历史版本](#历史版本) 16 | 17 | ## 功能特点 18 | - [x] 采用VFL布局,3.0版本开始,核心控件为UIStackView,风格与微信几乎零误差 19 | - [x] 3.0版本开始,对话框头部新增图片设置 20 | - [x] 3.0版本开始,action支持图片设置 21 | - [x] 3.0版本开始,iOS11及其以上系统可单独设置指定action后的间距 22 | - [x] 3.0版本开始,支持富文本 23 | - [x] action的排列可灵活设置垂直排列和水平排列 24 | - [x] 每个action的高度自适应 25 | - [x] 支持旋转(横竖屏) 26 | - [x] 可以自定义各种UIView 27 | - [x] 支持对话框毛玻璃和背景蒙层毛玻璃 28 | - [x] 全面适配iPhoneX,iPhoneXR,iPhoneXS,iPhoneXS MAX 29 | - [x] 全面适配深色模式 30 | ## CocoaPods 31 | ##### 版本4.0.0 32 | ``` 33 | platform:ios,'9.0' 34 | target 'MyApp' do 35 | pod 'SPAlertController', '~> 4.0.0' 36 | end 37 | ``` 38 | 39 | ## 使用示例 40 | ``` 41 | SPAlertController *alert = [SPAlertController alertControllerWithTitle:@"我是主标题" message:@"我是副标题" preferredStyle:SPAlertControllerStyleActionSheet]; 42 | 43 | SPAlertAction *action1 = [SPAlertAction actionWithTitle:@"Default" style:SPAlertActionStyleDefault handler:^(SPAlertAction * _Nonnull action) {}]; 44 | SPAlertAction *action2 = [SPAlertAction actionWithTitle:@"Destructive" style:SPAlertActionStyleDestructive handler:^(SPAlertAction * _Nonnull action) {}]; 45 | SPAlertAction *action3 = [SPAlertAction actionWithTitle:@"Cancel" style:SPAlertActionStyleCancel handler:^(SPAlertAction * _Nonnull action) {}]; 46 | 47 | [alert addAction:action1]; 48 | [alert addAction:action2]; 49 | [alert addAction:action3]; 50 | [self presentViewController: alert animated:YES completion:^{}]; 51 | ``` 52 | 53 | ## API及属性详解 54 | ### 创建SPAlertController 55 | ``` 56 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle; 57 | ``` 58 | ``` 59 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 60 | ``` 61 | 上面2种创建方式唯一的区别就是:第2种方式多了一个animationType参数,该参数可以设置弹出动画。如果以第一种方式创建,会采用默认动画,默认动画跟preferredStyle 有关,如果是SPAlertControllerStyleActionSheet样式,默认动画为从底部弹出,如果是SPAlertControllerStyleAlert样式,默认动画为从中间弹出 62 | ### SPAlertController的头部配置 63 | * title,对话框的主标题 64 | * message,对话框的副标题 65 | * attributedTitle,对话框的主标题,富文本 66 | * attributedMessage,对话框的副标题,富文本 67 | * image,对话框的头部上的图标,位置处于主标题之上 68 | * titleColor,对话框主标题的颜色 69 | * titleFont,对话框主标题的字体 70 | * messageColor,对话框副标题的颜色 71 | * messageFont,对话框副标题的字体 72 | * textAlignment,对话框标题的对齐方式(标题指主标题和副标题) 73 | * imageLimitSize,对话框头部图标的限制大小,默认是无穷大 74 | 75 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/F4FB539593B4CC499E65735E4F1E8227.jpg) 76 | 77 | ### SPAlertController的action配置 78 | ``` 79 | // 添加action,actions里面存放的就是添加的所有action 80 | 81 | - (void)addAction:(SPAlertAction *)action; 82 | 83 | @property (nonatomic, readonly) NSArray *actions; 84 | ``` 85 | 86 | ``` 87 | // 添加文本输入框,textFields存放的就是添加的所有textField 88 | 89 | - (void)addTextFieldWithConfigurationHandler:(void (^ __nullable)(UITextField *textField))configurationHandler; 90 | 91 | @property(nullable, nonatomic, readonly) NSArray *textFields; 92 | ``` 93 | 94 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-9ed0416190e155dc.jpg) 95 | 96 | ``` 97 | // SPAlertControllerStyleActionSheet样式下:默认为UILayoutConstraintAxisVertical(垂直排列), 如果设置为UILayoutConstraintAxisHorizontal(水平排列),则除去取消样式action之外的其余action将水平排列;SPAlertControllerStyleAlert样式下:当actions的个数大于2,或者某个action的title显示不全时为UILayoutConstraintAxisVertical(垂直排列),否则默认为UILayoutConstraintAxisHorizontal(水平排列),此样式下设置该属性可以修改所有action的排列方式;不论哪种样式,只要外界设置了该属性,永远以外界设置的优先 98 | 99 | @property(nonatomic) UILayoutConstraintAxis actionAxis; 100 | ``` 101 | * SPAlertControllerStyleActionSheet样式下的垂直排列和水平排列 102 | 103 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-a12eae25bc1061d6.jpg) 104 | 105 | * SPAlertControllerStyleAlert样式下的垂直排列和水平排列 106 | 107 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-b35b79b657815756.jpg) 108 | 109 | ``` 110 | // 该属性配置的是距离屏幕边缘的最小间距;SPAlertControllerStyleAlert样式下该属性是指对话框四边与屏幕边缘之间的距离,此样式下默认值随设备变化,SPAlertControllerStyleActionSheet样式下是指弹出边的对立边与屏幕之间的距离,比如如果从右边弹出,那么该属性指的就是对话框左边与屏幕之间的距离,此样式下默认值为70 111 | 112 | @property(nonatomic, assign) CGFloat minDistanceToEdges; 113 | ``` 114 | * 图中红色画线都是指minDistanceToEdges 115 | 116 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-6f3752d49e579460.jpg) 117 | 118 | ``` 119 | // 该属性是制造对话框的毛玻璃效果,3.0版本开始采用的是系统私有类_UIDimmingKnockoutBackdropView所实现 120 | 121 | @property(nonatomic, assign) BOOL needDialogBlur; 122 | ``` 123 | ``` 124 | // SPAlertControllerStyleAlert下的偏移量配置 ,CGPoint类型,y值为正向下偏移,为负向上偏移;x值为正向右偏移,为负向左偏移,该属性只对SPAlertControllerStyleAlert样式有效,键盘的frame改变会自动偏移,如果外界手动设置偏移只会取手动设置的 125 | 126 | @property(nonatomic, assign) CGPoint offsetForAlert; 127 | 128 | - (void)setOffsetForAlert:(CGPoint)offsetForAlert animated:(BOOL)animated; 129 | ``` 130 | 131 | ``` 132 | // 该API是设置和获取指定action后面的间距,如图中箭头所指,iOS11及其以上才支持 133 | 134 | - (void)setCustomSpacing:(CGFloat)spacing afterAction:(SPAlertAction *)action API_AVAILABLE(ios(11.0)); 135 | 136 | - (CGFloat)customSpacingAfterAction:(SPAlertAction *)action API_AVAILABLE(ios(11.0)); 137 | ``` 138 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3CB7E93FDA241F253BFE156D0B4AA7E2.jpg) 139 | 140 | ``` 141 | // 该API是设置背景蒙层的样式,分为半透明和毛玻璃效果,毛玻璃又细分为Dark,ExtraLight,Light3种样式 142 | 143 | - (void)setBackgroundViewAppearanceStyle:(SPBackgroundViewAppearanceStyle)style alpha:(CGFloat)alpha; 144 | ``` 145 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-0b23494c3ba2a6fc.jpg) 146 | 147 | ``` 148 | // 单击背景蒙层是否退出对话框,默认YES 149 | 150 | @property(nonatomic, assign) BOOL tapBackgroundViewDismiss; 151 | ``` 152 | ``` 153 | @property(nonatomic, assign) CGFloat cornerRadiusForAlert; 154 | ``` 155 | SPAlertControllerStyleAlert下的圆角半径 156 | 157 | ### 创建action 158 | ``` 159 | // 其中,title为action的标题,创建的时候仅支持普通文本,如果要使用富文本,可以另外设置action的属性attributedTitle,设置后会覆盖普通文本 160 | 161 | + (instancetype)actionWithTitle:(nullable NSString *)title style:(SPAlertActionStyle)style handler:(void (^ __nullable)(SPAlertAction *action))handler; 162 | ``` 163 | ### 配置action 164 | * title,action的标题 165 | * attributedTitle,action的富文本标题,普通文本和富文本同时设置时,只会显示富文本 166 | * image,action上的图片,文字和图片都存在时,图片在左,文字在右 167 | * imageTitleSpacing,图片与文字之间的间距 168 | * titleColor,action标题的颜色 169 | * titleFont,action标题的字体 170 | * titleEdgeInsets,action标题的内边距,此属性能够改变action的高度 171 | * enabled,action是否能被点击 172 | 173 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/6AAAA07F90853F52CA6166D815F619A9.jpg) 174 | 175 | ## 自定义View 176 | * 自定义对话框的头部 177 | ``` 178 | + (instancetype)alertControllerWithCustomHeaderView:(nullable UIView *)customHeaderView preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 179 | ``` 180 | 181 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-41170beb443f32f0.jpg) 182 | 183 | * 自定义整个对话框 184 | ``` 185 | + (instancetype)alertControllerWithCustomAlertView:(nullable UIView *)customAlertView preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 186 | ``` 187 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-3cd4a2b6ff4da206.jpg) 188 | 189 | * 自定义对话框的action部分 190 | ``` 191 | + (instancetype)alertControllerWithCustomActionSequenceView:(nullable UIView *)customActionSequenceView title:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 192 | ``` 193 | ![image](https://github.com/SPStore/SPAlertController/blob/master/Images/3006981-9544748007937417.jpg) 194 | ## 关于自定义view的大小 195 | * 非自动布局,在传入自定义view之前,应该为自定义的view设置好frame,也可以在传入自定义view之后,调用API```- (void)updateCustomViewSize:(CGSize)size```设置其大小; 196 | * 自动布局,如果宽度和高度都能由子控件撑起来,那么你不需要设置frame,否则,宽度和高度只要有其中一个无法由子控件撑起,那么就必须设置其值,比如高度能被子控件撑起来,而宽度不能,那么你就必须手动设置一个宽度,高度可以不用设置或者设置为0都可。如果是xib或者storyboard,若自定义的view无法由子控件撑起来,SPAlertController会读取xib/storyboard中的默认frame,如果不合适,那么你应该修改xib/storyboard中的默认frame或者用纯代码重新设置frame。如果自定义view的宽度能够被子控件撑起,但同时又手动设置了自定义view的宽度,那么SPAlertController会取自动撑起的宽度和手动设置的宽度中较大的那个,高度同理。有一种情况要值得注意:如果子控件类似按钮这种不设置大小就自动会产生大小的子控件,同时该按钮设置了左右间距,那么它就能将自定义的view的宽度撑起,但是这种撑起来的宽度可能并非你想要的,因为按钮宽度是由内容自动产生,不是你设置的,这时你应该手动设置按钮的宽度,以便自定义的view的宽度被撑起的恰到好处,或者手动设置自定义view的宽度,这个手动设置的宽度,应该要比没有手动设置宽度的按钮将自定义view撑起来的宽度要大。 197 | * 当自定义的view的大小在对话框显示期间发生了变化,你应该调用```- (void)updateCustomViewSize:(CGSize)size```通知SPAlertController更新其大小 198 | 199 | ## 深色模式预览 200 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/1-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/1.jpg) 201 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/2-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/2.jpg) 202 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/3-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/3.jpg) 203 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/4-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/4.jpg) 204 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/5-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/5.jpg) 205 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/6-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/6.jpg) 206 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/7-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/7.jpg) 207 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/8-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/8.jpg) 208 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/9-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/9.jpg) 209 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/10-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/10.jpg) 210 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/11-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/11.jpg) 211 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/12-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/12.jpg) 212 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/13-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/13.jpg) 213 | [![](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/14-small.jpg)](https://raw.githubusercontent.com/wiki/SPStore/SPAlertController/Screetshots/14.jpg) 214 | ## 历史版本 215 | | 版本 | 更新日期 | 支持最低系统版本 |更新内容 | 216 | | :------------:| :------------:| :------------:|------------| 217 | |v4.0.0|2020.04.27|iOS9.0|适配深色模式| 218 | |v3.1.0|2019.08.08|iOS9.0|1、actionSheet样式加了单边圆角效果
2、毛玻璃默认为NO
3、当不需要毛玻璃效果时,actionButton的选中背景色修改(灰度0.1),属于bug修复
4、“取消action”上的分割线背景色修改(灰度由0.3变为0.2),高度由6增加为8
5、每个actionButton的最小高度由49变为55| 219 | |v3.0.4|2019.06.03|iOS9.0|修复了tapBackgroundViewDismiss属性无效问题| 220 | |v3.0.3|2019.05.30|iOS9.0|修复了action点击的回调为nil时闪退问题| 221 | |v3.0.2|2019.05.09|iOS9.0|修复了内存泄漏问题| 222 | |v3.0.1|2019.01.03|iOS9.0|背景蒙层动画更加的柔和| 223 | |v3.0.0|2018.12.29|iOS9.0|全方位的大重构| 224 | |v2.5.2|2018.12.03|iOS8.0|1、按钮处于最底部时长按touchDown事件的延时现象采用新方式解决
2、修复了内存泄露问题| 225 | |v2.5.1|2018.11.07|iOS8.0|1、修改了action的选中效果
2、解决iOS11之后,按钮处于最底部时长按touchDown事件的延时现象| 226 | |v2.5.0|2018.11.07|iOS8.0|1、毛玻璃思路另辟蹊径,毛玻璃效果不会受到背景遮罩的影响,同时背景遮罩不再被镂空
2、增加动画枚举,可以从左右弹出
3、自定义view时的背景色改为透明色
4、增加actionHeight属性,修复maxNumberOfActionHorizontalArrangementForAlert属性
5、去除了中间tableView的最后一条分割线
6、修改了分割线的颜色,更加接近微信原生
7、修复centerView上有textView/textField,旋转屏幕后不可见问题
8、优化代码| 227 | |v2.1.1|2018.11.01|iOS8.0|| 228 | |v2.1.0|2018.10.18|iOS8.0|| 229 | |v2.0.0|2017.11.19|iOS8.0|| 230 | |v1.7.0|2017.11.06|iOS8.0|| 231 | |v1.5.0|2017.11.06|iOS8.0|| 232 | |v1.0.1|2017.10.24|iOS8.0|| 233 | |v1.0.0|2017.10.24|iOS8.0||| 234 | 235 | [回到顶部](#目录) 236 | -------------------------------------------------------------------------------- /SPAlertController.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint SPAlertController.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "SPAlertController" 19 | s.version = "4.0.0" 20 | s.summary = "提醒对话框." 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | s.description = <<-DESC 28 | 说明:4.0.0适配了深色模式 29 | DESC 30 | 31 | s.homepage = "https://github.com/SPStore/SPAlertController" 32 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 33 | 34 | 35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 36 | # 37 | # Licensing your code is important. See http://choosealicense.com for more info. 38 | # CocoaPods will detect a license file if there is a named LICENSE* 39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 40 | # 41 | 42 | s.license = "MIT" 43 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 44 | 45 | 46 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 47 | # 48 | # Specify the authors of the library, with email addresses. Email addresses 49 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 50 | # accepts just a name if you'd rather not provide an email address. 51 | # 52 | # Specify a social_media_url where others can refer to, for example a twitter 53 | # profile URL. 54 | # 55 | 56 | s.author = { "SPStore" => "lesp163@163.com" } 57 | # Or just: s.author = "SPStore" 58 | # s.authors = { "SPStore" => "" } 59 | # s.social_media_url = "http://twitter.com/SPStore" 60 | 61 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 62 | # 63 | # If this Pod runs only on iOS or OS X, then specify the platform and 64 | # the deployment target. You can optionally include the target after the platform. 65 | # 66 | 67 | s.platform = :ios 68 | s.platform = :ios, "9.0" 69 | 70 | # When using multiple platforms 71 | s.ios.deployment_target = "9.0" 72 | # s.osx.deployment_target = "10.7" 73 | # s.watchos.deployment_target = "2.0" 74 | # s.tvos.deployment_target = "9.0" 75 | 76 | 77 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 78 | # 79 | # Specify the location from where the source should be retrieved. 80 | # Supports git, hg, bzr, svn and HTTP. 81 | # 82 | 83 | s.source = { :git => "https://github.com/SPStore/SPAlertController.git", :tag => s.version } 84 | 85 | 86 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 87 | # 88 | # CocoaPods is smart about how it includes source code. For source files 89 | # giving a folder will include any swift, h, m, mm, c & cpp files. 90 | # For header files it will include any header in the folder. 91 | # Not including the public_header_files will make all headers public. 92 | # 93 | 94 | s.source_files = "SPAlertController" 95 | s.exclude_files = "Classes/Exclude" 96 | 97 | # s.public_header_files = "Classes/**/*.h" 98 | 99 | 100 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 101 | # 102 | # A list of resources included with the Pod. These are copied into the 103 | # target bundle with a build phase script. Anything else will be cleaned. 104 | # You can preserve files from being cleaned, please don't preserve 105 | # non-essential files like tests, examples and documentation. 106 | # 107 | 108 | # s.resource = "icon.png" 109 | # s.resources = "Resources/*.png" 110 | 111 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 112 | 113 | 114 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 115 | # 116 | # Link your library with frameworks, or libraries. Libraries do not include 117 | # the lib prefix of their name. 118 | # 119 | 120 | # s.framework = "SomeFramework" 121 | # s.frameworks = "SomeFramework", "AnotherFramework" 122 | 123 | # s.library = "iconv" 124 | # s.libraries = "iconv", "xml2" 125 | 126 | 127 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 128 | # 129 | # If your library depends on compiler flags you can set them in the xcconfig hash 130 | # where they will only apply to your library. If you depend on other Podspecs 131 | # you can include multiple dependencies to ensure it works. 132 | 133 | # s.requires_arc = true 134 | 135 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 136 | # s.dependency "JSONKit", "~> 1.4" 137 | 138 | end 139 | -------------------------------------------------------------------------------- /SPAlertController/SPAlertController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SPAlertController.h 3 | // SPAlertController 4 | // 5 | // Created by 乐升平 on 18/10/12. https://github.com/SPStore/SPAlertController 6 | // Copyright © 2018-2019 leshengping (lesp163@163.com). All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef NS_ENUM(NSInteger, SPAlertControllerStyle) { 14 | SPAlertControllerStyleActionSheet = 0, // 从单侧弹出(顶/左/底/右) 15 | SPAlertControllerStyleAlert, // 从中间弹出 16 | }; 17 | 18 | typedef NS_ENUM(NSInteger, SPAlertAnimationType) { 19 | SPAlertAnimationTypeDefault = 0, // 默认动画,如果是SPAlertControllerStyleActionSheet样式,默认动画等效于SPAlertAnimationTypeFromBottom,如果是SPAlertControllerStyleAlert样式,默认动画等效于SPAlertAnimationTypeShrink 20 | SPAlertAnimationTypeFromBottom, // 从底部弹出 21 | SPAlertAnimationTypeFromTop, // 从顶部弹出 22 | SPAlertAnimationTypeFromRight, // 从右边弹出 23 | SPAlertAnimationTypeFromLeft, // 从左边弹出 24 | 25 | SPAlertAnimationTypeShrink, // 收缩动画 26 | SPAlertAnimationTypeExpand, // 发散动画 27 | SPAlertAnimationTypeFade, // 渐变动画 28 | 29 | SPAlertAnimationTypeNone, // 无动画 30 | SPAlertAnimationTypeAlpha NS_ENUM_DEPRECATED_IOS(8_0, 8_0, "Use SPAlertAnimationTypeFade instead"), // 渐变动画 31 | SPAlertAnimationTypeRaiseUp NS_ENUM_DEPRECATED_IOS(8_0, 8_0, "Use SPAlertAnimationTypeFromBottom instead"), // 从底部弹出 32 | SPAlertAnimationTypeDropDown NS_ENUM_DEPRECATED_IOS(8_0, 8_0, "Use SPAlertAnimationTypeFromTop instead"), // 从顶部弹出 33 | }; 34 | 35 | typedef NS_ENUM(NSInteger, SPAlertActionStyle) { 36 | SPAlertActionStyleDefault = 0, // 默认样式 37 | SPAlertActionStyleCancel, // 取消样式,字体加粗 38 | SPAlertActionStyleDestructive // 红色字体样式 39 | }; 40 | 41 | // ===================================================== SPAlertAction ===================================================== 42 | 43 | @interface SPAlertAction : NSObject 44 | 45 | + (instancetype)actionWithTitle:(nullable NSString *)title style:(SPAlertActionStyle)style handler:(void (^ __nullable)(SPAlertAction *action))handler; 46 | 47 | /** action的标题 */ 48 | @property(nullable, nonatomic, copy) NSString *title; 49 | /** action的富文本标题 */ 50 | @property(nullable, nonatomic, copy) NSAttributedString *attributedTitle; 51 | /** action的图标,位于title的左边 */ 52 | @property(nullable, nonatomic, copy) UIImage *image; 53 | /** title跟image之间的间距 */ 54 | @property (nonatomic, assign) CGFloat imageTitleSpacing; 55 | /** 渲染颜色,当外部的图片使用了UIImageRenderingModeAlwaysTemplate时,使用该属性可改变图片的颜色 */ 56 | @property (nonatomic, strong) UIColor *tintColor; 57 | /** 是否能点击,默认为YES */ 58 | @property(nonatomic, getter=isEnabled) BOOL enabled; 59 | /** action的标题颜色,这个颜色只是普通文本的颜色,富文本颜色需要用NSForegroundColorAttributeName */ 60 | @property(nonatomic, strong) UIColor *titleColor; 61 | /** action的标题字体,如果文字太长显示不全,会自动改变字体自适应按钮宽度,最多压缩文字为原来的0.5倍封顶 */ 62 | @property(nonatomic, strong) UIFont *titleFont; 63 | /** action的标题的内边距,如果在不改变字体的情况下想增大action的高度,可以设置该属性的top和bottom值,默认UIEdgeInsetsMake(0, 15, 0, 15) */ 64 | @property(nonatomic, assign) UIEdgeInsets titleEdgeInsets; 65 | 66 | /** 样式 */ 67 | @property(nonatomic, readonly) SPAlertActionStyle style; 68 | 69 | @end 70 | 71 | // ===================================================== SPAlertController ===================================================== 72 | 73 | @protocol SPAlertControllerDelegate; 74 | @interface SPAlertController : UIViewController 75 | 76 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle; 77 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 78 | 79 | - (void)addAction:(SPAlertAction *)action; 80 | @property (nonatomic, readonly) NSArray *actions; 81 | 82 | /* 添加文本输入框 83 | * 一旦添加后就会回调一次(仅回调一次,因此可以在这个block块里面自由定制textFiled,如设置textField的属性,设置代理,添加addTarget,监听通知等); 84 | */ 85 | - (void)addTextFieldWithConfigurationHandler:(void (^ __nullable)(UITextField *textField))configurationHandler; 86 | @property(nullable, nonatomic, readonly) NSArray *textFields; 87 | 88 | /** 主标题 */ 89 | @property(nullable, nonatomic, copy) NSString *title; 90 | /** 副标题 */ 91 | @property(nullable, nonatomic, copy) NSString *message; 92 | /** 主标题(富文本) */ 93 | @property(nullable, nonatomic, copy) NSAttributedString *attributedTitle; 94 | /** 副标题(富文本) */ 95 | @property(nullable, nonatomic, copy) NSAttributedString *attributedMessage; 96 | /** 头部图标,位置处于title之上,大小取决于图片本身大小 */ 97 | @property(nullable,nonatomic, copy) UIImage *image; 98 | 99 | /** 主标题颜色 */ 100 | @property(nonatomic, strong) UIColor *titleColor; 101 | /** 主标题字体,默认18,加粗 */ 102 | @property(nonatomic, strong) UIFont *titleFont; 103 | /** 副标题颜色 */ 104 | @property(nonatomic, strong) UIColor *messageColor; 105 | /** 副标题字体,默认16,未加粗 */ 106 | @property(nonatomic, strong) UIFont *messageFont; 107 | /** 对齐方式(包括主标题和副标题) */ 108 | @property(nonatomic, assign) NSTextAlignment textAlignment; 109 | /** 头部图标的限制大小,默认无穷大 */ 110 | @property (nonatomic, assign) CGSize imageLimitSize; 111 | /** 图片的tintColor,当外部的图片使用了UIImageRenderingModeAlwaysTemplate时,该属性可起到作用 */ 112 | @property (nonatomic, strong) UIColor *imageTintColor; 113 | 114 | /* 115 | * action水平排列还是垂直排列 116 | * actionSheet样式下:默认为UILayoutConstraintAxisVertical(垂直排列), 如果设置为UILayoutConstraintAxisHorizontal(水平排列),则除去取消样式action之外的其余action将水平排列 117 | * alert样式下:当actions的个数大于2,或者某个action的title显示不全时为UILayoutConstraintAxisVertical(垂直排列),否则默认为UILayoutConstraintAxisHorizontal(水平排列),此样式下设置该属性可以修改所有action的排列方式 118 | * 不论哪种样式,只要外界设置了该属性,永远以外界设置的优先 119 | */ 120 | @property(nonatomic) UILayoutConstraintAxis actionAxis; 121 | 122 | /* 距离屏幕边缘的最小间距 123 | * alert样式下该属性是指对话框四边与屏幕边缘之间的距离,此样式下默认值随设备变化,actionSheet样式下是指弹出边的对立边与屏幕之间的距离,比如如果从右边弹出,那么该属性指的就是对话框左边与屏幕之间的距离,此样式下默认值为70 124 | */ 125 | @property(nonatomic, assign) CGFloat minDistanceToEdges; 126 | 127 | /** SPAlertControllerStyleAlert样式下默认6.0f,SPAlertControllerStyleActionSheet样式下默认13.0f,去除半径设置为0即可 */ 128 | @property(nonatomic, assign) CGFloat cornerRadius; 129 | 130 | /** 对话框的偏移量,y值为正向下偏移,为负向上偏移;x值为正向右偏移,为负向左偏移,该属性只对SPAlertControllerStyleAlert样式有效,键盘的frame改变会自动偏移,如果手动设置偏移只会取手动设置的 */ 131 | @property(nonatomic, assign) CGPoint offsetForAlert; 132 | /** 设置alert样式下的偏移量,动画为NO则跟属性offsetForAlert等效 */ 133 | - (void)setOffsetForAlert:(CGPoint)offsetForAlert animated:(BOOL)animated; 134 | 135 | /** 是否需要对话框拥有毛玻璃,默认为YES */ 136 | @property(nonatomic, assign) BOOL needDialogBlur; 137 | 138 | /** 是否单击背景退出对话框,默认为YES */ 139 | @property(nonatomic, assign) BOOL tapBackgroundViewDismiss; 140 | 141 | @property(nonatomic, weak) id delegate; 142 | 143 | @property(nonatomic, readonly) SPAlertControllerStyle preferredStyle; 144 | @property(nonatomic, readonly) SPAlertAnimationType animationType; 145 | 146 | /** 设置action与下一个action之间的间距, action仅限于非取消样式,必须在'-addAction:'之后设置,iOS11或iOS11以上才能使用 */ 147 | - (void)setCustomSpacing:(CGFloat)spacing afterAction:(SPAlertAction *)action API_AVAILABLE(ios(11.0)); 148 | - (CGFloat)customSpacingAfterAction:(SPAlertAction *)action API_AVAILABLE(ios(11.0)); 149 | 150 | /** 设置蒙层的外观样式,可通过alpha调整透明度 */ 151 | - (void)setBackgroundViewAppearanceStyle:(UIBlurEffectStyle)style alpha:(CGFloat)alpha; 152 | 153 | // 插入一个组件view,位置处于头部和action部分之间,要求头部和action部分同时存在 154 | - (void)insertComponentView:(nonnull UIView *)componentView; 155 | 156 | 157 | // ---------------------------------------------- custom ----------------------------------------------------- 158 | /** 159 | 创建控制器(自定义整个对话框) 160 | 161 | @param customAlertView 整个对话框的自定义view 162 | @param preferredStyle 对话框样式 163 | @param animationType 动画类型 164 | @return 控制器对象 165 | */ 166 | + (instancetype)alertControllerWithCustomAlertView:(nonnull UIView *)customAlertView preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 167 | /** 168 | 创建控制器(自定义对话框的头部) 169 | 170 | @param customHeaderView 头部自定义view 171 | @param preferredStyle 对话框样式 172 | @param animationType 动画类型 173 | @return 控制器对象 174 | */ 175 | + (instancetype)alertControllerWithCustomHeaderView:(nonnull UIView *)customHeaderView preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 176 | /** 177 | 创建控制器(自定义对话框的action部分) 178 | 179 | @param customActionSequenceView action部分的自定义view 180 | @param title 大标题 181 | @param message 副标题 182 | @param preferredStyle 对话框样式 183 | @param animationType 动画类型 184 | @return 控制器对象 185 | */ 186 | + (instancetype)alertControllerWithCustomActionSequenceView:(nonnull UIView *)customActionSequenceView title:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType; 187 | 188 | /** 更新自定义view的size,比如屏幕旋转,自定义view的大小发生了改变,可通过该方法更新size */ 189 | - (void)updateCustomViewSize:(CGSize)size; 190 | 191 | @property(nonatomic, assign) CGFloat cornerRadiusForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use cornerRadius instead"); 192 | @property (nonatomic, assign) CGFloat maxTopMarginForActionSheet NS_DEPRECATED_IOS(8_0, 8_0,"Use minDistanceToEdges instead"); 193 | @property(nonatomic, assign) CGFloat maxMarginForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use minDistanceToEdges instead"); 194 | @property(nonatomic, assign) NSInteger maxNumberOfActionHorizontalArrangementForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use actionAxis instead"); 195 | @property(nonatomic, assign) CGFloat offsetYForAlert NS_DEPRECATED_IOS(8_0, 8_0,"Use offsetForAlert instead"); 196 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customView:(nullable UIView *)customView NS_DEPRECATED_IOS(8_0, 8_0,"Use +alertControllerWithCustomAlertView:preferredStyle:animationType:"); 197 | + (instancetype)alertControllerWithPreferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customHeaderView:(nullable UIView *)customHeaderView NS_DEPRECATED_IOS(8_0, 8_0,"Use +alertControllerWithCustomHeaderView:preferredStyle:animationType:"); 198 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customCenterView:(nullable UIView *)customCenterView NS_DEPRECATED_IOS(8_0, 8_0,"Use -insertComponentView:"); 199 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(SPAlertControllerStyle)preferredStyle animationType:(SPAlertAnimationType)animationType customFooterView:(nullable UIView *)customFooterView NS_DEPRECATED_IOS(8_0, 8_0,"Use +alertControllerWithCustomActionSequenceView:title:message:preferredStyle:animationType:"); 200 | @end 201 | 202 | @protocol SPAlertControllerDelegate 203 | @optional; 204 | - (void)willPresentAlertController:(SPAlertController *)alertController; // 将要present 205 | - (void)didPresentAlertController:(SPAlertController *)alertController; // 已经present 206 | - (void)willDismissAlertController:(SPAlertController *)alertController; // 将要dismiss 207 | - (void)didDismissAlertController:(SPAlertController *)alertController; // 已经dismiss 208 | 209 | 210 | - (void)sp_alertControllerWillShow:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -willPresentAlertController:"); 211 | - (void)sp_alertControllerDidShow:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -DidPresentAlertController:"); 212 | - (void)sp_alertControllerWillHide:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -willDismissAlertController:"); 213 | - (void)sp_alertControllerDidHide:(SPAlertController *)alertController NS_DEPRECATED_IOS(8_0, 8_0,"Use -DidDismissAlertController:"); 214 | @end 215 | 216 | @interface SPAlertPresentationController : UIPresentationController 217 | @end 218 | 219 | @interface SPAlertAnimation : NSObject 220 | + (instancetype)animationIsPresenting:(BOOL)presenting; 221 | @end 222 | 223 | NS_ASSUME_NONNULL_END 224 | --------------------------------------------------------------------------------