├── .gitignore ├── AXAlertController.podspec ├── AXAlertController.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── AXAlertController.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── AXAlertController ├── AXAlertController │ ├── AXActionSheet.h │ ├── AXActionSheet.m │ ├── AXAlertConstant.h │ ├── AXAlertController.h │ ├── AXAlertController.m │ ├── AXAlertView.h │ └── AXAlertView.m ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Image.imageset │ │ ├── Contents.json │ │ └── image.png │ ├── button.imageset │ │ ├── Contents.json │ │ ├── ax_button-1.png │ │ ├── ax_button-2.png │ │ └── ax_button.png │ ├── cancel.imageset │ │ ├── Contents.json │ │ ├── btn_dialog_cancel@2x.png │ │ └── btn_dialog_cancel@3x.png │ ├── confirm.imageset │ │ ├── Contents.json │ │ ├── btn_dialog_confirm@2x.png │ │ └── btn_dialog_confirm@3x.png │ ├── content_image.imageset │ │ ├── Contents.json │ │ └── image.png │ ├── more.imageset │ │ ├── Contents.json │ │ ├── btn_more@2x.png │ │ └── btn_more@3x.png │ ├── state.imageset │ │ ├── Contents.json │ │ ├── img-1.png │ │ └── img.png │ └── touch.imageset │ │ ├── Contents.json │ │ ├── touch@2x.png │ │ └── touch@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SampleViewController.h ├── SampleViewController.m ├── SettingViewController.h ├── SettingViewController.m ├── TableViewController.h ├── TableViewController.m ├── ViewController.h ├── ViewController.m ├── image.png └── main.m ├── LICENSE ├── Podfile └── Podfile.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /AXAlertController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "AXAlertController" 4 | s.version = "0.3.0" 5 | s.summary = "A customized alert view controller." 6 | s.description = "A customized alert view. A subclass of UIView. A simple way to show a custom alert view." 7 | 8 | s.homepage = "https://github.com/devedbox/AXAlertController" 9 | s.license = { :type => "MIT", :file => "LICENSE" } 10 | 11 | s.author = { "devedbox" => "devedbox@qq.com" } 12 | s.platform = :ios, "8.0" 13 | 14 | s.ios.deployment_target = "8.0" 15 | # s.osx.deployment_target = "10.7" 16 | # s.watchos.deployment_target = "2.0" 17 | # s.tvos.deployment_target = "9.0" 18 | 19 | s.source = { :git => "https://github.com/devedbox/AXAlertController.git", :tag => s.version } 20 | 21 | 22 | s.source_files = "AXAlertController/AXAlertController/*.{h,m}" 23 | #s.exclude_files = "Classes/Exclude" 24 | 25 | # s.public_header_files = "Classes/**/*.h" 26 | 27 | 28 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 29 | # 30 | # A list of resources included with the Pod. These are copied into the 31 | # target bundle with a build phase script. Anything else will be cleaned. 32 | # You can preserve files from being cleaned, please don't preserve 33 | # non-essential files like tests, examples and documentation. 34 | # 35 | 36 | # s.resource = "icon.png" 37 | # s.resources = "Resources/*.png" 38 | 39 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 40 | 41 | 42 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 43 | # 44 | # Link your library with frameworks, or libraries. Libraries do not include 45 | # the lib prefix of their name. 46 | # 47 | 48 | # s.framework = "SomeFramework" 49 | # s.frameworks = "SomeFramework", "AnotherFramework" 50 | 51 | # s.library = "iconv" 52 | # s.libraries = "iconv", "xml2" 53 | 54 | 55 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 56 | # 57 | # If your library depends on compiler flags you can set them in the xcconfig hash 58 | # where they will only apply to your library. If you depend on other Podspecs 59 | # you can include multiple dependencies to ensure it works. 60 | 61 | s.requires_arc = true 62 | 63 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 64 | # s.dependency "AXAnimationChain" 65 | 66 | end 67 | -------------------------------------------------------------------------------- /AXAlertController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 31782D886A303F15C4F350DA /* libPods-AXAlertController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C9FCD55F5D7066860C31901 /* libPods-AXAlertController.a */; }; 11 | DCA857B61EE698CB0008E9A4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857A31EE698CB0008E9A4 /* AppDelegate.m */; }; 12 | DCA857B71EE698CB0008E9A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DCA857A41EE698CB0008E9A4 /* Assets.xcassets */; }; 13 | DCA857B81EE698CB0008E9A4 /* AXActionSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857A71EE698CB0008E9A4 /* AXActionSheet.m */; }; 14 | DCA857B91EE698CB0008E9A4 /* AXAlertController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857A91EE698CB0008E9A4 /* AXAlertController.m */; }; 15 | DCA857BA1EE698CB0008E9A4 /* AXAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857AB1EE698CB0008E9A4 /* AXAlertView.m */; }; 16 | DCA857BB1EE698CB0008E9A4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DCA857AC1EE698CB0008E9A4 /* LaunchScreen.storyboard */; }; 17 | DCA857BC1EE698CB0008E9A4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DCA857AE1EE698CB0008E9A4 /* Main.storyboard */; }; 18 | DCA857BE1EE698CB0008E9A4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857B11EE698CB0008E9A4 /* main.m */; }; 19 | DCA857BF1EE698CB0008E9A4 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857B31EE698CB0008E9A4 /* TableViewController.m */; }; 20 | DCA857C01EE698CB0008E9A4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCA857B51EE698CB0008E9A4 /* ViewController.m */; }; 21 | DCB3D0382312713D0070487A /* NSLayoutConstraint+Configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB3D0362312713D0070487A /* NSLayoutConstraint+Configuration.m */; }; 22 | DCF5FA4E1EF90B0E009CE969 /* SampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF5FA4D1EF90B0E009CE969 /* SampleViewController.m */; }; 23 | DCFF5EFE1EFA0F6900744FD2 /* SettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DCFF5EFD1EFA0F6900744FD2 /* SettingViewController.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 01BB358D1CB35031002B5D1A /* AXAlertController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AXAlertController.app; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 37D7438B4F614BD7E4BD7FDA /* Pods-AXAlertView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AXAlertView.release.xcconfig"; path = "Pods/Target Support Files/Pods-AXAlertView/Pods-AXAlertView.release.xcconfig"; sourceTree = ""; }; 29 | 525EDD5E82AD48153196FAAB /* Pods-AXAlertView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AXAlertView.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AXAlertView/Pods-AXAlertView.debug.xcconfig"; sourceTree = ""; }; 30 | 6D00E16D94EC1983741C476A /* libPods-AXAlertView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AXAlertView.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 9C9FCD55F5D7066860C31901 /* libPods-AXAlertController.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AXAlertController.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | D91DA8761FD8A6D3F44323B6 /* Pods-AXAlertController.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AXAlertController.release.xcconfig"; path = "Pods/Target Support Files/Pods-AXAlertController/Pods-AXAlertController.release.xcconfig"; sourceTree = ""; }; 33 | DC6399181EE79DB000F23BCC /* AXAlertConstant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AXAlertConstant.h; sourceTree = ""; }; 34 | DCA857A21EE698CB0008E9A4 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | DCA857A31EE698CB0008E9A4 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | DCA857A41EE698CB0008E9A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 37 | DCA857A61EE698CB0008E9A4 /* AXActionSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AXActionSheet.h; sourceTree = ""; }; 38 | DCA857A71EE698CB0008E9A4 /* AXActionSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AXActionSheet.m; sourceTree = ""; }; 39 | DCA857A81EE698CB0008E9A4 /* AXAlertController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AXAlertController.h; sourceTree = ""; }; 40 | DCA857A91EE698CB0008E9A4 /* AXAlertController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AXAlertController.m; sourceTree = ""; }; 41 | DCA857AA1EE698CB0008E9A4 /* AXAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AXAlertView.h; sourceTree = ""; }; 42 | DCA857AB1EE698CB0008E9A4 /* AXAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AXAlertView.m; sourceTree = ""; }; 43 | DCA857AD1EE698CB0008E9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | DCA857AF1EE698CB0008E9A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 45 | DCA857B01EE698CB0008E9A4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | DCA857B11EE698CB0008E9A4 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 47 | DCA857B21EE698CB0008E9A4 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; }; 48 | DCA857B31EE698CB0008E9A4 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; }; 49 | DCA857B41EE698CB0008E9A4 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 50 | DCA857B51EE698CB0008E9A4 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 51 | DCB3D0362312713D0070487A /* NSLayoutConstraint+Configuration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSLayoutConstraint+Configuration.m"; sourceTree = ""; }; 52 | DCB3D0372312713D0070487A /* NSLayoutConstraint+Configuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSLayoutConstraint+Configuration.h"; sourceTree = ""; }; 53 | DCF5FA4C1EF90B0E009CE969 /* SampleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleViewController.h; sourceTree = ""; }; 54 | DCF5FA4D1EF90B0E009CE969 /* SampleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleViewController.m; sourceTree = ""; }; 55 | DCFF5EFC1EFA0F6900744FD2 /* SettingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingViewController.h; sourceTree = ""; }; 56 | DCFF5EFD1EFA0F6900744FD2 /* SettingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingViewController.m; sourceTree = ""; }; 57 | E0089C73A6637E46881D83DF /* Pods-AXAlertController.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AXAlertController.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AXAlertController/Pods-AXAlertController.debug.xcconfig"; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 01BB358A1CB35031002B5D1A /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | 31782D886A303F15C4F350DA /* libPods-AXAlertController.a in Frameworks */, 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | /* End PBXFrameworksBuildPhase section */ 70 | 71 | /* Begin PBXGroup section */ 72 | 01BB35841CB35031002B5D1A = { 73 | isa = PBXGroup; 74 | children = ( 75 | DCA857A11EE698CB0008E9A4 /* AXAlertController */, 76 | 01BB358E1CB35031002B5D1A /* Products */, 77 | E2AAD5D8A448265B45220D41 /* Pods */, 78 | 5C6ADC35B98060AEB3163FA0 /* Frameworks */, 79 | ); 80 | sourceTree = ""; 81 | }; 82 | 01BB358E1CB35031002B5D1A /* Products */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 01BB358D1CB35031002B5D1A /* AXAlertController.app */, 86 | ); 87 | name = Products; 88 | sourceTree = ""; 89 | }; 90 | 5C6ADC35B98060AEB3163FA0 /* Frameworks */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 6D00E16D94EC1983741C476A /* libPods-AXAlertView.a */, 94 | 9C9FCD55F5D7066860C31901 /* libPods-AXAlertController.a */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | DCA857A11EE698CB0008E9A4 /* AXAlertController */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | DCA857A21EE698CB0008E9A4 /* AppDelegate.h */, 103 | DCA857A31EE698CB0008E9A4 /* AppDelegate.m */, 104 | DCA857B21EE698CB0008E9A4 /* TableViewController.h */, 105 | DCA857B31EE698CB0008E9A4 /* TableViewController.m */, 106 | DCF5FA4C1EF90B0E009CE969 /* SampleViewController.h */, 107 | DCF5FA4D1EF90B0E009CE969 /* SampleViewController.m */, 108 | DCFF5EFC1EFA0F6900744FD2 /* SettingViewController.h */, 109 | DCFF5EFD1EFA0F6900744FD2 /* SettingViewController.m */, 110 | DCA857A51EE698CB0008E9A4 /* AXAlertController */, 111 | DCA857A41EE698CB0008E9A4 /* Assets.xcassets */, 112 | DCA857AC1EE698CB0008E9A4 /* LaunchScreen.storyboard */, 113 | DCA857AE1EE698CB0008E9A4 /* Main.storyboard */, 114 | DCA857B01EE698CB0008E9A4 /* Info.plist */, 115 | DCA857B11EE698CB0008E9A4 /* main.m */, 116 | DCA857B41EE698CB0008E9A4 /* ViewController.h */, 117 | DCA857B51EE698CB0008E9A4 /* ViewController.m */, 118 | ); 119 | path = AXAlertController; 120 | sourceTree = ""; 121 | }; 122 | DCA857A51EE698CB0008E9A4 /* AXAlertController */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | DCA857A81EE698CB0008E9A4 /* AXAlertController.h */, 126 | DCA857A91EE698CB0008E9A4 /* AXAlertController.m */, 127 | DC6399181EE79DB000F23BCC /* AXAlertConstant.h */, 128 | DCA857A61EE698CB0008E9A4 /* AXActionSheet.h */, 129 | DCA857A71EE698CB0008E9A4 /* AXActionSheet.m */, 130 | DCA857AA1EE698CB0008E9A4 /* AXAlertView.h */, 131 | DCA857AB1EE698CB0008E9A4 /* AXAlertView.m */, 132 | DCB3D0352312713D0070487A /* Categories */, 133 | ); 134 | path = AXAlertController; 135 | sourceTree = ""; 136 | }; 137 | DCB3D0352312713D0070487A /* Categories */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | DCB3D0372312713D0070487A /* NSLayoutConstraint+Configuration.h */, 141 | DCB3D0362312713D0070487A /* NSLayoutConstraint+Configuration.m */, 142 | ); 143 | path = Categories; 144 | sourceTree = ""; 145 | }; 146 | E2AAD5D8A448265B45220D41 /* Pods */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 525EDD5E82AD48153196FAAB /* Pods-AXAlertView.debug.xcconfig */, 150 | 37D7438B4F614BD7E4BD7FDA /* Pods-AXAlertView.release.xcconfig */, 151 | E0089C73A6637E46881D83DF /* Pods-AXAlertController.debug.xcconfig */, 152 | D91DA8761FD8A6D3F44323B6 /* Pods-AXAlertController.release.xcconfig */, 153 | ); 154 | name = Pods; 155 | sourceTree = ""; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | 01BB358C1CB35031002B5D1A /* AXAlertController */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = 01BB35BA1CB35031002B5D1A /* Build configuration list for PBXNativeTarget "AXAlertController" */; 163 | buildPhases = ( 164 | 25810A4B9622CC84E9595A08 /* [CP] Check Pods Manifest.lock */, 165 | 01BB35891CB35031002B5D1A /* Sources */, 166 | 01BB358A1CB35031002B5D1A /* Frameworks */, 167 | 01BB358B1CB35031002B5D1A /* Resources */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | ); 173 | name = AXAlertController; 174 | productName = AXAlertView; 175 | productReference = 01BB358D1CB35031002B5D1A /* AXAlertController.app */; 176 | productType = "com.apple.product-type.application"; 177 | }; 178 | /* End PBXNativeTarget section */ 179 | 180 | /* Begin PBXProject section */ 181 | 01BB35851CB35031002B5D1A /* Project object */ = { 182 | isa = PBXProject; 183 | attributes = { 184 | LastUpgradeCheck = 0900; 185 | ORGANIZATIONNAME = devedbox; 186 | TargetAttributes = { 187 | 01BB358C1CB35031002B5D1A = { 188 | CreatedOnToolsVersion = 7.3; 189 | DevelopmentTeam = TKA48YVS5T; 190 | }; 191 | }; 192 | }; 193 | buildConfigurationList = 01BB35881CB35031002B5D1A /* Build configuration list for PBXProject "AXAlertController" */; 194 | compatibilityVersion = "Xcode 3.2"; 195 | developmentRegion = English; 196 | hasScannedForEncodings = 0; 197 | knownRegions = ( 198 | English, 199 | en, 200 | Base, 201 | ); 202 | mainGroup = 01BB35841CB35031002B5D1A; 203 | productRefGroup = 01BB358E1CB35031002B5D1A /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 01BB358C1CB35031002B5D1A /* AXAlertController */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | 01BB358B1CB35031002B5D1A /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | DCA857BC1EE698CB0008E9A4 /* Main.storyboard in Resources */, 218 | DCA857B71EE698CB0008E9A4 /* Assets.xcassets in Resources */, 219 | DCA857BB1EE698CB0008E9A4 /* LaunchScreen.storyboard in Resources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXResourcesBuildPhase section */ 224 | 225 | /* Begin PBXShellScriptBuildPhase section */ 226 | 25810A4B9622CC84E9595A08 /* [CP] Check Pods Manifest.lock */ = { 227 | isa = PBXShellScriptBuildPhase; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | ); 231 | inputPaths = ( 232 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 233 | "${PODS_ROOT}/Manifest.lock", 234 | ); 235 | name = "[CP] Check Pods Manifest.lock"; 236 | outputPaths = ( 237 | "$(DERIVED_FILE_DIR)/Pods-AXAlertController-checkManifestLockResult.txt", 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | shellPath = /bin/sh; 241 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 242 | showEnvVarsInLog = 0; 243 | }; 244 | /* End PBXShellScriptBuildPhase section */ 245 | 246 | /* Begin PBXSourcesBuildPhase section */ 247 | 01BB35891CB35031002B5D1A /* Sources */ = { 248 | isa = PBXSourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | DCA857C01EE698CB0008E9A4 /* ViewController.m in Sources */, 252 | DCA857BE1EE698CB0008E9A4 /* main.m in Sources */, 253 | DCF5FA4E1EF90B0E009CE969 /* SampleViewController.m in Sources */, 254 | DCA857BF1EE698CB0008E9A4 /* TableViewController.m in Sources */, 255 | DCB3D0382312713D0070487A /* NSLayoutConstraint+Configuration.m in Sources */, 256 | DCA857BA1EE698CB0008E9A4 /* AXAlertView.m in Sources */, 257 | DCFF5EFE1EFA0F6900744FD2 /* SettingViewController.m in Sources */, 258 | DCA857B81EE698CB0008E9A4 /* AXActionSheet.m in Sources */, 259 | DCA857B61EE698CB0008E9A4 /* AppDelegate.m in Sources */, 260 | DCA857B91EE698CB0008E9A4 /* AXAlertController.m in Sources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXSourcesBuildPhase section */ 265 | 266 | /* Begin PBXVariantGroup section */ 267 | DCA857AC1EE698CB0008E9A4 /* LaunchScreen.storyboard */ = { 268 | isa = PBXVariantGroup; 269 | children = ( 270 | DCA857AD1EE698CB0008E9A4 /* Base */, 271 | ); 272 | name = LaunchScreen.storyboard; 273 | sourceTree = ""; 274 | }; 275 | DCA857AE1EE698CB0008E9A4 /* Main.storyboard */ = { 276 | isa = PBXVariantGroup; 277 | children = ( 278 | DCA857AF1EE698CB0008E9A4 /* Base */, 279 | ); 280 | name = Main.storyboard; 281 | sourceTree = ""; 282 | }; 283 | /* End PBXVariantGroup section */ 284 | 285 | /* Begin XCBuildConfiguration section */ 286 | 01BB35B81CB35031002B5D1A /* Debug */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ALWAYS_SEARCH_USER_PATHS = NO; 290 | CLANG_ANALYZER_NONNULL = YES; 291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 292 | CLANG_CXX_LIBRARY = "libc++"; 293 | CLANG_ENABLE_MODULES = YES; 294 | CLANG_ENABLE_OBJC_ARC = YES; 295 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 296 | CLANG_WARN_BOOL_CONVERSION = YES; 297 | CLANG_WARN_COMMA = YES; 298 | CLANG_WARN_CONSTANT_CONVERSION = YES; 299 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 300 | CLANG_WARN_EMPTY_BODY = YES; 301 | CLANG_WARN_ENUM_CONVERSION = YES; 302 | CLANG_WARN_INFINITE_RECURSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 305 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 306 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 307 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 308 | CLANG_WARN_STRICT_PROTOTYPES = YES; 309 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 310 | CLANG_WARN_UNREACHABLE_CODE = YES; 311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 312 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 313 | COPY_PHASE_STRIP = NO; 314 | DEBUG_INFORMATION_FORMAT = dwarf; 315 | ENABLE_STRICT_OBJC_MSGSEND = YES; 316 | ENABLE_TESTABILITY = YES; 317 | GCC_C_LANGUAGE_STANDARD = gnu99; 318 | GCC_DYNAMIC_NO_PIC = NO; 319 | GCC_NO_COMMON_BLOCKS = YES; 320 | GCC_OPTIMIZATION_LEVEL = 0; 321 | GCC_PREPROCESSOR_DEFINITIONS = ( 322 | "DEBUG=1", 323 | "$(inherited)", 324 | ); 325 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 326 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 327 | GCC_WARN_UNDECLARED_SELECTOR = YES; 328 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 329 | GCC_WARN_UNUSED_FUNCTION = YES; 330 | GCC_WARN_UNUSED_VARIABLE = YES; 331 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 332 | MTL_ENABLE_DEBUG_INFO = YES; 333 | ONLY_ACTIVE_ARCH = YES; 334 | SDKROOT = iphoneos; 335 | }; 336 | name = Debug; 337 | }; 338 | 01BB35B91CB35031002B5D1A /* Release */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | CLANG_ANALYZER_NONNULL = YES; 343 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 344 | CLANG_CXX_LIBRARY = "libc++"; 345 | CLANG_ENABLE_MODULES = YES; 346 | CLANG_ENABLE_OBJC_ARC = YES; 347 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 348 | CLANG_WARN_BOOL_CONVERSION = YES; 349 | CLANG_WARN_COMMA = YES; 350 | CLANG_WARN_CONSTANT_CONVERSION = YES; 351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 352 | CLANG_WARN_EMPTY_BODY = YES; 353 | CLANG_WARN_ENUM_CONVERSION = YES; 354 | CLANG_WARN_INFINITE_RECURSION = YES; 355 | CLANG_WARN_INT_CONVERSION = YES; 356 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 357 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 358 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 359 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 360 | CLANG_WARN_STRICT_PROTOTYPES = YES; 361 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 362 | CLANG_WARN_UNREACHABLE_CODE = YES; 363 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 364 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 365 | COPY_PHASE_STRIP = NO; 366 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 367 | ENABLE_NS_ASSERTIONS = NO; 368 | ENABLE_STRICT_OBJC_MSGSEND = YES; 369 | GCC_C_LANGUAGE_STANDARD = gnu99; 370 | GCC_NO_COMMON_BLOCKS = YES; 371 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 372 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 373 | GCC_WARN_UNDECLARED_SELECTOR = YES; 374 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 375 | GCC_WARN_UNUSED_FUNCTION = YES; 376 | GCC_WARN_UNUSED_VARIABLE = YES; 377 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 378 | MTL_ENABLE_DEBUG_INFO = NO; 379 | SDKROOT = iphoneos; 380 | VALIDATE_PRODUCT = YES; 381 | }; 382 | name = Release; 383 | }; 384 | 01BB35BB1CB35031002B5D1A /* Debug */ = { 385 | isa = XCBuildConfiguration; 386 | baseConfigurationReference = E0089C73A6637E46881D83DF /* Pods-AXAlertController.debug.xcconfig */; 387 | buildSettings = { 388 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 389 | DEVELOPMENT_TEAM = TKA48YVS5T; 390 | INFOPLIST_FILE = "$(SRCROOT)/AXAlertController/Info.plist"; 391 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 392 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 393 | PRODUCT_BUNDLE_IDENTIFIER = devedbox.AXAlertController; 394 | PRODUCT_NAME = "$(TARGET_NAME)"; 395 | TARGETED_DEVICE_FAMILY = "1,2"; 396 | }; 397 | name = Debug; 398 | }; 399 | 01BB35BC1CB35031002B5D1A /* Release */ = { 400 | isa = XCBuildConfiguration; 401 | baseConfigurationReference = D91DA8761FD8A6D3F44323B6 /* Pods-AXAlertController.release.xcconfig */; 402 | buildSettings = { 403 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 404 | DEVELOPMENT_TEAM = TKA48YVS5T; 405 | INFOPLIST_FILE = "$(SRCROOT)/AXAlertController/Info.plist"; 406 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 407 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 408 | PRODUCT_BUNDLE_IDENTIFIER = devedbox.AXAlertController; 409 | PRODUCT_NAME = "$(TARGET_NAME)"; 410 | TARGETED_DEVICE_FAMILY = "1,2"; 411 | }; 412 | name = Release; 413 | }; 414 | /* End XCBuildConfiguration section */ 415 | 416 | /* Begin XCConfigurationList section */ 417 | 01BB35881CB35031002B5D1A /* Build configuration list for PBXProject "AXAlertController" */ = { 418 | isa = XCConfigurationList; 419 | buildConfigurations = ( 420 | 01BB35B81CB35031002B5D1A /* Debug */, 421 | 01BB35B91CB35031002B5D1A /* Release */, 422 | ); 423 | defaultConfigurationIsVisible = 0; 424 | defaultConfigurationName = Release; 425 | }; 426 | 01BB35BA1CB35031002B5D1A /* Build configuration list for PBXNativeTarget "AXAlertController" */ = { 427 | isa = XCConfigurationList; 428 | buildConfigurations = ( 429 | 01BB35BB1CB35031002B5D1A /* Debug */, 430 | 01BB35BC1CB35031002B5D1A /* Release */, 431 | ); 432 | defaultConfigurationIsVisible = 0; 433 | defaultConfigurationName = Release; 434 | }; 435 | /* End XCConfigurationList section */ 436 | }; 437 | rootObject = 01BB35851CB35031002B5D1A /* Project object */; 438 | } 439 | -------------------------------------------------------------------------------- /AXAlertController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AXAlertController.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AXAlertController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AXAlertController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AXAlertController/AXAlertController/AXActionSheet.h: -------------------------------------------------------------------------------- 1 | // 2 | // AXActionSheet.h 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/5/28. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import "AXAlertView.h" 27 | 28 | NS_ASSUME_NONNULL_BEGIN 29 | @class AXActionSheetAction; 30 | 31 | typedef NS_ENUM(NSUInteger, AXActionSheetActionStyle) { 32 | AXActionSheetActionStyleDefault, 33 | AXActionSheetActionStyleCancel 34 | }; 35 | 36 | @interface AXActionSheet : AXAlertView @end 37 | 38 | @interface AXActionSheetAction : AXAlertViewAction 39 | /// Style of the action sheet. 40 | @property(assign, nonatomic) AXActionSheetActionStyle style; 41 | 42 | + (instancetype _Nonnull)actionWithTitle:(NSString *_Nonnull)title style:(AXActionSheetActionStyle)style handler:(AXAlertViewActionHandler _Nullable)handler; 43 | + (instancetype _Nonnull)actionWithTitle:(NSString *_Nonnull)title image:(UIImage *_Nullable)image style:(AXActionSheetActionStyle)style handler:(AXAlertViewActionHandler _Nullable)handler; 44 | @end 45 | NS_ASSUME_NONNULL_END 46 | -------------------------------------------------------------------------------- /AXAlertController/AXAlertController/AXActionSheet.m: -------------------------------------------------------------------------------- 1 | // 2 | // AXActionSheet.m 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/5/28. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import "AXActionSheet.h" 27 | 28 | @interface AXAlertView (SubclassHooks) 29 | - (void)initializer; 30 | 31 | + (BOOL)usingAutolayout; 32 | @end 33 | 34 | @interface AXActionSheet () { 35 | UIView *__weak _transitionView; 36 | } 37 | 38 | @property(readonly, nonatomic) UIView *transitionView; 39 | @property(strong, nonatomic) UIView *animatingView; 40 | @end 41 | 42 | @implementation AXActionSheet 43 | #pragma mark - Life cycle 44 | - (void)initializer { 45 | [super initializer]; 46 | super.horizontalLimits = 0; 47 | super.preferredMargin = UIEdgeInsetsMake(64, 0, 0, 0); 48 | super.cornerRadius = .0; 49 | super.maxAllowedWidth = 10000.0; 50 | self.verticalOffset = kAXAlertVertivalOffsetPinToBottom; 51 | 52 | if (![[self class] usingAutolayout]) self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin; 53 | } 54 | 55 | - (void)dealloc {} 56 | 57 | #pragma mark - Override. 58 | - (void)layoutSubviews { 59 | [super layoutSubviews]; 60 | } 61 | 62 | - (void)viewWillShow:(AXAlertView *)alertView animated:(BOOL)animated { 63 | [self setNeedsLayout]; 64 | [self layoutIfNeeded]; 65 | 66 | [self _addupAnimatingViewWithHeight:-0.1]; 67 | 68 | [super viewWillShow:alertView animated:animated]; 69 | } 70 | 71 | - (void)show:(BOOL)animated { 72 | if (self->_processing) return; 73 | [self viewWillShow:self animated:animated]; 74 | __weak typeof(self) wself = self; 75 | 76 | CGRect rect_content = self.contentView.frame; 77 | if ([[self class] usingAutolayout]) { 78 | self.contentView.transform = CGAffineTransformMakeTranslation(0, CGRectGetHeight(self.contentView.frame)); 79 | } else { 80 | CGRect frame = rect_content; 81 | frame.origin.y = CGRectGetHeight(self.bounds); 82 | self.contentView.frame = frame; 83 | } 84 | 85 | CGRect rect = _animatingView.frame; rect.size.height = 0.0; 86 | if (animated) [UIView animateWithDuration:0.45 delay:0.05 usingSpringWithDamping:1.0 initialSpringVelocity:1.0 options:7 animations:^{ 87 | if ([[self class] usingAutolayout]) { 88 | self.contentView.transform = CGAffineTransformIdentity; 89 | } else { 90 | [self.contentView setFrame:rect_content]; 91 | } 92 | 93 | [_animatingView setFrame:rect]; 94 | } completion:^(BOOL finished) { 95 | if (finished) { 96 | [wself viewDidShow:wself animated:animated]; 97 | } 98 | }]; else { 99 | [self viewDidShow:self animated:NO]; 100 | } 101 | } 102 | 103 | - (void)viewDidShow:(AXAlertView *)alertView animated:(BOOL)animated { 104 | [super viewDidShow:alertView animated:animated]; 105 | 106 | // [self.animatingView removeFromSuperview]; 107 | } 108 | 109 | - (void)viewWillHide:(AXAlertView *)alertView animated:(BOOL)animated { 110 | // [self _addupAnimatingViewWithHeight:.0]; 111 | // UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.contentView.frame]; 112 | // imageView.contentMode = UIViewContentModeScaleAspectFill; 113 | // imageView.image = [self _renderedImageOfView:self.contentView.window]; 114 | UIView *transitionView = [self.window resizableSnapshotViewFromRect:[self.window convertRect:self.contentView.frame fromView:self] afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero]; 115 | [transitionView setFrame:self.contentView.frame]; 116 | self.contentView.hidden = YES; 117 | [self addSubview:transitionView]; 118 | _transitionView = transitionView; 119 | 120 | [self setNeedsLayout]; 121 | [self layoutIfNeeded]; 122 | 123 | [super viewWillHide:alertView animated:animated]; 124 | } 125 | 126 | - (void)hide:(BOOL)animated { 127 | if (self->_processing) return; 128 | [self viewWillHide:self animated:animated]; 129 | __weak typeof(self) wself = self; 130 | 131 | CGRect frame = self.contentView.frame; 132 | 133 | CGRect rect_anim = _animatingView.frame; 134 | rect_anim.origin.y = frame.origin.y; 135 | _animatingView.frame = rect_anim; 136 | 137 | CGRect rect = frame; 138 | if ([[self class] usingAutolayout]) { 139 | _transitionView.transform = CGAffineTransformIdentity; 140 | } else { 141 | rect.origin.y = CGRectGetHeight(self.bounds); 142 | } 143 | 144 | if (animated) [UIView animateWithDuration:0.25 delay:0.0 options:7 animations:^{ 145 | if ([[self class] usingAutolayout]) { 146 | _transitionView.transform = CGAffineTransformMakeTranslation(0, CGRectGetHeight(frame)); 147 | } else { 148 | _transitionView.frame = rect; 149 | } 150 | 151 | _animatingView.frame = frame; 152 | // self.alpha = 0.0; 153 | } completion:^(BOOL finished) { 154 | if (finished) { 155 | [wself viewDidHide:self animated:animated]; 156 | } 157 | }]; else { 158 | [self viewDidHide:self animated:NO]; 159 | } 160 | } 161 | 162 | - (void)viewDidHide:(AXAlertView *)alertView animated:(BOOL)animated { 163 | [super viewDidHide:alertView animated:animated]; 164 | 165 | self.contentView.hidden = NO; 166 | self.alpha = 1.0; 167 | self.contentView.transform = CGAffineTransformIdentity; 168 | [self.animatingView removeFromSuperview]; 169 | [_transitionView removeFromSuperview]; 170 | _transitionView = nil; 171 | } 172 | 173 | - (void)setActions:(AXActionSheetAction *)actions, ... { 174 | va_list args; 175 | va_start(args, actions); 176 | AXAlertViewAction *action; 177 | _actionItems = [@[] mutableCopy]; 178 | [_actionItems addObject:actions]; 179 | while ((action = va_arg(args, AXAlertViewAction *))) { 180 | [_actionItems addObject:action]; 181 | } 182 | va_end(args); 183 | // Resort the actions. 184 | [_actionItems filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary * _Nullable bindings) { 185 | if ([evaluatedObject isKindOfClass:[AXActionSheetAction class]]) { 186 | return YES; 187 | } else { 188 | return NO; 189 | } 190 | }]]; 191 | [_actionItems sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"style" ascending:YES]]]; 192 | [self _addupPlaceholderAction]; 193 | // Delays to configure action items at layouting subviews. 194 | if (!_processing && self.superview != nil) { 195 | [self setNeedsLayout]; 196 | [self layoutIfNeeded]; 197 | } 198 | } 199 | 200 | - (void)appendActions:(AXActionSheetAction *)actions, ... { 201 | va_list args; 202 | va_start(args, actions); 203 | AXAlertViewAction *action; 204 | if (!_actionItems) { 205 | _actionItems = [@[] mutableCopy]; 206 | } 207 | [_actionItems addObject:actions]; 208 | while ((action = va_arg(args, AXAlertViewAction *))) { 209 | [_actionItems addObject:action]; 210 | } 211 | va_end(args); 212 | [_actionItems filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary * _Nullable bindings) { 213 | if ([evaluatedObject isKindOfClass:[AXActionSheetAction class]]) { 214 | return YES; 215 | } else { 216 | return NO; 217 | } 218 | }]]; 219 | [_actionItems sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"style" ascending:YES]]]; 220 | [self _addupPlaceholderAction]; 221 | // Delays to configure action items at layouting subviews. 222 | if (!_processing && self.superview != nil) { 223 | [self setNeedsLayout]; 224 | [self layoutIfNeeded]; 225 | } 226 | } 227 | 228 | - (void)setActionConfiguration:(AXAlertViewActionConfiguration *)configuration forKey:(NSString *)key { 229 | [super setActionConfiguration:configuration forKey:key]; 230 | 231 | [self _addupPlaceholderAction]; 232 | } 233 | 234 | - (void)setTranslucent:(BOOL)translucent { 235 | [super setTranslucent:translucent]; 236 | 237 | [self _addupPlaceholderAction]; 238 | } 239 | 240 | - (void)setTranslucentStyle:(AXAlertViewTranslucentStyle)translucentStyle { 241 | [super setTranslucentStyle:translucentStyle]; 242 | 243 | [self _addupPlaceholderAction]; 244 | } 245 | 246 | #pragma mark - Getters. 247 | - (UIView *)transitionView { return _transitionView; } 248 | - (UIView *)animatingView { 249 | if (_animatingView) return _animatingView; 250 | _animatingView = [UIView new]; 251 | return _animatingView; 252 | } 253 | #pragma mark - Setters. 254 | - (void)setHorizontalLimits:(NSInteger)horizontalLimits { 255 | [super setHorizontalLimits:0]; 256 | } 257 | 258 | - (void)setPreferedMargin:(AXEdgeMargins)preferedMargin { 259 | [super setPreferredMargin:UIEdgeInsetsMake(preferedMargin.top, 0, 0, 0)]; 260 | } 261 | 262 | - (void)setCornerRadius:(CGFloat)cornerRadius { 263 | [super setCornerRadius:.0]; 264 | } 265 | 266 | - (void)setMaxAllowedWidth:(CGFloat)maxAllowedWidth { 267 | [super setMaxAllowedWidth:10000.0]; 268 | } 269 | 270 | - (void)setVerticalOffset:(CGFloat)verticalOffset { 271 | [super setVerticalOffset:kAXAlertVertivalOffsetPinToBottom]; 272 | } 273 | #pragma mark - Private. 274 | - (UIImage *)_renderedImageOfView:(UIView *)view { 275 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [UIScreen mainScreen].scale); 276 | [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 277 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 278 | UIGraphicsEndImageContext(); 279 | return image; 280 | } 281 | 282 | - (void)_addupAnimatingViewWithHeight:(CGFloat)height { 283 | CGSize size = self.contentView.bounds.size; 284 | [self.animatingView setFrame:CGRectMake(0, CGRectGetHeight(self.bounds)-size.height, size.width, size.height)]; 285 | [_animatingView setBackgroundColor:[UIColor colorWithWhite:0 alpha:self.opacity]]; 286 | [_animatingView.layer setCornerRadius:self.cornerRadius]; 287 | [_animatingView.layer setMasksToBounds:YES]; 288 | if (height >= 0) { 289 | CGRect rect = _animatingView.frame; 290 | rect.size.height = height; 291 | _animatingView.frame = rect; 292 | } 293 | [self insertSubview:_animatingView belowSubview:self.contentView]; 294 | } 295 | 296 | - (void)_addupPlaceholderAction { 297 | if (_actionItems.count >= 2) { 298 | if ([_actionItems[_actionItems.count-2] isKindOfClass:[AXAlertViewPlaceholderAction class]]) { 299 | [_actionItems removeObjectAtIndex:_actionItems.count-2]; 300 | } 301 | } 302 | if ([_actionItems indexOfObjectPassingTest:^BOOL(AXAlertViewAction * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 303 | if (((AXActionSheetAction *)obj).style == AXActionSheetActionStyleCancel) { 304 | *stop = YES; 305 | return YES; 306 | } else { 307 | return NO; 308 | } 309 | }] != NSNotFound) { 310 | if ([_actionItems.lastObject isKindOfClass:[AXActionSheetAction class]]) { 311 | NSString *ident = _actionItems.lastObject.identifier; 312 | NSString *key = ident.length?ident:[NSString stringWithFormat:@"%@", @(_actionItems.count-1)]; 313 | if (_actionConfig[key] != nil) { 314 | [_actionConfig setObject:_actionConfig[key] forKey:ident.length?ident:[NSString stringWithFormat:@"%@", @(_actionItems.count)]]; 315 | } 316 | 317 | AXAlertViewPlaceholderActionConfiguration *config = [AXAlertViewPlaceholderActionConfiguration new]; 318 | config.heightForLayout = 10; 319 | if (self.translucent) { 320 | if (self.translucentStyle == AXAlertViewTranslucentLight) { 321 | config.backgroundColor = [UIColor colorWithWhite:0.98 alpha:0.7]; 322 | } else { 323 | config.backgroundColor = [UIColor colorWithWhite:0.11 alpha:0.6]; 324 | } 325 | } else { 326 | config.backgroundColor = [self.backgroundColor colorWithAlphaComponent:0.8]; 327 | } 328 | 329 | [_actionConfig setObject:config forKey:@"cancel_placeholder"]; 330 | 331 | AXAlertViewPlaceholderAction *placeholder = [AXAlertViewPlaceholderAction new]; 332 | placeholder.identifier = @"cancel_placeholder"; 333 | [_actionItems insertObject:placeholder atIndex:_actionItems.count-1]; 334 | } 335 | } 336 | } 337 | @end 338 | 339 | @implementation AXActionSheetAction 340 | + (instancetype)actionWithTitle:(NSString *)title style:(AXActionSheetActionStyle)style handler:(AXAlertViewActionHandler)handler { 341 | AXActionSheetAction *action = [super actionWithTitle:title handler:handler]; 342 | action.style = style; 343 | return action; 344 | } 345 | 346 | + (instancetype)actionWithTitle:(NSString *)title image:(UIImage *)image style:(AXActionSheetActionStyle)style handler:(AXAlertViewActionHandler)handler { 347 | AXActionSheetAction *action = [super actionWithTitle:title image:image handler:handler]; 348 | action.style = style; 349 | return action; 350 | } 351 | @end 352 | -------------------------------------------------------------------------------- /AXAlertController/AXAlertController/AXAlertConstant.h: -------------------------------------------------------------------------------- 1 | // 2 | // AXAlertConstant.h 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/6/7. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #ifndef AXAlertConstant_h 27 | #define AXAlertConstant_h 28 | 29 | 30 | #endif /* AXAlertConstant_h */ 31 | 32 | static BOOL AX_ALERT_AVAILABLE_ON_PLATFORM(NSString *plat) { 33 | NSString *systemVersion = [[UIDevice currentDevice].systemVersion copy]; 34 | NSArray *comp = [systemVersion componentsSeparatedByString:@"."]; 35 | if (comp.count == 0 || comp.count == 1) { 36 | systemVersion = [NSString stringWithFormat:@"%@.0.0", systemVersion]; 37 | } else if (comp.count == 2) { 38 | systemVersion = [NSString stringWithFormat:@"%@.0", systemVersion]; 39 | } 40 | NSComparisonResult result = [systemVersion compare:plat options:NSNumericSearch]; 41 | return result == NSOrderedSame || result == NSOrderedDescending; 42 | } 43 | -------------------------------------------------------------------------------- /AXAlertController/AXAlertController/AXAlertController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AXAlertController.h 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/5/27. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import 27 | #import "AXAlertView.h" 28 | #import "AXActionSheet.h" 29 | NS_ASSUME_NONNULL_BEGIN 30 | @class AXAlertAction; 31 | 32 | typedef NS_ENUM(NSInteger, AXAlertControllerStyle) { 33 | AXAlertControllerStyleActionSheet = 0, 34 | AXAlertControllerStyleAlert 35 | }; 36 | 37 | typedef NS_ENUM(NSInteger, AXAlertActionStyle) { 38 | AXAlertActionStyleDefault = 0, 39 | AXAlertActionStyleCancel 40 | }; 41 | 42 | typedef void(^AXAlertActionHandler)(AXAlertAction *__weak _Nonnull action); 43 | @interface AXAlertAction : NSObject 44 | 45 | + (instancetype)actionWithTitle:(nullable NSString *)title handler:(nullable AXAlertActionHandler)handler; 46 | 47 | @property(copy, nonatomic, nullable) NSString *identifier; 48 | @property(readonly, nonatomic, nullable) NSString *title; 49 | @property(readonly, nonatomic) AXAlertActionStyle style; 50 | @end 51 | 52 | @interface AXAlertAction (Extensions) 53 | + (instancetype)actionWithTitle:(nullable NSString *)title style:(AXAlertActionStyle)style handler:(nullable AXAlertActionHandler)handler; 54 | + (instancetype)actionWithTitle:(nullable NSString *)title image:(nullable UIImage *)image style:(AXAlertActionStyle)style handler:(nullable AXAlertActionHandler)handler; 55 | @end 56 | 57 | @interface AXAlertActionConfiguration : AXAlertViewActionConfiguration @end 58 | 59 | @interface AXAlertController : UIViewController 60 | /// Alert view. 61 | @property(readonly, nonatomic) AXAlertView *alertView; 62 | 63 | @property(nullable, nonatomic, copy) NSString *title; 64 | @property(nullable, nonatomic, copy) NSString *message; 65 | @property (nonatomic, readonly) NSArray *actions; 66 | 67 | @property(readonly, nonatomic) AXAlertControllerStyle preferredStyle; 68 | 69 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message preferredStyle:(AXAlertControllerStyle)preferredStyle; 70 | 71 | - (void)addAction:(AXAlertAction *)action; 72 | @end 73 | 74 | @interface AXAlertController (Configuration) 75 | - (void)addAction:(AXAlertAction *)action configuration:(nullable AXAlertActionConfiguration *)config; 76 | - (void)addAction:(AXAlertAction *)action configurationHandler:(void (^__nullable)(AXAlertActionConfiguration *config))configuration; 77 | @end 78 | 79 | @interface AXAlertController (Image) 80 | @property(nonatomic, nullable) UIImage *image; 81 | 82 | + (instancetype)alertControllerWithTitle:(nullable NSString *)title message:(nullable NSString *)message image:(nullable UIImage *)image preferredStyle:(AXAlertControllerStyle)preferredStyle; 83 | - (void)configureImageViewWithHandler:(void (^ __nullable)(UIImageView *imageView))handler; 84 | @end 85 | 86 | @interface AXAlertController (TextField) 87 | @property (nullable, nonatomic, readonly) NSArray *textFields; 88 | 89 | - (void)addTextFieldWithConfigurationHandler:(void (^ __nullable)(UITextField *textField))configurationHandler; 90 | @end 91 | NS_ASSUME_NONNULL_END 92 | -------------------------------------------------------------------------------- /AXAlertController/AXAlertController/AXAlertController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AXAlertController.m 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/5/27. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import "AXAlertController.h" 27 | #import "AXAlertConstant.h" 28 | 29 | #ifndef AXAlertViewHooks 30 | #define AXAlertViewHooks(_CustomView) @interface _CustomView : AXAlertView @end @implementation _CustomView @end 31 | #endif 32 | #ifndef AXActionSheetHooks 33 | #define AXActionSheetHooks(_CustomView) @interface _CustomView : AXActionSheet @end @implementation _CustomView @end 34 | #endif 35 | #ifndef AXAlertCustomSuperViewHooks 36 | #define AXAlertCustomSuperViewHooks(_CustomView, CocoaView) @protocol _AXAlertCustomSuperViewDelegate \ 37 | - (void)viewWillMoveToSuperview:(UIView *)newSuperView;\ 38 | - (void)viewDidMoveToSuperview;\ 39 | @end @interface _CustomView : CocoaView\ 40 | @property(weak, nonatomic) id<_AXAlertCustomSuperViewDelegate> delegate;\ 41 | @end @implementation _CustomView\ 42 | - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; [_delegate viewWillMoveToSuperview:newSuperview]; }\ 43 | - (void)didMoveToSuperview { [super didMoveToSuperview]; [_delegate viewDidMoveToSuperview]; }\ 44 | @end 45 | #endif 46 | #ifndef AXAlertCustomViewHooks2 47 | #define AXAlertCustomViewHooks2(_CustomView, CocoaView) @interface _CustomView : CocoaView @end @implementation _CustomView @end 48 | #endif 49 | #ifndef AXAlertCustomExceptionViewHooks 50 | #define AXAlertCustomExceptionViewHooks(_ExceptionView, View) @interface _ExceptionView : View@property(assign, nonatomic) CGRect exceptionFrame __deprecated_msg("Using dimming contet image instead.");@property(assign, nonatomic) CGFloat cornerRadius __deprecated_msg("Using dimming contet image instead.");@property(assign, nonatomic) CGFloat opacity __deprecated_msg("Using dimming contet image instead.");@end@implementation _ExceptionView - (void)drawRect:(CGRect)rect {[super drawRect:rect];CGContextRef context = UIGraphicsGetCurrentContext();CGPathRef outterPath = CGPathCreateWithRect(self.frame, nil);CGContextAddPath(context, outterPath);CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0 alpha:_opacity].CGColor);CGContextFillPath(context);CGPathRelease(outterPath);CGRect rectOfContainerView =_exceptionFrame;if (CGRectGetWidth(rectOfContainerView) < _cornerRadius*2 || CGRectGetHeight(rectOfContainerView) < _cornerRadius*2) return;CGPathRef innerPath = CGPathCreateWithRoundedRect(rectOfContainerView, _cornerRadius, _cornerRadius, nil);CGContextAddPath(context, innerPath);CGContextSetBlendMode(context, kCGBlendModeClear);CGContextFillPath(context);CGPathRelease(innerPath);}@end 51 | #endif 52 | #ifndef AXAlertControllerDelegateHooks 53 | #define AXAlertControllerDelegateHooks(_Delegate) @interface AXAlertController (_Delegate) <_Delegate> @end 54 | #endif 55 | 56 | AXAlertViewHooks(_AXAlertControllerAlertContentView) 57 | AXActionSheetHooks(_AXAlertControllerSheetContentView) 58 | AXAlertCustomSuperViewHooks(_AXAlertExceptionView, UIImageView) 59 | AXAlertCustomExceptionViewHooks(_AXAlertControllerView, _AXAlertExceptionView) 60 | AXAlertCustomViewHooks2(_AXAlertKeybboardAlignmentView, UIImageView) 61 | 62 | AXAlertControllerDelegateHooks(_AXAlertCustomSuperViewDelegate) 63 | @interface AXAlertView (Private) 64 | - (BOOL)processing;// Access to `_processing`, Used inside the module. 65 | - (void)_layoutSubviews;// Layout subviews. 66 | + (BOOL)usingAutolayout; 67 | + (UIImage *)_dimmingKnockoutImageOfExceptionRect:(CGRect)exceptionRect cornerRadius:(CGFloat)cornerRadius inRect:(CGRect)mainBounds opacity:(CGFloat)opacity; 68 | @end 69 | 70 | AXAlertCustomViewHooks2(_AXAlertTextfield, UITextField) 71 | 72 | @interface _AXAlertContentBackgroundView: UIView 73 | /// Text field. 74 | @property(readwrite, nonatomic) _AXAlertTextfield *textfield; 75 | /// Effect view. 76 | @property(strong, nonatomic) UIVisualEffectView *effectView; 77 | /// Effect mask view. 78 | @property(strong, nonatomic) UIImageView *effectMasksView; 79 | /// Background color view. 80 | @property(strong, nonatomic) UIImageView *backgroundColorView; 81 | /// Overrides light effect. 82 | @property(assign, nonatomic) BOOL overridesLightStyle; 83 | @end 84 | @interface _AXAlertControllerContentView: UIView 85 | /// Stack view for using autolayout. 86 | @property(strong, nonatomic) UIStackView *stackView; 87 | /// Content label. 88 | @property(strong, nonatomic) UILabel *contentLabel; 89 | /// Content image view. 90 | @property(strong, nonatomic) UIImageView *imageView; 91 | /// Image top margin. Defaults to 10.0. 92 | @property(assign, nonatomic) CGFloat padding; 93 | /// Text fields. 94 | @property(copy, nonatomic) NSMutableArray *textFields; 95 | /// Translucent. 96 | @property(assign, nonatomic) BOOL translucent; 97 | /// Translucent style. 98 | @property(assign, nonatomic) AXAlertViewTranslucentStyle translucentStyle; 99 | 100 | - (void)addTextFieldWithConfigurationHandler:(void (^)(UITextField * _Nonnull))configurationHandler; 101 | - (void)disableVisualEffects; 102 | - (void)enableVisualEffects; 103 | @end 104 | 105 | @interface AXAlertAction () { 106 | // Handler block of action. 107 | AXAlertActionHandler _handler; 108 | 109 | NSString *__title; 110 | uint64_t __style; 111 | UIImage *__image; 112 | } 113 | @property(readonly, nonatomic) AXAlertViewAction *alertViewAction; 114 | @property(readonly, nonatomic) AXActionSheetAction *actionSheetAction; 115 | @end 116 | 117 | @implementation AXAlertAction 118 | - (instancetype)initWithTitle:(NSString *)title image:(UIImage *)image style:(AXAlertActionStyle)style handler:(AXAlertActionHandler)handler { 119 | if (self = [super init]) { 120 | _handler = [handler copy]; 121 | __title = [title copy]; 122 | __style = style; 123 | __image = image; 124 | } 125 | return self; 126 | } 127 | 128 | - (id)copyWithZone:(NSZone *)zone { 129 | AXAlertAction *action = [[AXAlertAction allocWithZone:zone] init]; 130 | action.identifier = _identifier; 131 | action->_handler = [_handler copy]; 132 | action->__title = [__title copy]; 133 | action->__image = __image; 134 | action->__style = __style; 135 | return action; 136 | } 137 | 138 | + (instancetype)actionWithTitle:(NSString *)title handler:(AXAlertActionHandler)handler { 139 | return [self actionWithTitle:title style:AXAlertActionStyleDefault handler:handler]; 140 | } 141 | 142 | + (instancetype)actionWithTitle:(NSString *)title style:(AXAlertActionStyle)style handler:(AXAlertActionHandler)handler { 143 | return [self actionWithTitle:title image:nil style:style handler:handler]; 144 | } 145 | 146 | + (instancetype)actionWithTitle:(NSString *)title image:(UIImage *)image style:(AXAlertActionStyle)style handler:(AXAlertActionHandler)handler { 147 | return [[self alloc] initWithTitle:title image:image style:style handler:handler]; 148 | } 149 | 150 | - (NSString *)title { return [__title copy]; } 151 | - (AXAlertActionStyle)style { return __style; } 152 | 153 | - (AXAlertViewAction *)alertViewAction { 154 | AXAlertViewAction *_a = [AXAlertViewAction actionWithTitle:[__title copy] image:__image handler:^(AXAlertViewAction * _Nonnull __weak action) { 155 | if (_handler != NULL) { __weak typeof(self) wself = self; _handler(wself); } 156 | }]; 157 | _a.identifier = self.identifier; 158 | return _a; 159 | } 160 | 161 | - (AXActionSheetAction *)actionSheetAction { 162 | AXActionSheetAction *_a = [AXActionSheetAction actionWithTitle:[__title copy] image:__image style:__style handler:^(AXAlertViewAction * _Nonnull __weak action) { 163 | if (_handler != NULL) { __weak typeof(self) wself = self; _handler(wself); } 164 | }]; 165 | _a.identifier = self.identifier; 166 | return _a; 167 | } 168 | @end @implementation AXAlertActionConfiguration @end 169 | 170 | @implementation _AXAlertContentBackgroundView 171 | - (instancetype)init { 172 | if (self = [super init]) { 173 | self.clipsToBounds = YES; 174 | self.overridesLightStyle = YES; 175 | [self addSubview:self.effectView]; 176 | [self addSubview:self.backgroundColorView]; 177 | if ([AXAlertView usingAutolayout]) { 178 | _effectView.translatesAutoresizingMaskIntoConstraints = NO; 179 | _backgroundColorView.translatesAutoresizingMaskIntoConstraints = NO; 180 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_effectView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectView)]]; 181 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_effectView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectView)]]; 182 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0.5-[_backgroundColorView]-0.5-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_backgroundColorView)]]; 183 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0.5-[_backgroundColorView]-0.5-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_backgroundColorView)]]; 184 | } 185 | } return self; 186 | } 187 | 188 | - (CGSize)sizeThatFits:(CGSize)size { 189 | CGSize susize = [super sizeThatFits:size]; 190 | [self layoutSubviews]; 191 | susize.height = CGRectGetHeight(self.bounds); 192 | return susize; 193 | } 194 | 195 | - (void)layoutSubviews { 196 | [super layoutSubviews]; 197 | 198 | if (![AXAlertView usingAutolayout]) { 199 | CGSize sizeOfTxf = CGSizeMake(CGRectGetWidth(self.bounds)-10, _textfield.font.pointSize); 200 | CGFloat heightOfSelf = sizeOfTxf.height + 10; 201 | 202 | CGRect rect = self.frame; 203 | rect.size.height = heightOfSelf; 204 | [self setFrame:rect]; 205 | 206 | [_effectView setFrame:self.bounds]; 207 | [_effectMasksView setFrame:_effectView.bounds]; 208 | [_backgroundColorView setFrame:CGRectMake(0.5, 0.5, CGRectGetWidth(self.bounds)-1, CGRectGetHeight(self.bounds)-1)]; 209 | [_textfield setFrame:CGRectMake(5, 5, sizeOfTxf.width, sizeOfTxf.height)]; 210 | } 211 | } 212 | 213 | - (void)setTextfield:(_AXAlertTextfield *)textfield { 214 | _textfield = textfield; 215 | [self addSubview:_textfield]; 216 | if ([AXAlertView usingAutolayout]) { 217 | _textfield.translatesAutoresizingMaskIntoConstraints = NO; 218 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[_textfield]-5-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_textfield)]]; 219 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-5-[_textfield]-5-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_textfield)]]; 220 | } else { 221 | [self setNeedsLayout]; 222 | } 223 | } 224 | 225 | - (void)setOverridesLightStyle:(BOOL)overridesLightStyle { 226 | _overridesLightStyle = overridesLightStyle; 227 | [self _resetEffectView]; 228 | } 229 | 230 | - (UIVisualEffectView *)effectView { 231 | if (_effectView) return _effectView; 232 | _effectView = [[UIVisualEffectView alloc] initWithEffect:[UIVibrancyEffect effectForBlurEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]]]; 233 | [_effectView.contentView addSubview:self.effectMasksView]; 234 | if ([AXAlertView usingAutolayout]) { 235 | _effectView.translatesAutoresizingMaskIntoConstraints = NO; 236 | _effectMasksView.translatesAutoresizingMaskIntoConstraints = NO; 237 | [_effectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_effectMasksView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectMasksView)]]; 238 | [_effectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_effectMasksView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectMasksView)]]; 239 | } 240 | return _effectView; 241 | } 242 | 243 | - (UIImageView *)effectMasksView { 244 | if (_effectMasksView) return _effectMasksView; 245 | _effectMasksView = [UIImageView new]; 246 | [_effectMasksView setBackgroundColor:[UIColor clearColor]]; 247 | _effectMasksView.layer.borderWidth = 0.5; 248 | _effectMasksView.layer.borderColor = [UIColor whiteColor].CGColor; 249 | return _effectMasksView; 250 | } 251 | 252 | - (UIImageView *)backgroundColorView { 253 | if (_backgroundColorView) return _backgroundColorView; 254 | _backgroundColorView = [UIImageView new]; 255 | _backgroundColorView.backgroundColor = [UIColor whiteColor]; 256 | return _backgroundColorView; 257 | } 258 | 259 | - (void)_resetEffectView { 260 | if (_effectView) { 261 | [_effectView removeFromSuperview]; 262 | } 263 | _effectView = [[UIVisualEffectView alloc] initWithEffect:[UIVibrancyEffect effectForBlurEffect:[UIBlurEffect effectWithStyle:_overridesLightStyle?UIBlurEffectStyleExtraLight:UIBlurEffectStyleDark]]]; 264 | [_effectView.contentView addSubview:self.effectMasksView]; 265 | if ([AXAlertView usingAutolayout]) { 266 | _effectView.translatesAutoresizingMaskIntoConstraints = NO; 267 | _effectMasksView.translatesAutoresizingMaskIntoConstraints = NO; 268 | [_effectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_effectMasksView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectMasksView)]]; 269 | [_effectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_effectMasksView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectMasksView)]]; 270 | } 271 | [self insertSubview:_effectView atIndex:0]; 272 | if ([AXAlertView usingAutolayout]) { 273 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_effectView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectView)]]; 274 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_effectView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_effectView)]]; 275 | } 276 | } 277 | @end 278 | @implementation _AXAlertControllerContentView 279 | #pragma mark - Life cycle. 280 | - (instancetype)init { 281 | if (self = [super init]) { 282 | [self initializer]; 283 | } return self; 284 | } 285 | 286 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 287 | if (self = [super initWithCoder:aDecoder]) { 288 | [self initializer]; 289 | } return self; 290 | } 291 | 292 | - (instancetype)initWithFrame:(CGRect)frame { 293 | if (self = [super initWithFrame:frame]) { 294 | [self initializer]; 295 | } return self; 296 | } 297 | 298 | - (void)initializer { 299 | _padding = 10.0; 300 | _textFields = [NSMutableArray array]; 301 | 302 | if ([AXAlertView usingAutolayout]) { 303 | [self addSubview:self.stackView]; 304 | [self _addContraintsOfStackViewToSelf]; 305 | [_stackView addArrangedSubview:self.contentLabel]; 306 | [_stackView addArrangedSubview:self.imageView]; 307 | } else { 308 | [self addSubview:self.contentLabel]; 309 | [self addSubview:self.imageView]; 310 | } 311 | } 312 | 313 | - (void)dealloc {} 314 | #pragma mark - Overrides. 315 | - (CGSize)sizeThatFits:(CGSize)size { 316 | CGSize susize = [super sizeThatFits:size]; 317 | [self layoutSubviews]; 318 | susize.height = CGRectGetHeight(self.bounds); 319 | return susize; 320 | } 321 | 322 | - (void)layoutSubviews { 323 | [super layoutSubviews]; 324 | if (![AXAlertView usingAutolayout]) { 325 | // Calculate size of content label. 326 | CGSize sizeOfContentLabel = CGSizeMake(CGRectGetWidth(self.bounds), .0); 327 | if (_contentLabel.numberOfLines == 0) { 328 | [_contentLabel sizeToFit]; 329 | sizeOfContentLabel.height = CGRectGetHeight(_contentLabel.bounds); 330 | } else { 331 | CGSize size = [_contentLabel.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:_contentLabel.font} context:NULL].size; 332 | sizeOfContentLabel.height = ceil(size.height); 333 | } 334 | // Calculate size of image view. 335 | CGSize sizeOfImageView = CGSizeMake(CGRectGetWidth(self.bounds), .0); 336 | sizeOfImageView.height = _imageView.image.size.height; 337 | 338 | CGRect rect_contentLabel = _contentLabel.frame; 339 | rect_contentLabel.size = sizeOfContentLabel; 340 | _contentLabel.frame = rect_contentLabel; 341 | 342 | CGRect rect_imageView = _imageView.frame; 343 | rect_imageView.origin.y = CGRectGetHeight(rect_contentLabel)+_padding; 344 | rect_imageView.size = sizeOfImageView; 345 | _imageView.frame = rect_imageView; 346 | 347 | CGFloat height = CGRectGetMaxY(rect_imageView); 348 | 349 | // Set up frames of text fields. 350 | for (int i = 0; i < _textFields.count; i++) { 351 | _AXAlertTextfield *txf = (_AXAlertTextfield *)[_textFields objectAtIndex:i]; 352 | _AXAlertContentBackgroundView *_bgnView = [self viewWithTag:i+1]; 353 | CGSize sizeOfBgnView = CGSizeMake(CGRectGetWidth(self.bounds), .0); 354 | sizeOfBgnView.height += 5*2; 355 | sizeOfBgnView.height += txf.font.pointSize; 356 | CGFloat originY = .0; 357 | if (i == 0) { 358 | originY = CGRectGetMaxY(rect_imageView) + _padding; 359 | } else { 360 | originY = CGRectGetMaxY([self viewWithTag:i].frame) + _padding; 361 | } 362 | CGRect rect = CGRectMake(0, originY, sizeOfBgnView.width, sizeOfBgnView.height); 363 | [_bgnView setFrame:rect]; 364 | 365 | if (i == _textFields.count - 1) { 366 | height = CGRectGetMaxY(rect); 367 | } 368 | } 369 | 370 | CGRect rect = self.frame; 371 | rect.size.height = height; 372 | [self setFrame:rect]; 373 | } 374 | } 375 | 376 | #pragma mark - Public. 377 | - (void)addTextFieldWithConfigurationHandler:(void (^)(UITextField * _Nonnull))configurationHandler { 378 | _AXAlertTextfield *textField = [_AXAlertTextfield new]; 379 | textField.borderStyle = UITextBorderStyleNone; 380 | textField.backgroundColor = [UIColor whiteColor]; 381 | textField.font = [UIFont systemFontOfSize:13]; 382 | textField.spellCheckingType = UITextSpellCheckingTypeNo; 383 | textField.autocorrectionType = UITextAutocorrectionTypeNo; 384 | textField.returnKeyType = UIReturnKeyNext; 385 | textField.delegate = self; 386 | 387 | if (configurationHandler) { 388 | configurationHandler(textField); 389 | } 390 | if ([AXAlertView usingAutolayout]) { 391 | _AXAlertContentBackgroundView * _textBackgroundView = [_AXAlertContentBackgroundView new]; 392 | [_textBackgroundView setTextfield:textField]; 393 | [_stackView addArrangedSubview:_textBackgroundView]; 394 | [_textFields addObject:textField]; 395 | } else { 396 | _AXAlertContentBackgroundView * _textBackgroundView = [_AXAlertContentBackgroundView new]; 397 | [_textBackgroundView setTextfield:textField]; 398 | _textBackgroundView.tag = _textFields.count+1; 399 | [self addSubview:_textBackgroundView]; 400 | [_textFields addObject:textField]; 401 | [self setNeedsLayout]; 402 | } 403 | } 404 | 405 | - (void)setTranslucent:(BOOL)translucent { 406 | _translucent = translucent; 407 | if (_translucent) { 408 | [self enableVisualEffects]; 409 | } else { 410 | [self disableVisualEffects]; 411 | } 412 | } 413 | 414 | - (void)setTranslucentStyle:(AXAlertViewTranslucentStyle)translucentStyle { 415 | _translucentStyle = translucentStyle; 416 | if ([AXAlertView usingAutolayout]) { 417 | for (UIView *view in self.stackView.arrangedSubviews) { 418 | if ([view isKindOfClass:[_AXAlertContentBackgroundView class]]) { 419 | _AXAlertContentBackgroundView *_bgnView = (_AXAlertContentBackgroundView *)view; 420 | [_bgnView setOverridesLightStyle:_translucentStyle == AXAlertViewTranslucentLight]; 421 | } 422 | } 423 | } else { 424 | for (int i = 0; i < _textFields.count; i++) { 425 | _AXAlertContentBackgroundView *_bgnView = [self viewWithTag:i+1]; 426 | [_bgnView setOverridesLightStyle:_translucentStyle == AXAlertViewTranslucentLight]; 427 | } 428 | } 429 | } 430 | 431 | - (void)disableVisualEffects { 432 | if ([AXAlertView usingAutolayout]) { 433 | for (UIView *view in self.stackView.arrangedSubviews) { 434 | if ([view isKindOfClass:[_AXAlertContentBackgroundView class]]) { 435 | _AXAlertContentBackgroundView *_bgnView = (_AXAlertContentBackgroundView *)view; 436 | _bgnView.layer.borderColor = [UIColor colorWithWhite:0 alpha:0.3].CGColor; 437 | _bgnView.layer.borderWidth = 0.5; 438 | [_bgnView.effectView setHidden:YES]; 439 | } 440 | } 441 | } else { 442 | for (int i = 0; i < _textFields.count; i++) { 443 | _AXAlertContentBackgroundView *_bgnView = [self viewWithTag:i+1]; 444 | _bgnView.layer.borderColor = [UIColor colorWithWhite:0 alpha:0.3].CGColor; 445 | _bgnView.layer.borderWidth = 0.5; 446 | [_bgnView.effectView setHidden:YES]; 447 | } 448 | } 449 | } 450 | 451 | - (void)enableVisualEffects { 452 | if ([AXAlertView usingAutolayout]) { 453 | for (UIView *view in self.stackView.arrangedSubviews) { 454 | if ([view isKindOfClass:[_AXAlertContentBackgroundView class]]) { 455 | _AXAlertContentBackgroundView *_bgnView = (_AXAlertContentBackgroundView *)view; 456 | _bgnView.layer.borderColor = [UIColor clearColor].CGColor; 457 | _bgnView.layer.borderWidth = 0.0; 458 | [_bgnView.effectView setHidden:NO]; 459 | } 460 | } 461 | } else { 462 | for (int i = 0; i < _textFields.count; i++) { 463 | _AXAlertContentBackgroundView *_bgnView = [self viewWithTag:i+1]; 464 | _bgnView.layer.borderColor = [UIColor clearColor].CGColor; 465 | _bgnView.layer.borderWidth = 0.0; 466 | [_bgnView.effectView setHidden:NO]; 467 | } 468 | } 469 | } 470 | #pragma mark - Getters. 471 | - (UIStackView *)stackView { 472 | if (_stackView) return _stackView; 473 | _stackView = [UIStackView new]; 474 | _stackView.translatesAutoresizingMaskIntoConstraints = NO; 475 | _stackView.axis = UILayoutConstraintAxisVertical; 476 | _stackView.distribution = UIStackViewDistributionFill; 477 | _stackView.alignment = UIStackViewAlignmentFill; 478 | _stackView.spacing = _padding; 479 | return _stackView; 480 | } 481 | 482 | - (UILabel *)contentLabel { 483 | if (_contentLabel) return _contentLabel; 484 | _contentLabel = [UILabel new]; 485 | _contentLabel.font = [UIFont systemFontOfSize:13]; 486 | _contentLabel.numberOfLines = 0; 487 | _contentLabel.textAlignment = NSTextAlignmentCenter; 488 | _contentLabel.backgroundColor = [UIColor clearColor]; 489 | if ([AXAlertView usingAutolayout]) { 490 | _contentLabel.translatesAutoresizingMaskIntoConstraints = NO; 491 | } 492 | return _contentLabel; 493 | } 494 | 495 | - (UIImageView *)imageView { 496 | if (_imageView) return _imageView; 497 | _imageView = [UIImageView new]; 498 | _imageView.backgroundColor = [UIColor clearColor]; 499 | return _imageView; 500 | } 501 | 502 | #pragma mark - Setters. 503 | - (void)setPadding:(CGFloat)padding { 504 | _padding = padding; 505 | if ([AXAlertView usingAutolayout]) { 506 | _stackView.spacing = _padding; 507 | } else { 508 | [self setNeedsLayout]; 509 | } 510 | } 511 | 512 | #pragma mark - UITextFieldDelegate. 513 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 514 | if (textField.returnKeyType == UIReturnKeyNext) { 515 | NSUInteger index = [_textFields indexOfObject:textField]; 516 | if (index != NSNotFound) { 517 | if (index == _textFields.count-1) index = 0; else { 518 | index++; 519 | } 520 | 521 | UITextField *_nextTextfield = [_textFields objectAtIndex:index]; 522 | if (_nextTextfield && [_nextTextfield canBecomeFirstResponder]) [_nextTextfield becomeFirstResponder]; 523 | } 524 | } 525 | return NO; 526 | } 527 | #pragma mark - Private. 528 | - (void)_addContraintsOfStackViewToSelf { 529 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_stackView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_stackView)]]; 530 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_stackView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_stackView)]]; 531 | } 532 | @end 533 | 534 | @interface AXAlertController () { 535 | BOOL _isBeingPresented;// Whether the alert controller is being presented. 536 | BOOL _isViewDidAppear;// Whether the view controller's view did appear. 537 | BOOL _animated;// Whether showing transition is animated or not. 538 | BOOL _isAlertShowsTranitionTriggered;// Whether the alert view has showed any once. 539 | BOOL _isAlertShowsTranitionFinished;// Whether the alert view did finish showing transition animation. 540 | 541 | BOOL _translucent;// Tmp storage of the translucent of the alert view. 542 | BOOL _shouldExceptArea __deprecated_msg("Using dimming content image instead."); 543 | /// Indicator is the keyboard alignment view is in animating or not. YES when animation is in processing, otherwise NO. 544 | BOOL _processingKeyboardAlignmentViewTransition; 545 | 546 | float _opacity; // Defaults to 0.4. 547 | NSLayoutConstraint *__weak _heightOfKeyboardAlignment;// Height layout contraint of the keyboard alignment view. 548 | 549 | AXAlertControllerStyle _style;// Style of the alert controller. 550 | NSMutableArray *_actions;// Alert actions of the alert view. 551 | } 552 | /// Underlying view. 553 | @property(strong, nonatomic) _AXAlertControllerView *underlyingView; 554 | /// Keyboard alignment view. 555 | @property(strong, nonatomic) _AXAlertKeybboardAlignmentView *keyboardAlignmentView; 556 | /// Content alert view. 557 | @property(strong, nonatomic) _AXAlertControllerAlertContentView *alertContentView; 558 | /// Content action sheet view. 559 | @property(strong, nonatomic) _AXAlertControllerSheetContentView *actionSheetContentView; 560 | /// Content view. 561 | @property(strong, nonatomic) _AXAlertControllerContentView *contentView; 562 | 563 | /// Set the style of the alert controller. 564 | - (void)_setStyle:(uint64_t)arg; 565 | /// Set should except area. 566 | - (void)_setShouldExceptArea:(BOOL)arg __deprecated_msg("Using dimming content image instead."); 567 | @end 568 | 569 | @implementation AXAlertController @dynamic title; 570 | #pragma mark - Life cycle. 571 | - (instancetype)init { 572 | if (self = [super init]) { 573 | [self initializer]; 574 | } 575 | return self; 576 | } 577 | 578 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 579 | if (self = [super initWithCoder:aDecoder]) { 580 | [self initializer]; 581 | } 582 | return self; 583 | } 584 | 585 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 586 | if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 587 | [self initializer]; 588 | } 589 | return self; 590 | } 591 | 592 | - (void)initializer { 593 | _opacity = 0.4; 594 | super.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; 595 | super.modalPresentationStyle = UIModalPresentationOverCurrentContext; 596 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 597 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeviceOrientationDidChangeNotification:) name:UIDeviceOrientationDidChangeNotification object:nil]; 598 | // _shouldExceptArea = YES; 599 | // Observe the notification of key board. 600 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillChangeFrameNotification:) name:UIKeyboardWillShowNotification object:nil]; 601 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillChangeFrameNotification:) name:UIKeyboardWillChangeFrameNotification object:nil]; 602 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleKeyboardWillChangeFrameNotification:) name:UIKeyboardWillHideNotification object:nil]; 603 | } 604 | 605 | - (void)dealloc { 606 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 607 | [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; 608 | 609 | [_alertContentView removeObserver:self forKeyPath:[AXAlertView usingAutolayout]?@"containerView.bounds":@"containerView.frame"]; 610 | [_actionSheetContentView removeObserver:self forKeyPath:[AXAlertView usingAutolayout]?@"containerView.bounds":@"containerView.frame"]; 611 | [_alertContentView removeObserver:self forKeyPath:@"containerView.center"]; 612 | [_actionSheetContentView removeObserver:self forKeyPath:@"containerView.center"]; 613 | [_alertContentView removeObserver:self forKeyPath:@"translucent"]; 614 | [_alertContentView removeObserver:self forKeyPath:@"translucentStyle"]; 615 | } 616 | 617 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 618 | if ([keyPath isEqualToString:@"containerView.bounds"] || [keyPath isEqualToString:@"containerView.frame"] || [keyPath isEqualToString:@"containerView.center"]) { 619 | // if (_shouldExceptArea) { 620 | // [self _enableExceptionArea]; 621 | // Replaced with: 622 | [self _setupContentImageOfDimmingView]; 623 | // } 624 | } else if ([keyPath isEqualToString:@"translucent"]) { 625 | BOOL translucent = [change[NSKeyValueChangeNewKey] boolValue]; 626 | [self.contentView setTranslucent:translucent]; 627 | } else if ([keyPath isEqualToString:@"translucentStyle"]) { 628 | NSUInteger style = [change[NSKeyValueChangeNewKey] integerValue]; 629 | [self.contentView setTranslucentStyle:style]; 630 | } else [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 631 | } 632 | 633 | + (instancetype)alertControllerWithTitle:(NSString *)title message:(NSString *)message preferredStyle:(AXAlertControllerStyle)preferredStyle { 634 | AXAlertController *alert = [[self alloc] init]; 635 | [alert _setStyle:preferredStyle]; 636 | alert.alertView.title = title; 637 | alert.alertView.customView = alert.contentView; 638 | alert.contentView.contentLabel.text = message; 639 | return alert; 640 | } 641 | 642 | + (instancetype)alertControllerWithTitle:(NSString *)title message:(NSString *)message image:(UIImage *)image preferredStyle:(AXAlertControllerStyle)preferredStyle { 643 | AXAlertController *alert = [self alertControllerWithTitle:title message:message preferredStyle:preferredStyle]; 644 | alert.image = image; 645 | return alert; 646 | } 647 | 648 | - (void)configureImageViewWithHandler:(void (^)(UIImageView * _Nonnull))handler { 649 | if (handler != NULL) { 650 | handler(_contentView.imageView); 651 | } 652 | } 653 | 654 | #pragma mark - Overrides. 655 | - (void)loadView { 656 | [super loadView]; 657 | [self.view addSubview:self.keyboardAlignmentView]; 658 | [self.view addSubview:self.underlyingView]; 659 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_underlyingView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_underlyingView)]]; 660 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_keyboardAlignmentView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_keyboardAlignmentView)]]; 661 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_underlyingView][_keyboardAlignmentView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_underlyingView, _keyboardAlignmentView)]]; 662 | NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:_keyboardAlignmentView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0.0]; 663 | [_keyboardAlignmentView addConstraint:height]; 664 | _heightOfKeyboardAlignment = height; 665 | 666 | [self _addContentViewToContainer]; 667 | } 668 | 669 | - (void)viewDidLoad { 670 | [super viewDidLoad]; 671 | // Do any additional setup after loading the view. 672 | } 673 | 674 | - (void)viewDidLayoutSubviews { 675 | [super viewDidLayoutSubviews]; 676 | 677 | [self _setupContentImageOfDimmingView];// Update the dimming background content image. 678 | if (!_isViewDidAppear && !_isAlertShowsTranitionTriggered) { 679 | if (_style == AXAlertControllerStyleActionSheet) { 680 | [self _addContentViewToContainer]; 681 | [self.alertView show:_animated]; 682 | } else { 683 | [self.alertView show:_animated]; 684 | if (_contentView.textFields.count > 0) { 685 | [_contentView.textFields.firstObject becomeFirstResponder]; 686 | } 687 | } 688 | } 689 | } 690 | 691 | - (void)viewWillAppear:(BOOL)animated { 692 | [super viewWillAppear:animated]; 693 | _isBeingPresented = [self isBeingPresented]; 694 | _animated = animated; 695 | } 696 | 697 | - (void)viewWillMoveToSuperview:(UIView *)newSuperView {} 698 | - (void)viewDidMoveToSuperview {} 699 | 700 | - (void)viewDidAppear:(BOOL)animated { 701 | [super viewDidAppear:animated]; 702 | 703 | _isViewDidAppear = YES; 704 | if (self.alertView.superview != self.underlyingView) { 705 | [self _addContentViewToView:self.underlyingView]; 706 | } 707 | } 708 | 709 | #pragma mark - Public. 710 | - (void)addAction:(AXAlertAction *)action { 711 | if (!_actions) _actions = [NSMutableArray array]; 712 | [_actions addObject:action]; 713 | 714 | if (_style == AXAlertControllerStyleActionSheet) { 715 | AXActionSheetAction *_action = action.actionSheetAction; 716 | if (action.style == AXAlertActionStyleCancel) { 717 | _action.identifier = @"__cancel_ac"; 718 | AXAlertViewActionConfiguration *cancel = [AXAlertViewActionConfiguration new]; 719 | cancel.backgroundColor = [UIColor whiteColor]; 720 | cancel.heightForLayout = 44; 721 | cancel.cornerRadius = .0; 722 | cancel.heightForSeparator = .0; 723 | cancel.tintColor = [UIColor redColor]; 724 | [self.alertView setActionConfiguration:cancel forKey:_action.identifier]; 725 | } 726 | [self.alertView appendActions:_action, nil]; 727 | } else { 728 | AXAlertViewAction *_action = action.alertViewAction; 729 | [self.alertView appendActions:_action, nil]; 730 | } 731 | } 732 | 733 | - (void)addAction:(AXAlertAction *)action configuration:(AXAlertActionConfiguration *)config { 734 | [self addAction:action]; 735 | if (config) [self.alertView setActionConfiguration:config forKey:action.identifier.length?action.identifier:[NSString stringWithFormat:@"%@", @(_actions.count-1)]]; 736 | } 737 | 738 | - (void)addAction:(AXAlertAction *)action configurationHandler:(void (^)(AXAlertActionConfiguration * _Nonnull))configuration { 739 | AXAlertActionConfiguration *config = [self.alertView.actionConfiguration copy]; 740 | 741 | if (configuration != NULL) { 742 | configuration(config); 743 | } 744 | 745 | [self addAction:action configuration:config]; 746 | } 747 | 748 | - (void)addTextFieldWithConfigurationHandler:(void (^)(UITextField * _Nonnull))configurationHandler { 749 | NSAssert(_style == AXAlertControllerStyleAlert, @"Text fields configurations support only alert style."); 750 | [_contentView addTextFieldWithConfigurationHandler:configurationHandler]; 751 | // Reset the inset of the custom view. 752 | UIEdgeInsets customViewInset = self.alertView.customViewInset; 753 | customViewInset.bottom = 12; 754 | [self.alertView setCustomViewInset:customViewInset]; 755 | } 756 | 757 | #pragma mark - Getters. 758 | - (AXAlertView *)alertView { return (_style==AXAlertControllerStyleActionSheet?self.actionSheetContentView:self.alertContentView); } 759 | - (NSArray *)actions { return [_actions copy]; } 760 | - (NSArray *)textFields { return [_contentView.textFields copy]; } 761 | - (NSString *)title { return _alertContentView.title; } 762 | - (NSString *)message { return _contentView.contentLabel.text; } 763 | - (UIImage *)image { return _contentView.imageView.image; } 764 | - (AXAlertControllerStyle)preferredStyle { return _style; } 765 | 766 | - (_AXAlertControllerContentView *)contentView { 767 | if (_contentView) return _contentView; 768 | _contentView = [_AXAlertControllerContentView new]; 769 | return _contentView; 770 | } 771 | 772 | - (_AXAlertKeybboardAlignmentView *)keyboardAlignmentView { 773 | if (_keyboardAlignmentView) return _keyboardAlignmentView; 774 | _keyboardAlignmentView = [_AXAlertKeybboardAlignmentView new]; 775 | _keyboardAlignmentView.translatesAutoresizingMaskIntoConstraints = NO; 776 | _keyboardAlignmentView.backgroundColor = [UIColor colorWithWhite:0 alpha:_opacity]; 777 | return _keyboardAlignmentView; 778 | } 779 | 780 | - (_AXAlertControllerView *)underlyingView { 781 | if (_underlyingView) return _underlyingView; 782 | _underlyingView = [_AXAlertControllerView new]; 783 | _underlyingView.translatesAutoresizingMaskIntoConstraints = NO; 784 | _underlyingView.userInteractionEnabled = YES; 785 | [_underlyingView setDelegate:self]; 786 | // [_underlyingView setOpacity:0.4]; 787 | [_underlyingView setContentMode:UIViewContentModeCenter]; 788 | [_underlyingView setBackgroundColor:[UIColor clearColor]]; 789 | [_underlyingView setClipsToBounds:YES]; 790 | return _underlyingView; 791 | } 792 | 793 | - (_AXAlertControllerAlertContentView *)alertContentView { 794 | if (_alertContentView) return _alertContentView; 795 | _alertContentView = [[_AXAlertControllerAlertContentView alloc] initWithFrame:self.underlyingView.bounds]; 796 | [_alertContentView setBackgroundColor:[UIColor whiteColor]]; 797 | _alertContentView.translatesAutoresizingMaskIntoConstraints = NO; 798 | _alertContentView.opacity = 0.0; 799 | _alertContentView.titleInset = UIEdgeInsetsMake(20, 16, 0, 16); 800 | _alertContentView.delegate = self; 801 | _alertContentView.customViewInset = UIEdgeInsetsMake(5, 15, 20, 15); 802 | _alertContentView.padding = 0; 803 | _alertContentView.cornerRadius = [AXAlertView usingAutolayout]?12.0:6; 804 | _alertContentView.actionItemMargin = 0; 805 | _alertContentView.actionItemPadding = 0; 806 | _alertContentView.titleLabel.numberOfLines = 0; 807 | _alertContentView.preferredMargin = UIEdgeInsetsMake(0, 25, 0, 25); 808 | _alertContentView.titleLabel.font = [UIFont boldSystemFontOfSize:17]; 809 | _alertContentView.titleLabel.textColor = [UIColor blackColor]; 810 | AXAlertViewActionConfiguration *config = [AXAlertViewActionConfiguration new]; 811 | config.backgroundColor = [UIColor whiteColor]; 812 | config.heightForLayout = 44; 813 | config.cornerRadius = .0; 814 | config.tintColor = [UIColor blackColor]; 815 | config.font = [UIFont systemFontOfSize:16]; 816 | [_alertContentView setActionConfiguration:config]; 817 | 818 | [_alertContentView addObserver:self forKeyPath:[AXAlertView usingAutolayout]?@"containerView.bounds":@"containerView.frame" options:NSKeyValueObservingOptionNew context:NULL]; 819 | [_alertContentView addObserver:self forKeyPath:@"containerView.center" options:NSKeyValueObservingOptionNew context:NULL]; 820 | [_alertContentView addObserver:self forKeyPath:@"translucent" options:NSKeyValueObservingOptionNew context:NULL]; 821 | [_alertContentView addObserver:self forKeyPath:@"translucentStyle" options:NSKeyValueObservingOptionNew context:NULL]; 822 | return _alertContentView; 823 | } 824 | 825 | - (_AXAlertControllerSheetContentView *)actionSheetContentView { 826 | if (_actionSheetContentView) return _actionSheetContentView; 827 | _actionSheetContentView = [[_AXAlertControllerSheetContentView alloc] initWithFrame:self.underlyingView.bounds]; 828 | [_actionSheetContentView setBackgroundColor:[UIColor whiteColor]]; 829 | _actionSheetContentView.translatesAutoresizingMaskIntoConstraints = NO; 830 | _actionSheetContentView.opacity = 0.0; 831 | _actionSheetContentView.titleInset = UIEdgeInsetsMake(20, 16, 0, 16); 832 | _actionSheetContentView.delegate = self; 833 | _actionSheetContentView.customViewInset = UIEdgeInsetsMake(5, 15, 20, 15); 834 | _actionSheetContentView.padding = 0; 835 | _actionSheetContentView.hidesOnTouch = YES; 836 | _actionSheetContentView.cornerRadius = [AXAlertView usingAutolayout]?12.0:6; 837 | _actionSheetContentView.actionItemMargin = 0; 838 | _actionSheetContentView.actionItemPadding = 0; 839 | _actionSheetContentView.titleLabel.numberOfLines = 0; 840 | _actionSheetContentView.preferredMargin = UIEdgeInsetsMake(52, 52, 52, 52); 841 | _actionSheetContentView.titleLabel.font = [UIFont boldSystemFontOfSize:17]; 842 | _actionSheetContentView.titleLabel.textColor = [UIColor blackColor]; 843 | AXAlertViewActionConfiguration *config = [AXAlertViewActionConfiguration new]; 844 | config.backgroundColor = [UIColor whiteColor]; 845 | config.heightForLayout = 44; 846 | config.cornerRadius = .0; 847 | config.tintColor = [UIColor blackColor]; 848 | [_actionSheetContentView setActionConfiguration:config]; 849 | 850 | [_actionSheetContentView addObserver:self forKeyPath:[AXAlertView usingAutolayout]?@"containerView.bounds":@"containerView.frame" options:NSKeyValueObservingOptionNew context:NULL]; 851 | [_actionSheetContentView addObserver:self forKeyPath:@"containerView.center" options:NSKeyValueObservingOptionNew context:NULL]; 852 | return _actionSheetContentView; 853 | } 854 | 855 | #pragma mark - Setters. 856 | - (void)setTitle:(NSString *)title { 857 | [_alertContentView setTitle:title]; 858 | } 859 | 860 | - (void)setMessage:(NSString *)message { 861 | [_contentView.contentLabel setText:message]; 862 | } 863 | 864 | - (void)setImage:(UIImage *)image { 865 | [_contentView.imageView setImage:image]; 866 | } 867 | 868 | - (void)setModalTransitionStyle:(UIModalTransitionStyle)modalTransitionStyle { 869 | [super setModalTransitionStyle:UIModalTransitionStyleCrossDissolve]; 870 | } 871 | 872 | - (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle { 873 | [super setModalPresentationStyle:UIModalPresentationOverCurrentContext]; 874 | } 875 | 876 | #pragma mark - AXAlertViewDelegate. 877 | - (void)alertViewWillShow:(AXAlertView *)alertView { 878 | _isAlertShowsTranitionTriggered = YES;// Disabled the more times show actions. 879 | if (_style == AXAlertControllerStyleActionSheet) { 880 | UIView *view = [_actionSheetContentView valueForKeyPath:@"animatingView"]; 881 | [view setBackgroundColor:[UIColor colorWithWhite:0 alpha:/*self.underlyingView.opacity*/_opacity]]; 882 | [self.underlyingView addSubview:view]; 883 | } else { 884 | if (!AX_ALERT_AVAILABLE_ON_PLATFORM(@"11.0.0")) { 885 | _translucent = self.alertView.translucent; 886 | self.alertView.translucent = NO; 887 | } 888 | } 889 | } 890 | 891 | - (void)alertViewDidShow:(AXAlertView *)alertView { 892 | _isAlertShowsTranitionFinished = YES; 893 | if (!AX_ALERT_AVAILABLE_ON_PLATFORM(@"11.0.0")) { 894 | [self _updatedTranslucentState]; 895 | } 896 | } 897 | 898 | - (void)alertViewWillHide:(AXAlertView *)alertView { 899 | if (_style == AXAlertControllerStyleActionSheet) { 900 | // [self _addContentViewToContainer]; 901 | UIView *transitionView = [_actionSheetContentView valueForKeyPath:@"transitionView"]; 902 | UIView *containerView = /*self.view.superview ?: self.underlyingView*/self.view.window; 903 | [containerView addSubview:transitionView]; 904 | } else { 905 | if (!AX_ALERT_AVAILABLE_ON_PLATFORM(@"11.0.0")) { 906 | _translucent = self.alertView.translucent; 907 | self.alertView.translucent = NO; 908 | [self.contentView disableVisualEffects]; 909 | } 910 | } 911 | [_contentView.textFields makeObjectsPerformSelector:@selector(resignFirstResponder)]; 912 | [self _dismiss:alertView]; 913 | } 914 | 915 | - (void)alertViewDidHide:(AXAlertView *)alertView { 916 | if (!AX_ALERT_AVAILABLE_ON_PLATFORM(@"11.0.0")) { 917 | [self _updatedTranslucentState]; 918 | } 919 | } 920 | 921 | #pragma mark - Actions. 922 | - (void)handleDeviceOrientationDidChangeNotification:(NSNotification *)aNote { 923 | // if (_style == AXAlertControllerStyleActionSheet) return; 924 | // [self _setShouldExceptArea:NO]; 925 | // [self performSelector:@selector(_enableShouldExceptArea) withObject:nil afterDelay:0.3]; 926 | } 927 | // UIKeyboardWillChangeFrameNotification 928 | - (void)handleKeyboardWillChangeFrameNotification:(NSNotification *)aNote { 929 | CGRect keyboardFrame = [[[aNote userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 930 | NSTimeInterval duration = [[[aNote userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; 931 | NSUInteger curve = [[[aNote userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]; 932 | 933 | [self _updateContraintsOfAlignmentViewAndContentViewWithHeight:CGRectGetHeight(keyboardFrame) duration:duration curve:curve]; 934 | } 935 | 936 | #pragma mark - Private. 937 | - (void)_dismiss:(id)sender { 938 | if (_isBeingPresented) { 939 | [self dismissViewControllerAnimated:YES completion:NULL]; 940 | } 941 | } 942 | 943 | - (void)_setStyle:(uint64_t)arg { _style = arg; } 944 | 945 | - (void)_setShouldExceptArea:(BOOL)arg { 946 | _shouldExceptArea = arg; 947 | // if (_shouldExceptArea) { 948 | // [self _enableExceptionArea]; 949 | // } else { 950 | // [self _disableExceptionArea]; 951 | //} 952 | } 953 | - (void)_enableShouldExceptArea __deprecated_msg("Using dimming content image instead.") { 954 | // [self _setShouldExceptArea:YES]; 955 | } 956 | 957 | - (void)_addContentViewToContainer { 958 | UIView *containerView = self.view.superview ?: self.underlyingView; 959 | if (_style == AXAlertControllerStyleAlert) { 960 | containerView = self.underlyingView; 961 | } 962 | [self _addContentViewToView:containerView]; 963 | } 964 | 965 | - (void)_addContentViewToView:(UIView *)view { 966 | if (self.alertView.superview) [self.alertView removeFromSuperview]; 967 | [view addSubview:self.alertView]; 968 | [view addConstraint:[NSLayoutConstraint constraintWithItem:self.alertView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0]]; 969 | [view addConstraint:[NSLayoutConstraint constraintWithItem:self.alertView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]]; 970 | [view addConstraint:[NSLayoutConstraint constraintWithItem:self.alertView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]]; 971 | [view addConstraint:[NSLayoutConstraint constraintWithItem:self.alertView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]]; 972 | 973 | [self.alertView _layoutSubviews]; 974 | // [self _enableExceptionArea]; 975 | // Replaced with: 976 | [self _setupContentImageOfDimmingView]; 977 | } 978 | 979 | - (void)_enableExceptionArea __deprecated_msg("Using dimming content image instead.") { /*return;*/ 980 | // [self.underlyingView setExceptionFrame:[[self.alertView valueForKeyPath:@"containerView.frame"] CGRectValue]]; 981 | // [self.underlyingView setCornerRadius:self.alertView.cornerRadius]; 982 | // [self.underlyingView setNeedsDisplay]; 983 | UIImage *image = [AXAlertView _dimmingKnockoutImageOfExceptionRect:[[self.alertView valueForKeyPath:@"containerView.frame"] CGRectValue] cornerRadius:self.alertView.cornerRadius inRect:self.underlyingView.bounds opacity:_opacity]; 984 | if (image) { 985 | [self.underlyingView setImage:image]; 986 | } 987 | } 988 | 989 | - (void)_disableExceptionArea __deprecated_msg("Using dimming content image instead.") { 990 | // [self.underlyingView setExceptionFrame:CGRectZero]; 991 | // [self.underlyingView setCornerRadius:.0]; 992 | // [self.underlyingView setNeedsDisplay]; 993 | [self.underlyingView setImage:nil]; 994 | } 995 | 996 | - (void)_setupContentImageOfDimmingView { 997 | UIImage *image = [AXAlertView _dimmingKnockoutImageOfExceptionRect:[[self.alertView valueForKeyPath:@"containerView.frame"] CGRectValue] cornerRadius:self.alertView.cornerRadius inRect:self.underlyingView.bounds opacity:_opacity]; 998 | if (image != nil) { 999 | [self.underlyingView setImage:image]; 1000 | } 1001 | } 1002 | 1003 | - (void)_updatedTranslucentState { 1004 | if (_translucent && _style == AXAlertControllerStyleAlert) { 1005 | [self.alertView setTranslucent:_translucent]; 1006 | } 1007 | } 1008 | 1009 | - (BOOL)_shouldBeginTransitionOfKeyboardAlignmentView { return !_processingKeyboardAlignmentViewTransition; } 1010 | /// Update contraints of views by animated. 1011 | - (void)_updateContraintsOfAlignmentViewAndContentViewWithHeight:(CGFloat)height duration:(NSTimeInterval)duration curve:(NSUInteger)curve { 1012 | if (![self _shouldBeginTransitionOfKeyboardAlignmentView]) return; 1013 | _processingKeyboardAlignmentViewTransition = YES; 1014 | _heightOfKeyboardAlignment.constant = height; 1015 | 1016 | if (!_isAlertShowsTranitionFinished) { 1017 | [UIView setAnimationsEnabled:NO]; 1018 | self.underlyingView.clipsToBounds = NO; 1019 | self.keyboardAlignmentView.hidden = YES; 1020 | self.underlyingView.transform = CGAffineTransformMakeTranslation(0, height/2); 1021 | [UIView setAnimationsEnabled:YES]; 1022 | [UIView animateWithDuration:duration delay:0.0 options:curve|UIViewAnimationOptionLayoutSubviews|UIViewAnimationOptionOverrideInheritedOptions animations:^{ 1023 | self.underlyingView.transform = CGAffineTransformIdentity; 1024 | } completion:^(BOOL finished) { 1025 | if (finished) { 1026 | self.underlyingView.clipsToBounds = YES; 1027 | self.keyboardAlignmentView.hidden = NO; 1028 | _processingKeyboardAlignmentViewTransition = NO; 1029 | } 1030 | }]; 1031 | } else { 1032 | _processingKeyboardAlignmentViewTransition = NO; 1033 | } 1034 | } 1035 | @end 1036 | -------------------------------------------------------------------------------- /AXAlertController/AXAlertController/AXAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // AXAlertView.h 3 | // AXAlertController 4 | // 5 | // Created by ai on 16/4/5. 6 | // Copyright © 2016年 devedbox. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | 26 | #import 27 | 28 | @class AXAlertViewAction; 29 | @class AXAlertViewActionConfiguration; 30 | @class AXAlertView; 31 | 32 | NS_ASSUME_NONNULL_BEGIN 33 | @protocol AXAlertViewDelegate 34 | @optional 35 | /// Called when the alert view is about to show in the container view. 36 | - (void)alertViewWillShow:(AXAlertView *)alertView; 37 | /// Called when the alert view did show in the container view. 38 | - (void)alertViewDidShow:(AXAlertView *)alertView; 39 | /// Called when the alert view is about to hide from the container view. 40 | - (void)alertViewWillHide:(AXAlertView *)alertView; 41 | /// Called when the alert view did hide from the container view. 42 | - (void)alertViewDidHide:(AXAlertView *)alertView; 43 | @end 44 | 45 | /// Defines the block callback when alert view is animating showing or hidding instead of using delegate. 46 | /// The block call back can eixst with the delegate. 47 | typedef void(^AXAlertViewShowsBlock)(AXAlertView *alertView, BOOL animated); 48 | /// Defines the block callback when the alert view is touched. 49 | typedef void(^AXAlertViewTouchBlock)(AXAlertView *alertView); 50 | 51 | /// A enum type represents the translucent style of the alert view. 52 | typedef NS_ENUM(NSInteger, AXAlertViewTranslucentStyle) { 53 | /// The light translucent style. 54 | AXAlertViewTranslucentLight, 55 | /// The dark translucent style. 56 | AXAlertViewTranslucentDark 57 | }; 58 | 59 | typedef UIEdgeInsets AXEdgeMargins; 60 | 61 | /// Bounds of the container view remain in the center. 62 | extern CGFloat const kAXAlertVertivalOffsetCenter; 63 | /// Bounds of the container view pin to the top. 64 | extern CGFloat const kAXAlertVertivalOffsetPinToTop; 65 | /// Bounds of the container view pin to the bottom. 66 | extern CGFloat const kAXAlertVertivalOffsetPinToBottom; 67 | 68 | /// UIAlertController 69 | @interface AXAlertView : UIView { 70 | @protected 71 | /// Is animation processing. 72 | BOOL _processing; 73 | /// Action items. 74 | NSMutableArray *_actionItems; 75 | /// Configuration for action items. 76 | NSMutableDictionary *_actionConfig; 77 | } 78 | /// Delegate. 79 | @property(weak, nonatomic, nullable) iddelegate; 80 | /// Title label. 81 | @property(readonly, nonatomic) UILabel *titleLabel; 82 | /// Title text color. Default is #FEB925. 83 | @property(strong, nonatomic, nullable) UIColor *titleColor UI_APPEARANCE_SELECTOR; 84 | /// Text font of title. Default is system bold 17 pt. 85 | @property(strong, nonatomic, nullable) UIFont *titleFont UI_APPEARANCE_SELECTOR; 86 | /// Translucent. Default is YES. 87 | @property(assign, nonatomic) BOOL translucent UI_APPEARANCE_SELECTOR; 88 | /// Hide alert view on touch. Defaults to NO. 89 | @property(assign, nonatomic) BOOL hidesOnTouch UI_APPEARANCE_SELECTOR; 90 | /// Show the separator view or not. Defaults to YES. 91 | @property(assign, nonatomic) BOOL showsSeparators UI_APPEARANCE_SELECTOR; 92 | /// Translucent style. Default is Light. 93 | @property(assign, nonatomic) AXAlertViewTranslucentStyle translucentStyle UI_APPEARANCE_SELECTOR; 94 | /// Content inset. Defaults to (0, 0, 0, 0) 95 | @property(assign, nonatomic) UIEdgeInsets contentInset UI_APPEARANCE_SELECTOR; 96 | /// Custom view inset. Defaults to (0, 10, 10, 10) 97 | @property(assign, nonatomic) UIEdgeInsets customViewInset UI_APPEARANCE_SELECTOR; 98 | /// Title label content inset. Defaults to (10, 10, 10, 10). 99 | @property(assign, nonatomic) UIEdgeInsets titleInset UI_APPEARANCE_SELECTOR; 100 | /// Content padding. Defaults to 10. 101 | @property(assign, nonatomic) CGFloat padding UI_APPEARANCE_SELECTOR; 102 | /// Action items padding. Defalt is 0. 103 | @property(assign, nonatomic) CGFloat actionItemPadding UI_APPEARANCE_SELECTOR; 104 | /// Action items margin. Default is 0. 105 | @property(assign, nonatomic) CGFloat actionItemMargin UI_APPEARANCE_SELECTOR; 106 | /// Offset on the vertical direction. Defaults to 0.0; 107 | @property(assign, nonatomic) CGFloat verticalOffset UI_APPEARANCE_SELECTOR; 108 | /// Horizontal action item limits. Defaults to 2. 109 | /// 110 | /// @discusstion This is a limits of horizontal action item. If the count of actions is more than the limits count, the action will show vertically. 111 | @property(assign, nonatomic) NSInteger horizontalLimits UI_APPEARANCE_SELECTOR; 112 | /// Opacity of the dimed background. Value between [0, 1]. Defaults to 0.4. 113 | @property(assign, nonatomic) CGFloat opacity UI_APPEARANCE_SELECTOR; 114 | /// Content preferred height. Default is 0. 115 | @property(assign, nonatomic) CGFloat preferredHeight UI_APPEARANCE_SELECTOR __deprecated; 116 | /// Content preferred edge margin. Default is 40. 117 | @property(assign, nonatomic) AXEdgeMargins preferredMargin UI_APPEARANCE_SELECTOR; 118 | /// Max width of the alert view. Default is 270. 119 | @property(assign, nonatomic) CGFloat maxAllowedWidth UI_APPEARANCE_SELECTOR; 120 | /// Corner radius. Default is 6. 121 | @property(assign, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR; 122 | /// Custom view. Defaults to nil. 123 | @property(strong, nonatomic, nullable) IBOutlet UIView *customView; 124 | /// Title of alert view. Defaults to nil. 125 | @property(nonatomic, nullable) NSString *title; 126 | /// Action item configuration. This is a default configuration of all action item. 127 | @property(strong, nonatomic, nonnull) AXAlertViewActionConfiguration *actionConfiguration UI_APPEARANCE_SELECTOR; 128 | /// Alert view will show block. 129 | @property(copy, nonatomic, nullable) AXAlertViewShowsBlock willShow; 130 | /// Alert view did show block. 131 | @property(copy, nonatomic, nullable) AXAlertViewShowsBlock didShow; 132 | /// Alert view will hide. 133 | @property(copy, nonatomic, nullable) AXAlertViewShowsBlock willHide; 134 | /// Alert view did hide. 135 | @property(copy, nonatomic, nullable) AXAlertViewShowsBlock didHide; 136 | /// Alert view did touch. 137 | @property(copy, nonatomic, nullable) AXAlertViewTouchBlock touch; 138 | /// Content view, shows the content of alert title and message and custom view. 139 | @property(readonly, nonatomic, nullable) UIView *contentView; 140 | /// Actions. 141 | @property(readonly, nonatomic, copy, nullable) NSArray *actionItems; 142 | /// Set the actions of the alert view with replacing of the old ones. 143 | /// @discusstion Using this method to update the actions if you want to 144 | /// replace the old actions with new actions. 145 | /// 146 | /// @param actions The actions to replace the old ones of A Mutable-Length va_list. 147 | /// 148 | - (void)setActions:(__kindof AXAlertViewAction *_Nonnull)actions,...; 149 | - (void)appendActions:(__kindof AXAlertViewAction *_Nonnull)actions,...; 150 | 151 | - (void)show:(BOOL)animated; 152 | - (void)show:(BOOL)animated completion:(AXAlertViewShowsBlock _Nullable)didShow; 153 | - (void)hide:(BOOL)animated; 154 | - (void)hide:(BOOL)animated completion:(AXAlertViewShowsBlock _Nullable)didHide; 155 | 156 | - (void)setActionConfiguration:(AXAlertViewActionConfiguration *_Nonnull)configuration 157 | forKey:(NSString *_Nonnull)key UI_APPEARANCE_SELECTOR; 158 | - (void)setActionConfiguration:(AXAlertViewActionConfiguration *_Nonnull)configuration 159 | forItemAtIndex:(NSUInteger)index; 160 | - (void)setActionConfiguration:(AXAlertViewActionConfiguration *_Nonnull)configuration 161 | forAction:(AXAlertViewAction *_Nonnull)action; 162 | 163 | - (void)viewWillShow:(AXAlertView *)alertView animated:(BOOL)animated NS_REQUIRES_SUPER; 164 | - (void)viewDidShow:(AXAlertView *)alertView animated:(BOOL)animated NS_REQUIRES_SUPER; 165 | 166 | - (void)viewWillHide:(AXAlertView *)alertView animated:(BOOL)animated NS_REQUIRES_SUPER; 167 | - (void)viewDidHide:(AXAlertView *)alertView animated:(BOOL)animated NS_REQUIRES_SUPER; 168 | 169 | @end 170 | 171 | @interface AXAlertView (Configurations) 172 | 173 | - (void)setNeedsReconfigureItems; 174 | - (void)reconfigureItemsIfNeeded; 175 | 176 | @end 177 | 178 | typedef void(^AXAlertViewActionHandler)(AXAlertViewAction *__weak _Nonnull action); 179 | 180 | @interface AXAlertViewAction : NSObject 181 | /// Key for the configuration. 182 | @property(copy, nonatomic, nullable) NSString *identifier; 183 | /// Title 184 | @property(readonly, nonatomic, nonnull) NSString *title; 185 | /// Image. 186 | @property(readonly, nonatomic, nullable) UIImage *image; 187 | /// Handler call back block. If handler is null, then the handler is dismiss by default. 188 | @property(copy, nonatomic, nullable) AXAlertViewActionHandler handler; 189 | 190 | + (instancetype _Nonnull)actionWithTitle:(NSString *_Nonnull)title 191 | handler:(AXAlertViewActionHandler _Nullable)handler; 192 | + (instancetype _Nonnull)actionWithTitle:(NSString *_Nonnull)title 193 | image:(UIImage *_Nullable)image 194 | handler:(AXAlertViewActionHandler _Nullable)handler; 195 | @end 196 | 197 | #pragma mark - AXAlertViewActionConfiguration. 198 | 199 | /// The configuration of the alert action. 200 | @interface AXAlertViewActionConfiguration : NSObject 201 | /// Font of title. 202 | @property(strong, nonatomic, nullable) UIFont *font; 203 | /// Text color of title. 204 | @property(strong, nonatomic, nullable) UIColor *tintColor; 205 | /// Background color. 206 | @property(strong, nonatomic, nonnull) UIColor *backgroundColor; 207 | /// preferred height. Only used for default configuration. 208 | @property(assign, nonatomic) CGFloat heightForLayout; 209 | /// Separator height. 210 | @property(assign, nonatomic) CGFloat heightForSeparator; 211 | /// Corner radius. 212 | @property(assign, nonatomic) CGFloat cornerRadius; 213 | /// Translucent of the action item. Defailts to YES. 214 | @property(assign, nonatomic, getter=isTranslucent) BOOL translucent; 215 | /// Translucent style. Defaults to Light. 216 | @property(assign, nonatomic) AXAlertViewTranslucentStyle translucentStyle; 217 | @end 218 | 219 | @interface AXAlertViewPlaceholderAction : AXAlertViewAction @end 220 | @interface AXAlertViewPlaceholderActionConfiguration : AXAlertViewActionConfiguration @end 221 | 222 | NS_ASSUME_NONNULL_END 223 | -------------------------------------------------------------------------------- /AXAlertController/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AXAlertView 4 | // 5 | // Created by ai on 16/4/5. 6 | // Copyright © 2016年 devedbox. 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 | -------------------------------------------------------------------------------- /AXAlertController/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AXAlertView 4 | // 5 | // Created by ai on 16/4/5. 6 | // Copyright © 2016年 devedbox. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "AXAlertView.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | // [[UIBarButtonItem appearance] setTitleTextAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:13]} forState:UIControlStateNormal]; 22 | return YES; 23 | } 24 | 25 | - (void)applicationWillResignActive:(UIApplication *)application { 26 | // 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. 27 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 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 | - (void)applicationWillEnterForeground:(UIApplication *)application { 36 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 37 | } 38 | 39 | - (void)applicationDidBecomeActive:(UIApplication *)application { 40 | // 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. 41 | } 42 | 43 | - (void)applicationWillTerminate:(UIApplication *)application { 44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /AXAlertController/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" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/Image.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/Image.imageset/image.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/button.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ax_button.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ax_button-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ax_button-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/button.imageset/ax_button-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/button.imageset/ax_button-1.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/button.imageset/ax_button-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/button.imageset/ax_button-2.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/button.imageset/ax_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/button.imageset/ax_button.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/cancel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "btn_dialog_cancel@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "btn_dialog_cancel@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/cancel.imageset/btn_dialog_cancel@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/cancel.imageset/btn_dialog_cancel@2x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/cancel.imageset/btn_dialog_cancel@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/cancel.imageset/btn_dialog_cancel@3x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/confirm.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "btn_dialog_confirm@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "btn_dialog_confirm@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/confirm.imageset/btn_dialog_confirm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/confirm.imageset/btn_dialog_confirm@2x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/confirm.imageset/btn_dialog_confirm@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/confirm.imageset/btn_dialog_confirm@3x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/content_image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/content_image.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/content_image.imageset/image.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/more.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "btn_more@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "btn_more@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "template" 24 | } 25 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/more.imageset/btn_more@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/more.imageset/btn_more@2x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/more.imageset/btn_more@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/more.imageset/btn_more@3x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/state.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "img.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "img-1.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/state.imageset/img-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/state.imageset/img-1.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/state.imageset/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/state.imageset/img.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/touch.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "touch@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "touch@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/touch.imageset/touch@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/touch.imageset/touch@2x.png -------------------------------------------------------------------------------- /AXAlertController/Assets.xcassets/touch.imageset/touch@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/Assets.xcassets/touch.imageset/touch@3x.png -------------------------------------------------------------------------------- /AXAlertController/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 | -------------------------------------------------------------------------------- /AXAlertController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarStyle 34 | UIStatusBarStyleLightContent 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /AXAlertController/SampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SampleViewController.h 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/6/20. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SampleViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AXAlertController/SampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SampleViewController.m 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/6/20. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | 9 | #import "SampleViewController.h" 10 | #import "SettingViewController.h" 11 | #import "AXAlertController.h" 12 | 13 | @interface SampleViewController () 14 | /// Setting model. 15 | @property(strong, nonatomic) SettingModel *settings; 16 | @end 17 | 18 | @interface SampleTableViewCell: UITableViewCell { 19 | UIView *_highlightedView; 20 | } 21 | @end 22 | @implementation SampleTableViewCell 23 | - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { 24 | [super setHighlighted:highlighted animated:animated]; 25 | 26 | if (!_highlightedView) { 27 | _highlightedView = [UIView new]; 28 | _highlightedView.backgroundColor = [UIColor colorWithWhite:0.98 alpha:0.77]; 29 | } 30 | [_highlightedView setFrame:self.bounds]; 31 | 32 | if (highlighted) { 33 | [self insertSubview:_highlightedView atIndex:0]; 34 | if (animated) { 35 | _highlightedView.alpha = 0.0; 36 | [UIView animateWithDuration:0.25 animations:^{ 37 | _highlightedView.alpha = 1.0; 38 | }]; 39 | } 40 | } else { 41 | if (animated) { 42 | [UIView animateWithDuration:0.25 animations:^{ 43 | _highlightedView.alpha = 0.0; 44 | } completion:^(BOOL finished) { 45 | if (finished) { 46 | [_highlightedView removeFromSuperview]; 47 | _highlightedView.alpha = 1.0; 48 | } 49 | }]; 50 | } else { 51 | [_highlightedView removeFromSuperview]; 52 | } 53 | } 54 | } 55 | @end 56 | 57 | @implementation SampleViewController 58 | 59 | - (void)viewDidLoad { 60 | [super viewDidLoad]; 61 | 62 | // Uncomment the following line to preserve selection between presentations. 63 | // self.clearsSelectionOnViewWillAppear = NO; 64 | 65 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 66 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 67 | UIImage *image = [UIImage imageNamed:@"Image"]; 68 | UIView *backgroundView = [[UIImageView alloc] initWithImage:image]; 69 | backgroundView.contentMode = UIViewContentModeScaleAspectFill; 70 | self.tableView.backgroundView = backgroundView; 71 | 72 | [self _resetSettings:nil]; 73 | } 74 | 75 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 76 | if ([segue.identifier isEqualToString:@"settings"]) { 77 | SettingViewController *settingViewController = (SettingViewController *)(((UINavigationController *)segue.destinationViewController).topViewController); 78 | settingViewController.delegate = self; 79 | } 80 | 81 | [super prepareForSegue:segue sender:sender]; 82 | } 83 | #pragma mark - UITableViewDelegate. 84 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 85 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 86 | UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 87 | switch (indexPath.row) { 88 | case 0: {// Show normal. 89 | [self showNormal:cell]; 90 | } break; 91 | case 1: {// With image. 92 | [self showWithImage:cell]; 93 | } break; 94 | case 2: {// With single textfield. 95 | [self showWithSingleTextfield:cell]; 96 | } break; 97 | case 3: {// With image and single textfield. 98 | [self showWithImageAndSingleTextfield:cell]; 99 | } break; 100 | case 4: {// With multiple text fields. 101 | [self showWithMultipleTextfields:cell]; 102 | } break; 103 | case 5: {// With multiple actions. 104 | [self showWithMultipleActions:cell]; 105 | } break; 106 | case 6: {// With multiple textfields and actions. 107 | [self showWithMultipleTextfieldsAndActions:cell]; 108 | } break; 109 | case 7: {// Scrollable image content. 110 | [self showScrollableImageContent:cell]; 111 | } break; 112 | case 8: {// Scrollable message content. 113 | [self showScrollableMessageContent:cell]; 114 | } break; 115 | default: 116 | break; 117 | } 118 | } 119 | 120 | #pragma mark - Actions. 121 | - (IBAction)showNormal:(id)sender { 122 | [self presentViewController:[self _normalAlertController] animated:YES completion:NULL]; 123 | } 124 | 125 | - (IBAction)showWithImage:(id)sender { 126 | AXAlertController *alert = [self _normalAlertController]; 127 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 128 | imageView.contentMode = UIViewContentModeCenter; 129 | imageView.image = [self _resizedTouchImage]; 130 | }]; 131 | 132 | [self presentViewController:alert animated:YES completion:NULL]; 133 | } 134 | 135 | - (IBAction)showWithSingleTextfield:(id)sender { 136 | AXAlertController *alert = [self _normalAlertController]; 137 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 138 | textField.placeholder = @"Type text..."; 139 | }]; 140 | 141 | [self presentViewController:alert animated:YES completion:NULL]; 142 | } 143 | 144 | - (IBAction)showWithImageAndSingleTextfield:(id)sender { 145 | AXAlertController *alert = [self _normalAlertController]; 146 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 147 | imageView.contentMode = UIViewContentModeCenter; 148 | imageView.image = [self _resizedTouchImage]; 149 | }]; 150 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 151 | textField.placeholder = @"Type text..."; 152 | }]; 153 | 154 | [self presentViewController:alert animated:YES completion:NULL]; 155 | } 156 | 157 | - (IBAction)showWithMultipleTextfields:(id)sender { 158 | AXAlertController *alert = [self _normalAlertController]; 159 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 160 | imageView.contentMode = UIViewContentModeCenter; 161 | imageView.image = [self _resizedTouchImage]; 162 | }]; 163 | for (int i = 0; i < 5; i++) { 164 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 165 | textField.placeholder = @"Type text..."; 166 | }]; 167 | } 168 | [self presentViewController:alert animated:YES completion:NULL]; 169 | } 170 | 171 | - (IBAction)showWithMultipleActions:(id)sender { 172 | AXAlertController *alert = [self _normalAlertController]; 173 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 174 | imageView.contentMode = UIViewContentModeCenter; 175 | imageView.image = [self _resizedTouchImage]; 176 | }]; 177 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 178 | textField.placeholder = @"Type text..."; 179 | }]; 180 | for (int i = 0; i<4; i++) { 181 | [alert addAction:[AXAlertAction actionWithTitle:@"OK" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 182 | config.translucent = _settings.actionTranslucent; 183 | config.translucentStyle = _settings.actionTranslucentStyle; 184 | 185 | config.font = [UIFont systemFontOfSize:17]; 186 | if (_settings.actionTranslucentStyle == AXAlertViewTranslucentDark) { 187 | config.backgroundColor = [UIColor grayColor]; 188 | config.tintColor = [UIColor whiteColor]; 189 | } else { 190 | config.backgroundColor = [UIColor whiteColor]; 191 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 192 | } 193 | 194 | config.cornerRadius = _settings.actionCornerRadius; 195 | config.heightForLayout = _settings.actionHeight; 196 | }]; 197 | } 198 | [self presentViewController:alert animated:YES completion:NULL]; 199 | } 200 | 201 | - (IBAction)showWithMultipleTextfieldsAndActions:(id)sender { 202 | AXAlertController *alert = [self _normalAlertController]; 203 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 204 | imageView.contentMode = UIViewContentModeCenter; 205 | imageView.image = [self _resizedTouchImage]; 206 | }]; 207 | for (int i = 0; i < 3; i++) { 208 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 209 | textField.placeholder = @"Type text..."; 210 | }]; 211 | } 212 | for (int i = 0; i < 3; i++) { 213 | [alert addAction:[AXAlertAction actionWithTitle:@"OK" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 214 | config.translucent = _settings.actionTranslucent; 215 | config.translucentStyle = _settings.actionTranslucentStyle; 216 | 217 | config.font = [UIFont systemFontOfSize:17]; 218 | if (_settings.actionTranslucentStyle == AXAlertViewTranslucentDark) { 219 | config.backgroundColor = [UIColor grayColor]; 220 | config.tintColor = [UIColor whiteColor]; 221 | } else { 222 | config.backgroundColor = [UIColor whiteColor]; 223 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 224 | } 225 | 226 | config.cornerRadius = _settings.actionCornerRadius; 227 | config.heightForLayout = _settings.actionHeight; 228 | }]; 229 | } 230 | [self presentViewController:alert animated:YES completion:NULL]; 231 | } 232 | 233 | - (IBAction)showScrollableImageContent:(id)sender { 234 | AXAlertController *alert = [self _normalAlertController]; 235 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 236 | imageView.contentMode = UIViewContentModeScaleAspectFill; 237 | imageView.image = [UIImage imageNamed:@"content_image"]; 238 | }]; 239 | 240 | [self presentViewController:alert animated:YES completion:NULL]; 241 | } 242 | 243 | - (IBAction)showScrollableMessageContent:(id)sender { 244 | AXAlertController *alert = [self _normalAlertController]; 245 | alert.message = @"The iPhone has shipped with a camera since its first model. In the first SDKs, the only way to integrate the camera within an app was by using UIImagePickerController, but iOS 4 introduced the AVFoundation framework, which allowed more flexibility.\n\nIn this article, we’ll see how image capture with AVFoundation works, how to control the camera, and the new features recently introduced in iOS 8.\n\nUIImagePickerController provides a very simple way to take a picture. It supports all the basic features, such as switching to the front-facing camera, toggling the flash, tapping on an area to lock focus and exposure, and, on iOS 8, adjusting the exposure just as in the system camera app.\n\nHowever, when direct access to the camera is necessary, the AVFoundation framework allows full control, for example, for changing the hardware parameters programmatically, or manipulating the live preview.\n\nAn image capture implemented with the AVFoundation framework is based on a few classes. These classes give access to the raw data coming from the camera device and can control its components.\n\nNow we need a camera device input. On most iPhones and iPads, we can choose between the back camera and the front camera — aka the selfie camera. So first we have to iterate over all the devices that can provide video data (the microphone is also an AVCaptureDevice, but we’ll skip it) and check for the position property\n\nNote that the first time the app is executed, the first call to AVCaptureDeviceInput.deviceInputWithDevice() triggers a system dialog, asking the user to allow usage of the camera. This was introduced in some countries with iOS 7, and was extended to all regions with iOS 8. Until the user accepts the dialog, the camera input will send a stream of black frames."; 246 | 247 | [self presentViewController:alert animated:YES completion:NULL]; 248 | } 249 | 250 | #pragma mark - SettingViewControllerDelegate. 251 | - (SettingModel *)originalSettingModel { return _settings; } 252 | - (void)settingViewControllerDidFinishConfiguring:(SettingModel *)settingModel { 253 | _settings = settingModel; 254 | } 255 | 256 | #pragma mark - Private. 257 | - (IBAction)_resetSettings:(id)sender { 258 | _settings = [SettingModel new]; 259 | _settings.translucent = YES; 260 | _settings.translucentStyle = AXAlertViewTranslucentLight; 261 | _settings.hidesOnTouch = NO; 262 | _settings.showsSeparators = YES; 263 | _settings.padding = 0.0; 264 | _settings.verticalOffset = 0.0; 265 | _settings.opacity = 0.0; 266 | _settings.maxAllowedWidth = 270; 267 | _settings.cornerRadius = 12.0; 268 | _settings.actionTranslucent = YES; 269 | _settings.actionTranslucentStyle = AXAlertViewTranslucentLight; 270 | _settings.actionPadding = 0.0; 271 | _settings.actionMargin = 0.0; 272 | _settings.actionCornerRadius = 0.0; 273 | _settings.actionHeight = 44.0; 274 | _settings.preferedMargin = UIEdgeInsetsMake(0, 25, 0, 25); 275 | _settings.contentInset = UIEdgeInsetsZero; 276 | _settings.customViewInset = UIEdgeInsetsMake(5, 15, 20, 15); 277 | _settings.titleInset = UIEdgeInsetsMake(20, 16, 0, 16); 278 | 279 | if (sender != nil) { 280 | AXAlertController *alert = [self _alertController]; 281 | alert.title = @"Notice"; 282 | alert.message = @"Settings has been reset."; 283 | [alert addAction:[AXAlertAction actionWithTitle:@"OK" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 284 | config.translucent = _settings.actionTranslucent; 285 | config.translucentStyle = _settings.actionTranslucentStyle; 286 | 287 | config.font = [UIFont systemFontOfSize:17]; 288 | if (_settings.actionTranslucentStyle == AXAlertViewTranslucentDark) { 289 | config.backgroundColor = [UIColor grayColor]; 290 | config.tintColor = [UIColor whiteColor]; 291 | } else { 292 | config.backgroundColor = [UIColor whiteColor]; 293 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 294 | } 295 | 296 | config.cornerRadius = _settings.actionCornerRadius; 297 | config.heightForLayout = _settings.actionHeight; 298 | }]; 299 | [self presentViewController:alert animated:YES completion:NULL]; 300 | } 301 | } 302 | 303 | - (AXAlertController *)_normalAlertController { 304 | AXAlertController *alert = [self _alertController]; 305 | 306 | [alert addAction:[AXAlertAction actionWithTitle:@"Cancel" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 307 | config.translucent = _settings.actionTranslucent; 308 | config.translucentStyle = _settings.actionTranslucentStyle; 309 | 310 | if (_settings.actionTranslucentStyle == AXAlertViewTranslucentDark) { 311 | config.backgroundColor = [UIColor grayColor]; 312 | config.tintColor = [UIColor whiteColor]; 313 | } else { 314 | config.backgroundColor = [UIColor whiteColor]; 315 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 316 | } 317 | config.font = [UIFont boldSystemFontOfSize:17]; 318 | 319 | config.cornerRadius = _settings.actionCornerRadius; 320 | config.heightForLayout = _settings.actionHeight; 321 | }]; 322 | [alert addAction:[AXAlertAction actionWithTitle:@"OK" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 323 | config.translucent = _settings.actionTranslucent; 324 | config.translucentStyle = _settings.actionTranslucentStyle; 325 | 326 | config.font = [UIFont systemFontOfSize:17]; 327 | if (_settings.actionTranslucentStyle == AXAlertViewTranslucentDark) { 328 | config.backgroundColor = [UIColor grayColor]; 329 | config.tintColor = [UIColor whiteColor]; 330 | } else { 331 | config.backgroundColor = [UIColor whiteColor]; 332 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 333 | } 334 | 335 | config.cornerRadius = _settings.actionCornerRadius; 336 | config.heightForLayout = _settings.actionHeight; 337 | }]; 338 | return alert; 339 | } 340 | 341 | - (AXAlertController *)_alertController { 342 | AXAlertController *alert = [AXAlertController alertControllerWithTitle:@"Some title..." message:@"Some message..." preferredStyle:AXAlertControllerStyleAlert]; 343 | // Set up alert. 344 | alert.alertView.translucent = _settings.translucent; 345 | alert.alertView.translucentStyle = _settings.translucentStyle; 346 | if (_settings.translucentStyle == AXAlertViewTranslucentDark) { 347 | alert.alertView.backgroundColor = [UIColor grayColor]; 348 | alert.alertView.titleColor = [UIColor whiteColor]; 349 | [alert setValue:[UIColor whiteColor] forKeyPath:@"contentView.contentLabel.textColor"]; 350 | } else { 351 | alert.alertView.backgroundColor = [UIColor whiteColor]; 352 | alert.alertView.titleColor = [UIColor blackColor]; 353 | [alert setValue:[UIColor darkTextColor] forKeyPath:@"contentView.contentLabel.textColor"]; 354 | } 355 | alert.alertView.hidesOnTouch = _settings.hidesOnTouch; 356 | alert.alertView.showsSeparators = _settings.showsSeparators; 357 | alert.alertView.padding = _settings.padding; 358 | alert.alertView.verticalOffset = _settings.verticalOffset; 359 | alert.alertView.opacity = _settings.opacity; 360 | alert.alertView.maxAllowedWidth = _settings.maxAllowedWidth; 361 | alert.alertView.cornerRadius = _settings.cornerRadius; 362 | alert.alertView.actionItemPadding = _settings.actionPadding; 363 | alert.alertView.actionItemMargin = _settings.actionMargin; 364 | alert.alertView.preferredMargin = _settings.preferedMargin; 365 | alert.alertView.contentInset = _settings.contentInset; 366 | alert.alertView.customViewInset = _settings.customViewInset; 367 | alert.alertView.titleInset = _settings.titleInset; 368 | return alert; 369 | } 370 | 371 | - (UIImage *)_resizedTouchImage { 372 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(44.0, 44.0), NO, [UIScreen mainScreen].scale); 373 | CGContextRef context = UIGraphicsGetCurrentContext(); 374 | CGContextSaveGState(context); 375 | CGContextTranslateCTM(context, 0, 44.0); 376 | CGContextScaleCTM(context, 1.0, -1); 377 | CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor); 378 | CGContextDrawImage(context, CGRectMake(0, 0, 44.0, 44.0), [UIImage imageNamed:@"touch"].CGImage); 379 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 380 | CGContextRestoreGState(context); 381 | UIGraphicsEndImageContext(); 382 | return image; 383 | } 384 | @end 385 | -------------------------------------------------------------------------------- /AXAlertController/SettingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SettingViewController.h 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/6/21. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AXAlertController.h" 11 | 12 | @class SettingViewController; 13 | @class SettingModel; 14 | @protocol SettingViewControllerDelegate 15 | - (SettingModel *)originalSettingModel; 16 | - (void)settingViewControllerDidFinishConfiguring:(SettingModel *)settingModel; 17 | @end 18 | 19 | @interface SettingViewController : UITableViewController 20 | @property(assign, nonatomic) id delegate; 21 | @end 22 | 23 | @interface SettingModel: NSObject 24 | #pragma mark - Normal. 25 | @property(assign, nonatomic) BOOL translucent; 26 | @property(assign, nonatomic) AXAlertViewTranslucentStyle translucentStyle; 27 | @property(assign, nonatomic) BOOL hidesOnTouch; 28 | @property(assign, nonatomic) BOOL showsSeparators; 29 | @property(assign, nonatomic) CGFloat padding; 30 | @property(assign, nonatomic) CGFloat verticalOffset; 31 | @property(assign, nonatomic) CGFloat opacity; 32 | @property(assign, nonatomic) CGFloat maxAllowedWidth; 33 | @property(assign, nonatomic) CGFloat cornerRadius; 34 | #pragma mark - Actions. 35 | @property(assign, nonatomic) BOOL actionTranslucent; 36 | @property(assign, nonatomic) AXAlertViewTranslucentStyle actionTranslucentStyle; 37 | @property(assign, nonatomic) CGFloat actionPadding; 38 | @property(assign, nonatomic) CGFloat actionMargin; 39 | @property(assign, nonatomic) CGFloat actionCornerRadius; 40 | @property(assign, nonatomic) CGFloat actionHeight; 41 | #pragma mark - Insets. 42 | @property(assign, nonatomic) UIEdgeInsets preferedMargin; 43 | @property(assign, nonatomic) UIEdgeInsets contentInset; 44 | @property(assign, nonatomic) UIEdgeInsets customViewInset; 45 | @property(assign, nonatomic) UIEdgeInsets titleInset; 46 | @end 47 | -------------------------------------------------------------------------------- /AXAlertController/SettingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SettingViewController.m 3 | // AXAlertController 4 | // 5 | // Created by devedbox on 2017/6/21. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | 9 | #import "SettingViewController.h" 10 | 11 | @implementation SettingModel 12 | @end 13 | 14 | @interface SettingViewController () 15 | /// Setting model. 16 | @property(strong, nonatomic) SettingModel *settings; 17 | /// Translucent of alert. 18 | @property(weak, nonatomic) IBOutlet UISwitch *alertTranslucentSwitch; 19 | /// Hides on touch. 20 | @property(weak, nonatomic) IBOutlet UISwitch *hidesOnTouchSwitch; 21 | /// Show separators. 22 | @property(weak, nonatomic) IBOutlet UISwitch *showsSeparatorsSwitch; 23 | /// Translucent style segmented control. 24 | @property(weak, nonatomic) IBOutlet UISegmentedControl *alertTranslucentStyleControl; 25 | /// Padding slider. 26 | @property(weak, nonatomic) IBOutlet UISlider *paddingSlider; 27 | @property(weak, nonatomic) IBOutlet UILabel *paddingValueLabel; 28 | /// Vertical offset slider. 29 | @property(weak, nonatomic) IBOutlet UISlider *verticalOffsetSlider; 30 | @property(weak, nonatomic) IBOutlet UILabel *verticalOffsetValueLabel; 31 | /// Opacity slider. 32 | @property(weak, nonatomic) IBOutlet UISlider *opacitySlider; 33 | @property(weak, nonatomic) IBOutlet UILabel *opacityValueLabel; 34 | /// Max allowed width slider. 35 | @property(weak, nonatomic) IBOutlet UISlider *maxAllowedWidthSlider; 36 | @property(weak, nonatomic) IBOutlet UILabel *maxAllowedWidthValueLabel; 37 | /// Corner radius slider. 38 | @property(weak, nonatomic) IBOutlet UISlider *cornerRadiusSlider; 39 | @property(weak, nonatomic) IBOutlet UILabel *cornerRadiusValueLabel; 40 | /// Translucent of action. 41 | @property(weak, nonatomic) IBOutlet UISwitch *actionTranslucentSwitch; 42 | /// Translucent style segmented control. 43 | @property(weak, nonatomic) IBOutlet UISegmentedControl *actionTranslucentStyleControl; 44 | /// Padding slider. 45 | @property(weak, nonatomic) IBOutlet UISlider *actionPaddingSlider; 46 | @property(weak, nonatomic) IBOutlet UILabel *actionPaddingValueLabel; 47 | /// Padding slider. 48 | @property(weak, nonatomic) IBOutlet UISlider *actionMarginSlider; 49 | @property(weak, nonatomic) IBOutlet UILabel *actionMarginValueLabel; 50 | /// Corner radius slider. 51 | @property(weak, nonatomic) IBOutlet UISlider *actionCornerRadiusSlider; 52 | @property(weak, nonatomic) IBOutlet UILabel *actionCornerRadiusValueLabel; 53 | /// Height slider. 54 | @property(weak, nonatomic) IBOutlet UISlider *actionHeightSlider; 55 | @property(weak, nonatomic) IBOutlet UILabel *actionHeightValueLabel; 56 | #pragma mark - Prefered margin. 57 | /// Content top slider. 58 | @property(weak, nonatomic) IBOutlet UISlider *preferedMarginTopSlider; 59 | @property(weak, nonatomic) IBOutlet UILabel *preferedMarginTopValueLabel; 60 | /// Content top slider. 61 | @property(weak, nonatomic) IBOutlet UISlider *preferedMarginLeftSlider; 62 | @property(weak, nonatomic) IBOutlet UILabel *preferedMarginLeftValueLabel; 63 | /// Content top slider. 64 | @property(weak, nonatomic) IBOutlet UISlider *preferedMarginBottomSlider; 65 | @property(weak, nonatomic) IBOutlet UILabel *preferedMarginBottomValueLabel; 66 | /// Content top slider. 67 | @property(weak, nonatomic) IBOutlet UISlider *preferedMarginRightSlider; 68 | @property(weak, nonatomic) IBOutlet UILabel *preferedMarginRightValueLabel; 69 | #pragma mark - Conent inset. 70 | /// Content top slider. 71 | @property(weak, nonatomic) IBOutlet UISlider *contentInsetTopSlider; 72 | @property(weak, nonatomic) IBOutlet UILabel *contentInsetTopValueLabel; 73 | /// Content top slider. 74 | @property(weak, nonatomic) IBOutlet UISlider *contentInsetLeftSlider; 75 | @property(weak, nonatomic) IBOutlet UILabel *contentInsetLeftValueLabel; 76 | /// Content top slider. 77 | @property(weak, nonatomic) IBOutlet UISlider *contentInsetBottomSlider; 78 | @property(weak, nonatomic) IBOutlet UILabel *contentInsetBottomValueLabel; 79 | /// Content top slider. 80 | @property(weak, nonatomic) IBOutlet UISlider *contentInsetRightSlider; 81 | @property(weak, nonatomic) IBOutlet UILabel *contentInsetRightValueLabel; 82 | #pragma mark - Custom inset. 83 | /// Content top slider. 84 | @property(weak, nonatomic) IBOutlet UISlider *customInsetTopSlider; 85 | @property(weak, nonatomic) IBOutlet UILabel *customInsetTopValueLabel; 86 | /// Content top slider. 87 | @property(weak, nonatomic) IBOutlet UISlider *customInsetLeftSlider; 88 | @property(weak, nonatomic) IBOutlet UILabel *customInsetLeftValueLabel; 89 | /// Content top slider. 90 | @property(weak, nonatomic) IBOutlet UISlider *customInsetBottomSlider; 91 | @property(weak, nonatomic) IBOutlet UILabel *customInsetBottomValueLabel; 92 | /// Content top slider. 93 | @property(weak, nonatomic) IBOutlet UISlider *customInsetRightSlider; 94 | @property(weak, nonatomic) IBOutlet UILabel *customInsetRightValueLabel; 95 | #pragma mark - Title inset. 96 | /// Content top slider. 97 | @property(weak, nonatomic) IBOutlet UISlider *titleInsetTopSlider; 98 | @property(weak, nonatomic) IBOutlet UILabel *titleInsetTopValueLabel; 99 | /// Content top slider. 100 | @property(weak, nonatomic) IBOutlet UISlider *titleInsetLeftSlider; 101 | @property(weak, nonatomic) IBOutlet UILabel *titleInsetLeftValueLabel; 102 | /// Content top slider. 103 | @property(weak, nonatomic) IBOutlet UISlider *titleInsetBottomSlider; 104 | @property(weak, nonatomic) IBOutlet UILabel *titleInsetBottomValueLabel; 105 | /// Content top slider. 106 | @property(weak, nonatomic) IBOutlet UISlider *titleInsetRightSlider; 107 | @property(weak, nonatomic) IBOutlet UILabel *titleInsetRightValueLabel; 108 | @end 109 | 110 | @implementation SettingViewController 111 | 112 | - (void)viewDidLoad { 113 | [super viewDidLoad]; 114 | 115 | // Uncomment the following line to preserve selection between presentations. 116 | // self.clearsSelectionOnViewWillAppear = NO; 117 | 118 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 119 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 120 | 121 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)]; 122 | 123 | if (_delegate) { 124 | _settings = [_delegate originalSettingModel]; 125 | } else { 126 | _settings = [SettingModel new]; 127 | } 128 | 129 | [_alertTranslucentSwitch setOn:_settings.translucent]; 130 | [_alertTranslucentStyleControl setSelectedSegmentIndex:_settings.translucentStyle]; 131 | [_hidesOnTouchSwitch setOn:_settings.hidesOnTouch]; 132 | [_showsSeparatorsSwitch setOn:_settings.showsSeparators]; 133 | [_paddingSlider setValue:_settings.padding]; 134 | [_paddingSlider sendActionsForControlEvents:UIControlEventValueChanged]; 135 | [_verticalOffsetSlider setValue:_settings.verticalOffset]; 136 | [_verticalOffsetSlider sendActionsForControlEvents:UIControlEventValueChanged]; 137 | [_opacitySlider setValue:_settings.opacity]; 138 | [_opacitySlider sendActionsForControlEvents:UIControlEventValueChanged]; 139 | [_maxAllowedWidthSlider setValue:_settings.maxAllowedWidth]; 140 | [_maxAllowedWidthSlider sendActionsForControlEvents:UIControlEventValueChanged]; 141 | [_cornerRadiusSlider setValue:_settings.cornerRadius]; 142 | [_cornerRadiusSlider sendActionsForControlEvents:UIControlEventValueChanged]; 143 | 144 | [_actionTranslucentSwitch setOn:_settings.actionTranslucent]; 145 | [_actionTranslucentStyleControl setSelectedSegmentIndex:_settings.actionTranslucentStyle]; 146 | [_actionPaddingSlider setValue:_settings.actionPadding]; 147 | [_actionPaddingSlider sendActionsForControlEvents:UIControlEventValueChanged]; 148 | [_actionMarginSlider setValue:_settings.actionMargin]; 149 | [_actionMarginSlider sendActionsForControlEvents:UIControlEventValueChanged]; 150 | [_actionCornerRadiusSlider setValue:_settings.actionCornerRadius]; 151 | [_actionCornerRadiusSlider sendActionsForControlEvents:UIControlEventValueChanged]; 152 | [_actionHeightSlider setValue:_settings.actionHeight]; 153 | [_actionHeightSlider sendActionsForControlEvents:UIControlEventValueChanged]; 154 | 155 | [_preferedMarginTopSlider setValue:_settings.preferedMargin.top]; 156 | [_preferedMarginTopSlider sendActionsForControlEvents:UIControlEventValueChanged]; 157 | [_preferedMarginLeftSlider setValue:_settings.preferedMargin.left]; 158 | [_preferedMarginLeftSlider sendActionsForControlEvents:UIControlEventValueChanged]; 159 | [_preferedMarginBottomSlider setValue:_settings.preferedMargin.bottom]; 160 | [_preferedMarginBottomSlider sendActionsForControlEvents:UIControlEventValueChanged]; 161 | [_preferedMarginRightSlider setValue:_settings.preferedMargin.right]; 162 | [_preferedMarginRightSlider sendActionsForControlEvents:UIControlEventValueChanged]; 163 | 164 | [_contentInsetTopSlider setValue:_settings.contentInset.top]; 165 | [_contentInsetTopSlider sendActionsForControlEvents:UIControlEventValueChanged]; 166 | [_contentInsetLeftSlider setValue:_settings.contentInset.left]; 167 | [_contentInsetLeftSlider sendActionsForControlEvents:UIControlEventValueChanged]; 168 | [_contentInsetBottomSlider setValue:_settings.contentInset.bottom]; 169 | [_contentInsetBottomSlider sendActionsForControlEvents:UIControlEventValueChanged]; 170 | [_contentInsetRightSlider setValue:_settings.contentInset.right]; 171 | [_contentInsetRightSlider sendActionsForControlEvents:UIControlEventValueChanged]; 172 | 173 | [_customInsetTopSlider setValue:_settings.customViewInset.top]; 174 | [_customInsetTopSlider sendActionsForControlEvents:UIControlEventValueChanged]; 175 | [_customInsetLeftSlider setValue:_settings.customViewInset.left]; 176 | [_customInsetLeftSlider sendActionsForControlEvents:UIControlEventValueChanged]; 177 | [_customInsetBottomSlider setValue:_settings.customViewInset.bottom]; 178 | [_customInsetBottomSlider sendActionsForControlEvents:UIControlEventValueChanged]; 179 | [_customInsetRightSlider setValue:_settings.customViewInset.right]; 180 | [_customInsetRightSlider sendActionsForControlEvents:UIControlEventValueChanged]; 181 | 182 | [_titleInsetTopSlider setValue:_settings.titleInset.top]; 183 | [_titleInsetTopSlider sendActionsForControlEvents:UIControlEventValueChanged]; 184 | [_titleInsetLeftSlider setValue:_settings.titleInset.left]; 185 | [_titleInsetLeftSlider sendActionsForControlEvents:UIControlEventValueChanged]; 186 | [_titleInsetBottomSlider setValue:_settings.titleInset.bottom]; 187 | [_titleInsetBottomSlider sendActionsForControlEvents:UIControlEventValueChanged]; 188 | [_titleInsetRightSlider setValue:_settings.titleInset.right]; 189 | [_titleInsetRightSlider sendActionsForControlEvents:UIControlEventValueChanged]; 190 | } 191 | 192 | - (void)didReceiveMemoryWarning { 193 | [super didReceiveMemoryWarning]; 194 | // Dispose of any resources that can be recreated. 195 | } 196 | 197 | #pragma mark - Actions. 198 | - (IBAction)done:(id)sender { 199 | if (_delegate) { 200 | _settings.translucent = _alertTranslucentSwitch.isOn; 201 | _settings.translucentStyle = _alertTranslucentStyleControl.selectedSegmentIndex; 202 | _settings.hidesOnTouch = _hidesOnTouchSwitch.isOn; 203 | _settings.showsSeparators = _showsSeparatorsSwitch.isOn; 204 | _settings.padding = _paddingSlider.value; 205 | _settings.verticalOffset = _verticalOffsetSlider.value; 206 | _settings.opacity = _opacitySlider.value; 207 | _settings.maxAllowedWidth = _maxAllowedWidthSlider.value; 208 | _settings.cornerRadius = _cornerRadiusSlider.value; 209 | 210 | _settings.actionTranslucent = _actionTranslucentSwitch.isOn; 211 | _settings.actionTranslucentStyle = _actionTranslucentStyleControl.selectedSegmentIndex; 212 | _settings.actionPadding = _actionPaddingSlider.value; 213 | _settings.actionMargin = _actionMarginSlider.value; 214 | _settings.actionCornerRadius = _actionCornerRadiusSlider.value; 215 | _settings.actionHeight = _actionHeightSlider.value; 216 | 217 | _settings.preferedMargin = UIEdgeInsetsMake(_preferedMarginTopSlider.value, _preferedMarginLeftSlider.value, _preferedMarginBottomSlider.value, _preferedMarginRightSlider.value); 218 | _settings.contentInset = UIEdgeInsetsMake(_contentInsetTopSlider.value, _contentInsetLeftSlider.value, _contentInsetBottomSlider.value, _contentInsetRightSlider.value); 219 | _settings.customViewInset = UIEdgeInsetsMake(_customInsetTopSlider.value, _customInsetLeftSlider.value, _customInsetBottomSlider.value, _customInsetRightSlider.value); 220 | _settings.titleInset = UIEdgeInsetsMake(_titleInsetTopSlider.value, _titleInsetLeftSlider.value, _titleInsetBottomSlider.value, _titleInsetRightSlider.value); 221 | 222 | [_delegate settingViewControllerDidFinishConfiguring:_settings]; 223 | } 224 | [self dismissViewControllerAnimated:YES completion:NULL]; 225 | } 226 | 227 | - (IBAction)handlePaddingSlider:(UISlider *)sender { 228 | [_paddingValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 229 | } 230 | 231 | - (IBAction)handleVerticalOffsetSlider:(UISlider *)sender { 232 | [_verticalOffsetValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 233 | } 234 | 235 | - (IBAction)handleOpacitySlider:(UISlider *)sender { 236 | [_opacityValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 237 | } 238 | 239 | - (IBAction)handleMaxAllowedWidthSlider:(UISlider *)sender { 240 | [_maxAllowedWidthValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 241 | } 242 | 243 | - (IBAction)handleCornerRadiusSlider:(UISlider *)sender { 244 | [_cornerRadiusValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 245 | } 246 | 247 | - (IBAction)handleActionPaddingSlider:(UISlider *)sender { 248 | [_actionPaddingValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 249 | } 250 | 251 | - (IBAction)handleActionMarginSlider:(UISlider *)sender { 252 | [_actionMarginValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 253 | } 254 | 255 | - (IBAction)handleActionCornerRadiusSlider:(UISlider *)sender { 256 | [_actionCornerRadiusValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 257 | } 258 | 259 | - (IBAction)handleActionHeightSlider:(UISlider *)sender { 260 | [_actionCornerRadiusSlider setMaximumValue:sender.value]; 261 | [_actionCornerRadiusSlider sendActionsForControlEvents:UIControlEventValueChanged]; 262 | [_actionHeightValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 263 | } 264 | 265 | #pragma mark - Prefered Margin. 266 | - (IBAction)handePreferedMarginTopSlider:(UISlider *)sender { 267 | [_preferedMarginTopValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 268 | } 269 | - (IBAction)handePreferedMarginLeftSlider:(UISlider *)sender { 270 | [_preferedMarginLeftValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 271 | } 272 | - (IBAction)handePreferedMarginBottomSlider:(UISlider *)sender { 273 | [_preferedMarginBottomValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 274 | } 275 | - (IBAction)handePreferedMarginRightSlider:(UISlider *)sender { 276 | [_preferedMarginRightValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 277 | } 278 | 279 | #pragma mark - Content Inset. 280 | - (IBAction)handeContentInsetTopSlider:(UISlider *)sender { 281 | [_contentInsetTopValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 282 | } 283 | - (IBAction)handeContentInsetLeftSlider:(UISlider *)sender { 284 | [_contentInsetLeftValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 285 | } 286 | - (IBAction)handeContentInsetBottomSlider:(UISlider *)sender { 287 | [_contentInsetBottomValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 288 | } 289 | - (IBAction)handeContentInsetRightSlider:(UISlider *)sender { 290 | [_contentInsetRightValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 291 | } 292 | 293 | #pragma mark - Custom Inset. 294 | - (IBAction)handeCustomInsetTopSlider:(UISlider *)sender { 295 | [_customInsetTopValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 296 | } 297 | - (IBAction)handeCustomInsetLeftSlider:(UISlider *)sender { 298 | [_customInsetLeftValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 299 | } 300 | - (IBAction)handeCustomInsetBottomSlider:(UISlider *)sender { 301 | [_customInsetBottomValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 302 | } 303 | - (IBAction)handeCustomInsetRightSlider:(UISlider *)sender { 304 | [_customInsetRightValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 305 | } 306 | 307 | #pragma mark - Title Inset. 308 | - (IBAction)handeTitleInsetTopSlider:(UISlider *)sender { 309 | [_titleInsetTopValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 310 | } 311 | - (IBAction)handeTitleInsetLeftSlider:(UISlider *)sender { 312 | [_titleInsetLeftValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 313 | } 314 | - (IBAction)handeTitleInsetBottomSlider:(UISlider *)sender { 315 | [_titleInsetBottomValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 316 | } 317 | - (IBAction)handeTitleInsetRightSlider:(UISlider *)sender { 318 | [_titleInsetRightValueLabel setText:[NSString stringWithFormat:@"%.2f", sender.value]]; 319 | } 320 | @end 321 | -------------------------------------------------------------------------------- /AXAlertController/TableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.h 3 | // AXAlertView 4 | // 5 | // Created by devedbox on 2017/5/24. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AXAlertController/TableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.m 3 | // AXAlertView 4 | // 5 | // Created by devedbox on 2017/5/24. 6 | // Copyright © 2017年 devedbox. All rights reserved. 7 | // 8 | 9 | #import "TableViewController.h" 10 | #import "AXAlertView.h" 11 | #import "AXActionSheet.h" 12 | #import "AXAlertController.h" 13 | 14 | @interface TableViewController () 15 | 16 | @end 17 | 18 | @implementation TableViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | // Uncomment the following line to preserve selection between presentations. 24 | // self.clearsSelectionOnViewWillAppear = NO; 25 | 26 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 27 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 28 | UIImage *image = [UIImage imageNamed:@"Image"]; 29 | UIView *backgroundView = [[UIImageView alloc] initWithImage:image]; 30 | backgroundView.contentMode = UIViewContentModeScaleAspectFill; 31 | self.tableView.backgroundView = backgroundView; 32 | } 33 | 34 | - (void)didReceiveMemoryWarning { 35 | [super didReceiveMemoryWarning]; 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | - (IBAction)showNormal:(id)sender { 40 | 41 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Some Title..." message:@"Some message..." preferredStyle:UIAlertControllerStyleAlert]; 42 | [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:NULL]]; 43 | [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:NULL]]; 44 | for (int i = 0; i < 15; i++) { 45 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 46 | // textField.borderStyle = UITextBorderStyleRoundedRect; 47 | // textField.font = [UIFont boldSystemFontOfSize:21]; 48 | textField.placeholder = @"Type text..."; 49 | }]; 50 | } 51 | [self presentViewController:alert animated:YES completion:^{ 52 | 53 | // for (UIView *view in alert.view.subviews) { 54 | // for (UIView *_view in view.subviews) { 55 | // for (UIView *__view in _view.subviews) { 56 | // for (UIView *___view in __view.subviews) { 57 | // if ([___view isKindOfClass:UIVisualEffectView.class]) { 58 | // ___view.hidden = YES; 59 | // } 60 | // } 61 | // } 62 | // } 63 | // } 64 | }]; 65 | alert.modalPresentationStyle = UIModalPresentationPageSheet; 66 | return; 67 | AXAlertView *alertView = [[AXAlertView alloc] initWithFrame:self.navigationController.view.bounds]; 68 | alertView.customViewInset = UIEdgeInsetsMake(5, 20, 10, 20); 69 | alertView.padding = 0; 70 | alertView.cornerRadius = 10.0; 71 | alertView.actionItemMargin = 0; 72 | alertView.actionItemPadding = 0; 73 | alertView.titleLabel.numberOfLines = 0; 74 | alertView.hidesOnTouch = YES; 75 | alertView.preferredMargin = UIEdgeInsetsMake(52, 52, 52, 52); 76 | alertView.title = @"兑换申请已受理"; 77 | UILabel *label = [UILabel new]; 78 | label.font = [UIFont systemFontOfSize:14]; 79 | label.numberOfLines = 0; 80 | label.text = @"您还有497个流量币可以兑换,继续兑换?"; 81 | 82 | alertView.customView = label; 83 | 84 | alertView.titleLabel.font = [UIFont systemFontOfSize:14]; 85 | 86 | alertView.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18]; 87 | alertView.titleLabel.textColor = [UIColor blackColor]; 88 | 89 | [alertView setActions:[AXAlertViewAction actionWithTitle:@"取消" image:nil handler:NULL],[AXAlertViewAction actionWithTitle:@"确认" image:nil handler:^(AXAlertViewAction * _Nonnull __weak action) { 90 | /* 91 | if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"https://www.baidu.com"]]) { 92 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://www.baidu.com"]]; 93 | } 94 | */ 95 | }],nil]; 96 | // alertView.showsSeparators = NO; 97 | // alertView.translucent = NO; 98 | 99 | AXAlertViewActionConfiguration *cancelConfig = [AXAlertViewActionConfiguration new]; 100 | cancelConfig.backgroundColor = [UIColor whiteColor]; 101 | cancelConfig.heightForLayout = 44; 102 | cancelConfig.cornerRadius = .0; 103 | cancelConfig.tintColor = [UIColor blackColor]; 104 | [alertView setActionConfiguration:cancelConfig forItemAtIndex:0]; 105 | AXAlertViewActionConfiguration *confirmConfig = [AXAlertViewActionConfiguration new]; 106 | // confirmConfig.backgroundColor = [UIColor blackColor]; 107 | confirmConfig.backgroundColor = [UIColor whiteColor]; 108 | confirmConfig.heightForLayout = 44; 109 | confirmConfig.cornerRadius = .0; 110 | // confirmConfig.tintColor = [UIColor blackColor]; 111 | confirmConfig.tintColor = [UIColor whiteColor]; 112 | confirmConfig.translucentStyle = AXAlertViewTranslucentDark; 113 | [alertView setActionConfiguration:confirmConfig forItemAtIndex:1]; 114 | [self.navigationController.view addSubview:alertView]; 115 | [alertView show:YES]; 116 | } 117 | 118 | - (IBAction)showNormalWithoutCustomView:(id)sender { 119 | AXAlertView *alertView = [[AXAlertView alloc] initWithFrame:self.navigationController.view.bounds]; 120 | alertView.customViewInset = UIEdgeInsetsMake(5, 20, 10, 20); 121 | alertView.padding = 5; 122 | alertView.cornerRadius = 10.0; 123 | alertView.actionItemMargin = 0; 124 | alertView.actionItemPadding = 0; 125 | alertView.titleLabel.numberOfLines = 0; 126 | alertView.hidesOnTouch = YES; 127 | alertView.title = @"Some title content..."; 128 | alertView.titleLabel.font = [UIFont systemFontOfSize:14]; 129 | alertView.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18]; 130 | alertView.titleLabel.textColor = [UIColor blackColor]; 131 | 132 | [alertView setActions:[AXAlertViewAction actionWithTitle:@"取消" image:nil handler:NULL],[AXAlertViewAction actionWithTitle:@"确认" image:nil handler:NULL],nil]; 133 | // alertView.showsSeparators = NO; 134 | // alertView.translucent = NO; 135 | 136 | AXAlertViewActionConfiguration *cancelConfig = [AXAlertViewActionConfiguration new]; 137 | cancelConfig.backgroundColor = [UIColor whiteColor]; 138 | cancelConfig.heightForLayout = 44; 139 | cancelConfig.cornerRadius = .0; 140 | cancelConfig.tintColor = [UIColor blackColor]; 141 | [alertView setActionConfiguration:cancelConfig forItemAtIndex:0]; 142 | AXAlertViewActionConfiguration *confirmConfig = [AXAlertViewActionConfiguration new]; 143 | confirmConfig.backgroundColor = [UIColor whiteColor]; 144 | confirmConfig.heightForLayout = 44; 145 | confirmConfig.cornerRadius = .0; 146 | confirmConfig.tintColor = [UIColor blackColor]; 147 | [alertView setActionConfiguration:confirmConfig forItemAtIndex:1]; 148 | 149 | [alertView setPreferredMargin:UIEdgeInsetsMake(40, 40, 40, 40)]; 150 | // [alertView setPreferedHeight:14]; 151 | [alertView setActionItemMargin:0]; 152 | [alertView setActionItemPadding:0]; 153 | 154 | [self.navigationController.view addSubview:alertView]; 155 | [alertView show:YES]; 156 | 157 | [self _delayUpdateAlertView:alertView]; 158 | } 159 | 160 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 161 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 162 | UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 163 | switch (indexPath.row) { 164 | case 0: { 165 | [self showNormal:cell]; 166 | } break; 167 | case 1: { 168 | [self showController:cell]; 169 | } break; 170 | case 2: { 171 | [self showNormalWithoutCustomView:cell]; 172 | } break; 173 | case 3: { 174 | [self showMoreItems:cell]; 175 | } break; 176 | case 4: { 177 | [self showSheet:cell]; 178 | } break; 179 | default: 180 | break; 181 | } 182 | } 183 | 184 | - (void)showSheet:(id)sender { 185 | AXAlertController *alert = [AXAlertController alertControllerWithTitle:@"Some title..." message:@"Some message..." preferredStyle:AXAlertControllerStyleActionSheet]; 186 | [alert addAction:[AXAlertAction actionWithTitle:@"取消" style:1 handler:NULL]]; 187 | [alert addAction:[AXAlertAction actionWithTitle:@"确认" handler:NULL]]; 188 | // for (int i = 0; i < 15; i++) { 189 | // [alert addAction:[AXAlertAction actionWithTitle:[NSString stringWithFormat:@"index%@", @(i)] handler:NULL]]; 190 | // } 191 | alert.image = [UIImage imageNamed:@"Image"]; 192 | [self presentViewController:alert animated:YES completion:NULL]; 193 | [self _delayUpdateAlertView:alert.alertView]; 194 | } 195 | 196 | - (void)showController:(id)sender { 197 | AXAlertController *alert = [AXAlertController alertControllerWithTitle:@"Some Title..." message:@"Some message..." preferredStyle:AXAlertControllerStyleAlert]; 198 | // alert.image = [UIImage imageNamed:@"Image"]; 199 | [alert addAction:[AXAlertAction actionWithTitle:@"Cancel" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 200 | config.heightForLayout = 44.0; 201 | config.backgroundColor = [UIColor whiteColor]; 202 | config.font = [UIFont boldSystemFontOfSize:17]; 203 | config.cornerRadius = .0; 204 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 205 | }]; 206 | for (int i = 0; i < 1; i++) { 207 | [alert addAction:[AXAlertAction actionWithTitle:@"OK" style:AXAlertActionStyleDefault handler:NULL] configurationHandler:^(AXAlertActionConfiguration * _Nonnull config) { 208 | config.font = [UIFont systemFontOfSize:17]; 209 | config.tintColor = [UIColor colorWithRed:0 green:0.48 blue:1 alpha:1]; 210 | }]; 211 | } 212 | for (int i = 0; i < 1; i++) { 213 | [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { 214 | textField.placeholder = @"Type text..."; 215 | }]; 216 | } 217 | [alert configureImageViewWithHandler:^(UIImageView * _Nonnull imageView) { 218 | imageView.contentMode = UIViewContentModeCenter; 219 | imageView.image = [self resizedTouchImage]; 220 | }]; 221 | [self presentViewController:alert animated:YES completion:NULL]; 222 | [self _delayUpdateAlertView:alert.alertView]; 223 | } 224 | 225 | - (void)showMoreItems:(id)sender { 226 | AXAlertView *alertView = [[AXAlertView alloc] initWithFrame:self.navigationController.view.bounds]; 227 | alertView.customViewInset = UIEdgeInsetsMake(20, 20, 10, 20); 228 | alertView.padding = 0; 229 | alertView.cornerRadius = 10.0; 230 | alertView.actionItemMargin = 0; 231 | alertView.actionItemPadding = 0; 232 | alertView.titleLabel.numberOfLines = 0; 233 | alertView.hidesOnTouch = YES; 234 | alertView.title = @"兑换申请已受理"; 235 | UILabel *label = [UILabel new]; 236 | label.font = [UIFont systemFontOfSize:14]; 237 | label.numberOfLines = 0; 238 | label.text = @"您还有497个流量币可以兑换,继续兑换?"; 239 | 240 | alertView.customView = label; 241 | 242 | // alertView.showsSeparators = NO; 243 | // alertView.translucent = NO; 244 | 245 | alertView.titleLabel.font = [UIFont systemFontOfSize:14]; 246 | 247 | alertView.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18]; 248 | alertView.titleLabel.textColor = [UIColor blackColor]; 249 | 250 | for (int i = 0; i < 15; i++) { 251 | [alertView appendActions:[AXAlertViewAction actionWithTitle:[NSString stringWithFormat:@"index%@", @(i)] image:nil handler:NULL], nil]; 252 | AXAlertViewActionConfiguration *confirmConfig = [AXAlertViewActionConfiguration new]; 253 | confirmConfig.backgroundColor = [UIColor colorWithWhite:1 alpha:0.3]; 254 | confirmConfig.heightForLayout = 50; 255 | confirmConfig.cornerRadius = .0; 256 | confirmConfig.tintColor = [UIColor whiteColor]; 257 | // confirmConfig.tintColor = [UIColor blackColor]; 258 | confirmConfig.translucent = YES; 259 | confirmConfig.translucentStyle = AXAlertViewTranslucentDark; 260 | // confirmConfig.translucentStyle = AXAlertViewTranslucentLight; 261 | [alertView setActionConfiguration:confirmConfig forItemAtIndex:i]; 262 | } 263 | [self.navigationController.view addSubview:alertView]; 264 | [alertView show:YES]; 265 | 266 | [self _delayUpdateAlertView:alertView]; 267 | } 268 | 269 | - (void)_delayUpdateAlertView:(AXAlertView *)alertView { 270 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 271 | // alertView.titleColor = [UIColor redColor]; 272 | // alertView.titleFont = [UIFont systemFontOfSize:12]; 273 | // alertView.translucent = NO; 274 | // alertView.translucentStyle = AXAlertViewTranslucentDark; 275 | // alertView.showsSeparators = NO; 276 | // alertView.contentInset = UIEdgeInsetsMake(20, 20, 20, 20); 277 | // alertView.customViewInset = UIEdgeInsetsMake(50, 50, 50, 50); 278 | // alertView.titleInset = UIEdgeInsetsMake(50, 50, 50, 50); 279 | // alertView.padding = 50; 280 | // alertView.actionItemPadding = 20; 281 | // alertView.actionItemMargin = 20; 282 | // alertView.horizontalLimits = 20; 283 | // alertView.opacity 284 | // alertView. 285 | // alertView.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Image"]]; 286 | // alertView.customView = nil; 287 | // alertView.verticalOffset = 100; 288 | }); 289 | } 290 | 291 | - (UIImage *)resizedTouchImage { 292 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(44.0, 44.0), NO, [UIScreen mainScreen].scale); 293 | CGContextRef context = UIGraphicsGetCurrentContext(); 294 | CGContextSaveGState(context); 295 | CGContextTranslateCTM(context, 0, 44.0); 296 | CGContextScaleCTM(context, 1.0, -1); 297 | CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor); 298 | CGContextDrawImage(context, CGRectMake(0, 0, 44.0, 44.0), [UIImage imageNamed:@"touch"].CGImage); 299 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 300 | CGContextRestoreGState(context); 301 | UIGraphicsEndImageContext(); 302 | return image; 303 | } 304 | @end 305 | -------------------------------------------------------------------------------- /AXAlertController/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // AXAlertView 4 | // 5 | // Created by ai on 16/4/5. 6 | // Copyright © 2016年 devedbox. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AXAlertController/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // AXAlertView 4 | // 5 | // Created by ai on 16/4/5. 6 | // Copyright © 2016年 devedbox. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "AXAlertView.h" 11 | // #import 12 | 13 | #undef AXAlertViewUsingAutolayout 14 | #define AXAlertViewUsingAutolayout 0 15 | 16 | @interface ViewController () 17 | /// Alert view. 18 | @property(strong, nonatomic) AXAlertView *alertView; 19 | /// Show button. 20 | @property(weak, nonatomic) UIButton *showButton; 21 | @end 22 | 23 | @implementation ViewController 24 | /* 25 | static void test() { 26 | int x = 10; 27 | dispatch_block_t _block = ^() { 28 | NSLog(@"%p", &x); 29 | }; 30 | _block(); 31 | NSLog(@"%@", _block); 32 | dispatch_block_t block = [_block copy]; 33 | block(); 34 | NSLog(@"%@", block); 35 | } */ 36 | 37 | - (void)loadView { 38 | [super loadView]; 39 | 40 | UIButton *showButton = [UIButton buttonWithType:UIButtonTypeSystem]; 41 | showButton.translatesAutoresizingMaskIntoConstraints = NO; 42 | [showButton setTitle:@"show" forState:UIControlStateNormal]; 43 | [showButton setBackgroundColor:[UIColor clearColor]]; 44 | [showButton setAdjustsImageWhenHighlighted:YES]; 45 | [showButton setAdjustsImageWhenDisabled:YES]; 46 | [showButton setTintColor:[UIColor whiteColor]]; 47 | [showButton.layer setCornerRadius:4]; 48 | [showButton.layer setMasksToBounds:YES]; 49 | [showButton addTarget:self action:@selector(showAlertView:) forControlEvents:UIControlEventTouchUpInside]; 50 | [self.view addSubview:showButton]; 51 | _showButton = showButton; 52 | 53 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[showButton]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(showButton)]]; 54 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[showButton(==56)]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(showButton)]]; 55 | } 56 | 57 | - (void)viewDidLoad { 58 | [super viewDidLoad]; 59 | self.view.backgroundColor = [UIColor orangeColor]; 60 | // Do any additional setup after loading the view, typically from a nib. 61 | _alertView = [[AXAlertView alloc] initWithFrame:self.view.bounds]; 62 | UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 63 | textLabel.text = @"到你的骄傲带哦带爱上电脑我回到id宝id赛欧作曲 : G.E.M.作词 : G.E.M. 阳光下的泡沫 是彩色的 就像被骗的我 是幸福的 追究什么对错 你的谎言 基于你还爱我 美丽的泡沫 虽然一刹花火 你所有承诺 虽然都太脆弱 但爱像泡沫 如果能够看破 有什么难过 早该知道泡沫 一触就破 就像已伤的心 不胜折磨 也不是谁的错 谎言再多"; 64 | textLabel.numberOfLines = 0; 65 | _alertView.customView = textLabel; 66 | [_alertView setActions:[AXAlertViewAction actionWithTitle:@"确定" handler:^(AXAlertViewAction *action) { 67 | [_alertView show:YES]; 68 | }],[AXAlertViewAction actionWithTitle:@"取消" handler:NULL],nil]; 69 | _alertView.horizontalLimits = 2; 70 | // _alertView.preferedHeight = 200; 71 | _alertView.title = @"测试"; 72 | _alertView.translucent = YES; 73 | _alertView.hidesOnTouch = YES; 74 | } 75 | 76 | - (void)viewDidAppear:(BOOL)animated { 77 | [super viewDidAppear:animated]; 78 | } 79 | 80 | - (void)didReceiveMemoryWarning { 81 | [super didReceiveMemoryWarning]; 82 | // Dispose of any resources that can be recreated. 83 | } 84 | 85 | - (void)showAlertView:(UIButton *)sender { 86 | 87 | // [_alertView showInView:self.view animated:YES]; 88 | // return; 89 | // Do any additional setup after loading the view, typically from a nib. 90 | 91 | AXAlertView *alertView = [[AXAlertView alloc] initWithFrame:self.view.bounds]; 92 | // alertView.titleInset = UIEdgeInsetsMake(35, 30, 35, 30); 93 | alertView.customViewInset = UIEdgeInsetsMake(5, 20, 10, 20); 94 | alertView.padding = 0; 95 | alertView.cornerRadius = 10.0; 96 | alertView.actionItemMargin = 0; 97 | alertView.actionItemPadding = 0; 98 | alertView.titleLabel.numberOfLines = 0; 99 | alertView.hidesOnTouch = YES; 100 | // alertView.title = @"告知当前状态,信息和解决方法,如果文字换行的情况"; 101 | alertView.title = @"兑换申请已受理"; 102 | UILabel *label = [UILabel new]; 103 | label.font = [UIFont systemFontOfSize:14]; 104 | label.numberOfLines = 0; 105 | label.text = @"您还有497个流量币可以兑换,继续兑换?"; 106 | 107 | alertView.customView = label; 108 | 109 | alertView.titleLabel.font = [UIFont systemFontOfSize:14]; 110 | 111 | alertView.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:18]; 112 | alertView.titleLabel.textColor = [UIColor blackColor]; 113 | 114 | // alertView.showsSeparators = NO; 115 | 116 | [alertView setActions:[AXAlertViewAction actionWithTitle:@"取消" image:nil handler:NULL],[AXAlertViewAction actionWithTitle:@"确认" image:nil handler:^(AXAlertViewAction * _Nonnull __weak action) { 117 | /* 118 | if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"https://www.baidu.com"]]) { 119 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://www.baidu.com"]]; 120 | } 121 | */ 122 | }],nil]; 123 | 124 | AXAlertViewActionConfiguration *cancelConfig = [AXAlertViewActionConfiguration new]; 125 | cancelConfig.backgroundColor = [UIColor colorWithRed:0.949 green:0.949 blue:0.949 alpha:1.00]; 126 | cancelConfig.heightForLayout = 44; 127 | cancelConfig.cornerRadius = .0; 128 | cancelConfig.tintColor = [UIColor blackColor]; 129 | [alertView setActionConfiguration:cancelConfig forItemAtIndex:0]; 130 | AXAlertViewActionConfiguration *confirmConfig = [AXAlertViewActionConfiguration new]; 131 | confirmConfig.backgroundColor = [UIColor blackColor]; 132 | confirmConfig.heightForLayout = 44; 133 | confirmConfig.cornerRadius = .0; 134 | confirmConfig.tintColor = [UIColor blackColor]; 135 | // confirmConfig.translucentStyle = AXAlertViewTranslucentDark; 136 | [alertView setActionConfiguration:confirmConfig forItemAtIndex:1]; 137 | [self.navigationController.view addSubview:alertView]; 138 | [alertView show:YES]; 139 | /* 140 | 141 | for (int i = 0; i < 15; i++) { 142 | [alertView appendActions:[AXAlertViewAction actionWithTitle:[NSString stringWithFormat:@"index%@", @(i)] image:nil handler:NULL], nil]; 143 | AXAlertViewActionConfiguration *confirmConfig = [AXAlertViewActionConfiguration new]; 144 | confirmConfig.backgroundColor = [UIColor colorWithWhite:1 alpha:0.3]; 145 | confirmConfig.preferedHeight = 50; 146 | confirmConfig.cornerRadius = .0; 147 | confirmConfig.tintColor = [UIColor blackColor]; 148 | confirmConfig.translucent = NO; 149 | confirmConfig.translucentStyle = AXAlertViewTranslucentDark; 150 | confirmConfig.translucentStyle = AXAlertViewTranslucentLight; 151 | [alertView setActionConfiguration:confirmConfig forItemAtIndex:i]; 152 | } 153 | [alertView show:YES]; 154 | 155 | */ 156 | /* 157 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Heheda" message:@"Hahaha" preferredStyle:UIAlertControllerStyleAlert]; 158 | [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:NULL]]; 159 | [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:NULL]]; 160 | [self presentViewController:alert animated:YES completion:NULL]; 161 | */ 162 | // test(); 163 | } 164 | @end 165 | -------------------------------------------------------------------------------- /AXAlertController/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devedbox/AXAlertController/d9c1a9408b4b5332e26cb9be88febb6a47f690f4/AXAlertController/image.png -------------------------------------------------------------------------------- /AXAlertController/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AXAlertView 4 | // 5 | // Created by ai on 16/4/5. 6 | // Copyright © 2016年 devedbox. 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ed.x 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | inhibit_all_warnings! 3 | 4 | target 'AXAlertController' do 5 | # pod 'pop' 6 | # pod 'AXExtensions' 7 | # pod 'AXAnimationChain' 8 | end 9 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODFILE CHECKSUM: c57a817740dcac5637db621a7ce342e4a4ec967e 2 | 3 | COCOAPODS: 1.6.1 4 | --------------------------------------------------------------------------------