├── .gitignore ├── .travis.yml ├── LICENSE ├── MKActionSheet.podspec ├── MKActionSheet.xcodeproj └── project.pbxproj ├── MKActionSheet ├── MKASOrientationConfig.h ├── MKASOrientationConfig.m ├── MKASRootViewController.h ├── MKASRootViewController.m ├── MKActionSheet.bundle │ ├── img_select_0@2x.png │ ├── img_select_0@3x.png │ ├── img_select_1@2x.png │ ├── img_select_1@3x.png │ └── img_selected@2x.png ├── MKActionSheet.h ├── MKActionSheet.m ├── MKActionSheetAdd.h └── MKActionSheetAdd.m ├── MKActionSheetDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Resource │ │ ├── Contents.json │ │ ├── image_0.imageset │ │ │ ├── Contents.json │ │ │ └── image_0@2x.png │ │ ├── image_1.imageset │ │ │ ├── Contents.json │ │ │ └── image_1@2x.png │ │ ├── image_2.imageset │ │ │ ├── Contents.json │ │ │ └── image_2@2x.png │ │ ├── image_3.imageset │ │ │ ├── Contents.json │ │ │ └── image_3@2x.png │ │ ├── image_4.imageset │ │ │ ├── Contents.json │ │ │ └── image_4@2x.png │ │ └── image_5.imageset │ │ │ ├── Contents.json │ │ │ └── image_5@2x.png │ └── img_bg.imageset │ │ ├── Contents.json │ │ └── img_bg.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Default-568h@2x.png ├── Info.plist ├── InfoModel.h ├── InfoModel.m ├── Toast │ ├── UIView+Toast.h │ └── UIView+Toast.m ├── ViewController.h ├── ViewController.m └── main.m ├── MKActionSheetTests ├── Info.plist └── MKActionSheetTests.m ├── MKActionSheetUITests ├── Info.plist └── MKActionSheetUITests.m ├── Podfile ├── README.md ├── Resource ├── image_0@2x.png ├── image_1@2x.png ├── image_2@2x.png ├── image_3@2x.png ├── image_4@2x.png ├── image_5@2x.png └── img_separator@3x.png ├── Screenshots ├── 31.png ├── 32.png ├── 33.png ├── 34.png ├── 35.png ├── 36.png ├── 37.png ├── 38.png ├── 39.png └── gif2.gif └── bootstrap /.gitignore: -------------------------------------------------------------------------------- 1 | /Resources 2 | 3 | # osx noise 4 | .DS_Store 5 | profile 6 | 7 | # xcode noise 8 | build/* 9 | *.mode1 10 | *.mode1v3 11 | *.mode2v3 12 | *.perspective 13 | *.perspectivev3 14 | *.pbxuser 15 | *.xcworkspace 16 | xcuserdata 17 | 18 | # svn & cvs 19 | .svn 20 | CVS 21 | MKActionSheet/MKActionSheet.xcodeproj/project.xcworkspace/xcuserdata/xiaomk.xcuserdatad/ 22 | Pods/ 23 | Podfile.lock 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | os: osx 3 | osx_image: xcode7.0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 MK Xiao 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 | -------------------------------------------------------------------------------- /MKActionSheet.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "MKActionSheet" 3 | s.version = "3.0.1" 4 | s.summary = "multi styles and multifunctional actionSheet" 5 | s.homepage = "https://github.com/mk2016/MKActionSheet" 6 | s.license = "MIT" 7 | s.author = { "MK Xiao" => "xiaomk7758@sina.com" } 8 | s.social_media_url = "https://mk2016.github.io" 9 | s.platform = :ios, "8.0" 10 | s.source = { :git => "https://github.com/mk2016/MKActionSheet.git", :tag => s.version } 11 | s.source_files = "MKActionSheet/**/*.{h,m}" 12 | s.resource = "MKActionSheet/MKActionSheet.bundle" 13 | s.requires_arc = true 14 | s.dependency "Masonry", '~> 1.1.0' 15 | end 16 | -------------------------------------------------------------------------------- /MKActionSheet.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 47; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B782EDFC668A3A554EC62495 /* libPods-MKActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4344F53EFBC17740EB28A41B /* libPods-MKActionSheet.a */; }; 11 | C51FB2411D547DEF00A766E1 /* UIView+Toast.m in Sources */ = {isa = PBXBuildFile; fileRef = C51FB2301D547DEF00A766E1 /* UIView+Toast.m */; }; 12 | C52062FA1EBC218A0005F3D2 /* MKASRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C52062F91EBC218A0005F3D2 /* MKASRootViewController.m */; }; 13 | C53D40AE1D524DB1003E1545 /* InfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = C53D40AD1D524DB1003E1545 /* InfoModel.m */; }; 14 | C56728541D9054F2002D0245 /* MKActionSheet.bundle in Resources */ = {isa = PBXBuildFile; fileRef = C567284B1D9054F2002D0245 /* MKActionSheet.bundle */; }; 15 | C56728551D9054F2002D0245 /* MKActionSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = C567284D1D9054F2002D0245 /* MKActionSheet.m */; }; 16 | C5A125C71CFEE7E700FEA77A /* MKActionSheetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C5A125C61CFEE7E700FEA77A /* MKActionSheetTests.m */; }; 17 | C5A125D21CFEE7E700FEA77A /* MKActionSheetUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = C5A125D11CFEE7E700FEA77A /* MKActionSheetUITests.m */; }; 18 | C5A125EB1CFEE91900FEA77A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C5A125E11CFEE91900FEA77A /* AppDelegate.m */; }; 19 | C5A125EC1CFEE91900FEA77A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C5A125E21CFEE91900FEA77A /* Assets.xcassets */; }; 20 | C5A125ED1CFEE91900FEA77A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5A125E31CFEE91900FEA77A /* LaunchScreen.storyboard */; }; 21 | C5A125EE1CFEE91900FEA77A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5A125E51CFEE91900FEA77A /* Main.storyboard */; }; 22 | C5A125F01CFEE91900FEA77A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C5A125E81CFEE91900FEA77A /* main.m */; }; 23 | C5A125F11CFEE91900FEA77A /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C5A125EA1CFEE91900FEA77A /* ViewController.m */; }; 24 | C5AEE5BD1EB0483C00D3BF3C /* MKActionSheetAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = C5AEE5BC1EB0483C00D3BF3C /* MKActionSheetAdd.m */; }; 25 | C5BD1B6C1ECEA611007F45DD /* MKASOrientationConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = C5BD1B6B1ECEA611007F45DD /* MKASOrientationConfig.m */; }; 26 | C5DFD7E91CFFF66500A9E037 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C5DFD7E81CFFF66500A9E037 /* Default-568h@2x.png */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | C5A125C31CFEE7E700FEA77A /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = C5A125A11CFEE7E700FEA77A /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = C5A125A81CFEE7E700FEA77A; 35 | remoteInfo = MKActionSheet; 36 | }; 37 | C5A125CE1CFEE7E700FEA77A /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = C5A125A11CFEE7E700FEA77A /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = C5A125A81CFEE7E700FEA77A; 42 | remoteInfo = MKActionSheet; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 1A0AB92F45101B2D7A88190B /* Pods-MKActionSheet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MKActionSheet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MKActionSheet/Pods-MKActionSheet.debug.xcconfig"; sourceTree = ""; }; 48 | 4344F53EFBC17740EB28A41B /* libPods-MKActionSheet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MKActionSheet.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | C51FB22F1D547DEF00A766E1 /* UIView+Toast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Toast.h"; sourceTree = ""; }; 50 | C51FB2301D547DEF00A766E1 /* UIView+Toast.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Toast.m"; sourceTree = ""; }; 51 | C52062F81EBC218A0005F3D2 /* MKASRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKASRootViewController.h; sourceTree = ""; }; 52 | C52062F91EBC218A0005F3D2 /* MKASRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKASRootViewController.m; sourceTree = ""; }; 53 | C53D40AC1D524DB1003E1545 /* InfoModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfoModel.h; sourceTree = ""; }; 54 | C53D40AD1D524DB1003E1545 /* InfoModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InfoModel.m; sourceTree = ""; }; 55 | C567284B1D9054F2002D0245 /* MKActionSheet.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MKActionSheet.bundle; sourceTree = ""; }; 56 | C567284C1D9054F2002D0245 /* MKActionSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKActionSheet.h; sourceTree = ""; }; 57 | C567284D1D9054F2002D0245 /* MKActionSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKActionSheet.m; sourceTree = ""; }; 58 | C5A125A91CFEE7E700FEA77A /* MKActionSheet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MKActionSheet.app; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | C5A125C21CFEE7E700FEA77A /* MKActionSheetTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MKActionSheetTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | C5A125C61CFEE7E700FEA77A /* MKActionSheetTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MKActionSheetTests.m; sourceTree = ""; }; 61 | C5A125C81CFEE7E700FEA77A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | C5A125CD1CFEE7E700FEA77A /* MKActionSheetUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MKActionSheetUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | C5A125D11CFEE7E700FEA77A /* MKActionSheetUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MKActionSheetUITests.m; sourceTree = ""; }; 64 | C5A125D31CFEE7E700FEA77A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | C5A125E01CFEE91900FEA77A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 66 | C5A125E11CFEE91900FEA77A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 67 | C5A125E21CFEE91900FEA77A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 68 | C5A125E41CFEE91900FEA77A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 69 | C5A125E61CFEE91900FEA77A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 70 | C5A125E71CFEE91900FEA77A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = MKActionSheetDemo/Info.plist; sourceTree = SOURCE_ROOT; }; 71 | C5A125E81CFEE91900FEA77A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = MKActionSheetDemo/main.m; sourceTree = SOURCE_ROOT; }; 72 | C5A125E91CFEE91900FEA77A /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 73 | C5A125EA1CFEE91900FEA77A /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 74 | C5AEE5BB1EB0483C00D3BF3C /* MKActionSheetAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKActionSheetAdd.h; sourceTree = ""; }; 75 | C5AEE5BC1EB0483C00D3BF3C /* MKActionSheetAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKActionSheetAdd.m; sourceTree = ""; }; 76 | C5BD1B6A1ECEA611007F45DD /* MKASOrientationConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKASOrientationConfig.h; sourceTree = ""; }; 77 | C5BD1B6B1ECEA611007F45DD /* MKASOrientationConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKASOrientationConfig.m; sourceTree = ""; }; 78 | C5DFD7E81CFFF66500A9E037 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 79 | D452706DB8406564AF8A4BBE /* Pods-MKActionSheet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MKActionSheet.release.xcconfig"; path = "Pods/Target Support Files/Pods-MKActionSheet/Pods-MKActionSheet.release.xcconfig"; sourceTree = ""; }; 80 | /* End PBXFileReference section */ 81 | 82 | /* Begin PBXFrameworksBuildPhase section */ 83 | C5A125A61CFEE7E700FEA77A /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | B782EDFC668A3A554EC62495 /* libPods-MKActionSheet.a in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | C5A125BF1CFEE7E700FEA77A /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | C5A125CA1CFEE7E700FEA77A /* Frameworks */ = { 99 | isa = PBXFrameworksBuildPhase; 100 | buildActionMask = 2147483647; 101 | files = ( 102 | ); 103 | runOnlyForDeploymentPostprocessing = 0; 104 | }; 105 | /* End PBXFrameworksBuildPhase section */ 106 | 107 | /* Begin PBXGroup section */ 108 | 6A7DAA095EB61B980492901D /* Frameworks */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 4344F53EFBC17740EB28A41B /* libPods-MKActionSheet.a */, 112 | ); 113 | name = Frameworks; 114 | sourceTree = ""; 115 | }; 116 | C51FB22E1D547DEF00A766E1 /* Toast */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | C51FB22F1D547DEF00A766E1 /* UIView+Toast.h */, 120 | C51FB2301D547DEF00A766E1 /* UIView+Toast.m */, 121 | ); 122 | path = Toast; 123 | sourceTree = ""; 124 | }; 125 | C567284A1D9054F2002D0245 /* MKActionSheet */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | C567284B1D9054F2002D0245 /* MKActionSheet.bundle */, 129 | C567284C1D9054F2002D0245 /* MKActionSheet.h */, 130 | C567284D1D9054F2002D0245 /* MKActionSheet.m */, 131 | C5AEE5BB1EB0483C00D3BF3C /* MKActionSheetAdd.h */, 132 | C5AEE5BC1EB0483C00D3BF3C /* MKActionSheetAdd.m */, 133 | C5BD1B6A1ECEA611007F45DD /* MKASOrientationConfig.h */, 134 | C5BD1B6B1ECEA611007F45DD /* MKASOrientationConfig.m */, 135 | C52062F81EBC218A0005F3D2 /* MKASRootViewController.h */, 136 | C52062F91EBC218A0005F3D2 /* MKASRootViewController.m */, 137 | ); 138 | path = MKActionSheet; 139 | sourceTree = ""; 140 | }; 141 | C5A125A01CFEE7E700FEA77A = { 142 | isa = PBXGroup; 143 | children = ( 144 | C567284A1D9054F2002D0245 /* MKActionSheet */, 145 | C5A125DF1CFEE91900FEA77A /* MKActionSheetDemo */, 146 | C5A125C51CFEE7E700FEA77A /* MKActionSheetTests */, 147 | C5A125D01CFEE7E700FEA77A /* MKActionSheetUITests */, 148 | C5A125AA1CFEE7E700FEA77A /* Products */, 149 | E57DB3F1F3D7580C43E2D390 /* Pods */, 150 | 6A7DAA095EB61B980492901D /* Frameworks */, 151 | ); 152 | sourceTree = ""; 153 | }; 154 | C5A125AA1CFEE7E700FEA77A /* Products */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | C5A125A91CFEE7E700FEA77A /* MKActionSheet.app */, 158 | C5A125C21CFEE7E700FEA77A /* MKActionSheetTests.xctest */, 159 | C5A125CD1CFEE7E700FEA77A /* MKActionSheetUITests.xctest */, 160 | ); 161 | name = Products; 162 | sourceTree = ""; 163 | }; 164 | C5A125AC1CFEE7E700FEA77A /* Supporting Files */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | C5A125E81CFEE91900FEA77A /* main.m */, 168 | ); 169 | name = "Supporting Files"; 170 | path = ../MKActionSheet; 171 | sourceTree = ""; 172 | }; 173 | C5A125C51CFEE7E700FEA77A /* MKActionSheetTests */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | C5A125C61CFEE7E700FEA77A /* MKActionSheetTests.m */, 177 | C5A125C81CFEE7E700FEA77A /* Info.plist */, 178 | ); 179 | path = MKActionSheetTests; 180 | sourceTree = ""; 181 | }; 182 | C5A125D01CFEE7E700FEA77A /* MKActionSheetUITests */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | C5A125D11CFEE7E700FEA77A /* MKActionSheetUITests.m */, 186 | C5A125D31CFEE7E700FEA77A /* Info.plist */, 187 | ); 188 | path = MKActionSheetUITests; 189 | sourceTree = ""; 190 | }; 191 | C5A125DF1CFEE91900FEA77A /* MKActionSheetDemo */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | C5A125E91CFEE91900FEA77A /* ViewController.h */, 195 | C5A125EA1CFEE91900FEA77A /* ViewController.m */, 196 | C53D40AC1D524DB1003E1545 /* InfoModel.h */, 197 | C53D40AD1D524DB1003E1545 /* InfoModel.m */, 198 | C5A125F21CFEE98F00FEA77A /* Origin */, 199 | C5CB17FA1D5B04D900C7B983 /* TookKit */, 200 | C5A125AC1CFEE7E700FEA77A /* Supporting Files */, 201 | ); 202 | path = MKActionSheetDemo; 203 | sourceTree = ""; 204 | }; 205 | C5A125F21CFEE98F00FEA77A /* Origin */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | C5DFD7E81CFFF66500A9E037 /* Default-568h@2x.png */, 209 | C5A125E01CFEE91900FEA77A /* AppDelegate.h */, 210 | C5A125E11CFEE91900FEA77A /* AppDelegate.m */, 211 | C5A125E21CFEE91900FEA77A /* Assets.xcassets */, 212 | C5A125E71CFEE91900FEA77A /* Info.plist */, 213 | C5A125E31CFEE91900FEA77A /* LaunchScreen.storyboard */, 214 | C5A125E51CFEE91900FEA77A /* Main.storyboard */, 215 | ); 216 | name = Origin; 217 | sourceTree = ""; 218 | }; 219 | C5CB17FA1D5B04D900C7B983 /* TookKit */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | C51FB22E1D547DEF00A766E1 /* Toast */, 223 | ); 224 | name = TookKit; 225 | sourceTree = ""; 226 | }; 227 | E57DB3F1F3D7580C43E2D390 /* Pods */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | 1A0AB92F45101B2D7A88190B /* Pods-MKActionSheet.debug.xcconfig */, 231 | D452706DB8406564AF8A4BBE /* Pods-MKActionSheet.release.xcconfig */, 232 | ); 233 | name = Pods; 234 | sourceTree = ""; 235 | }; 236 | /* End PBXGroup section */ 237 | 238 | /* Begin PBXNativeTarget section */ 239 | C5A125A81CFEE7E700FEA77A /* MKActionSheet */ = { 240 | isa = PBXNativeTarget; 241 | buildConfigurationList = C5A125D61CFEE7E700FEA77A /* Build configuration list for PBXNativeTarget "MKActionSheet" */; 242 | buildPhases = ( 243 | 6B37F529347CE32996EB6468 /* [CP] Check Pods Manifest.lock */, 244 | C5A125A51CFEE7E700FEA77A /* Sources */, 245 | C5A125A61CFEE7E700FEA77A /* Frameworks */, 246 | C5A125A71CFEE7E700FEA77A /* Resources */, 247 | ); 248 | buildRules = ( 249 | ); 250 | dependencies = ( 251 | ); 252 | name = MKActionSheet; 253 | productName = MKActionSheet; 254 | productReference = C5A125A91CFEE7E700FEA77A /* MKActionSheet.app */; 255 | productType = "com.apple.product-type.application"; 256 | }; 257 | C5A125C11CFEE7E700FEA77A /* MKActionSheetTests */ = { 258 | isa = PBXNativeTarget; 259 | buildConfigurationList = C5A125D91CFEE7E700FEA77A /* Build configuration list for PBXNativeTarget "MKActionSheetTests" */; 260 | buildPhases = ( 261 | C5A125BE1CFEE7E700FEA77A /* Sources */, 262 | C5A125BF1CFEE7E700FEA77A /* Frameworks */, 263 | C5A125C01CFEE7E700FEA77A /* Resources */, 264 | ); 265 | buildRules = ( 266 | ); 267 | dependencies = ( 268 | C5A125C41CFEE7E700FEA77A /* PBXTargetDependency */, 269 | ); 270 | name = MKActionSheetTests; 271 | productName = MKActionSheetTests; 272 | productReference = C5A125C21CFEE7E700FEA77A /* MKActionSheetTests.xctest */; 273 | productType = "com.apple.product-type.bundle.unit-test"; 274 | }; 275 | C5A125CC1CFEE7E700FEA77A /* MKActionSheetUITests */ = { 276 | isa = PBXNativeTarget; 277 | buildConfigurationList = C5A125DC1CFEE7E700FEA77A /* Build configuration list for PBXNativeTarget "MKActionSheetUITests" */; 278 | buildPhases = ( 279 | C5A125C91CFEE7E700FEA77A /* Sources */, 280 | C5A125CA1CFEE7E700FEA77A /* Frameworks */, 281 | C5A125CB1CFEE7E700FEA77A /* Resources */, 282 | ); 283 | buildRules = ( 284 | ); 285 | dependencies = ( 286 | C5A125CF1CFEE7E700FEA77A /* PBXTargetDependency */, 287 | ); 288 | name = MKActionSheetUITests; 289 | productName = MKActionSheetUITests; 290 | productReference = C5A125CD1CFEE7E700FEA77A /* MKActionSheetUITests.xctest */; 291 | productType = "com.apple.product-type.bundle.ui-testing"; 292 | }; 293 | /* End PBXNativeTarget section */ 294 | 295 | /* Begin PBXProject section */ 296 | C5A125A11CFEE7E700FEA77A /* Project object */ = { 297 | isa = PBXProject; 298 | attributes = { 299 | LastUpgradeCheck = 1020; 300 | ORGANIZATIONNAME = MK; 301 | TargetAttributes = { 302 | C5A125A81CFEE7E700FEA77A = { 303 | CreatedOnToolsVersion = 7.3.1; 304 | DevelopmentTeam = HT92EFC285; 305 | ProvisioningStyle = Automatic; 306 | }; 307 | C5A125C11CFEE7E700FEA77A = { 308 | CreatedOnToolsVersion = 7.3.1; 309 | TestTargetID = C5A125A81CFEE7E700FEA77A; 310 | }; 311 | C5A125CC1CFEE7E700FEA77A = { 312 | CreatedOnToolsVersion = 7.3.1; 313 | TestTargetID = C5A125A81CFEE7E700FEA77A; 314 | }; 315 | }; 316 | }; 317 | buildConfigurationList = C5A125A41CFEE7E700FEA77A /* Build configuration list for PBXProject "MKActionSheet" */; 318 | compatibilityVersion = "Xcode 6.3"; 319 | developmentRegion = en; 320 | hasScannedForEncodings = 0; 321 | knownRegions = ( 322 | en, 323 | Base, 324 | ); 325 | mainGroup = C5A125A01CFEE7E700FEA77A; 326 | productRefGroup = C5A125AA1CFEE7E700FEA77A /* Products */; 327 | projectDirPath = ""; 328 | projectRoot = ""; 329 | targets = ( 330 | C5A125A81CFEE7E700FEA77A /* MKActionSheet */, 331 | C5A125C11CFEE7E700FEA77A /* MKActionSheetTests */, 332 | C5A125CC1CFEE7E700FEA77A /* MKActionSheetUITests */, 333 | ); 334 | }; 335 | /* End PBXProject section */ 336 | 337 | /* Begin PBXResourcesBuildPhase section */ 338 | C5A125A71CFEE7E700FEA77A /* Resources */ = { 339 | isa = PBXResourcesBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | C5A125EC1CFEE91900FEA77A /* Assets.xcassets in Resources */, 343 | C56728541D9054F2002D0245 /* MKActionSheet.bundle in Resources */, 344 | C5A125EE1CFEE91900FEA77A /* Main.storyboard in Resources */, 345 | C5A125ED1CFEE91900FEA77A /* LaunchScreen.storyboard in Resources */, 346 | C5DFD7E91CFFF66500A9E037 /* Default-568h@2x.png in Resources */, 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | }; 350 | C5A125C01CFEE7E700FEA77A /* Resources */ = { 351 | isa = PBXResourcesBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | C5A125CB1CFEE7E700FEA77A /* Resources */ = { 358 | isa = PBXResourcesBuildPhase; 359 | buildActionMask = 2147483647; 360 | files = ( 361 | ); 362 | runOnlyForDeploymentPostprocessing = 0; 363 | }; 364 | /* End PBXResourcesBuildPhase section */ 365 | 366 | /* Begin PBXShellScriptBuildPhase section */ 367 | 6B37F529347CE32996EB6468 /* [CP] Check Pods Manifest.lock */ = { 368 | isa = PBXShellScriptBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | ); 372 | inputPaths = ( 373 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 374 | "${PODS_ROOT}/Manifest.lock", 375 | ); 376 | name = "[CP] Check Pods Manifest.lock"; 377 | outputPaths = ( 378 | "$(DERIVED_FILE_DIR)/Pods-MKActionSheet-checkManifestLockResult.txt", 379 | ); 380 | runOnlyForDeploymentPostprocessing = 0; 381 | shellPath = /bin/sh; 382 | 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"; 383 | showEnvVarsInLog = 0; 384 | }; 385 | /* End PBXShellScriptBuildPhase section */ 386 | 387 | /* Begin PBXSourcesBuildPhase section */ 388 | C5A125A51CFEE7E700FEA77A /* Sources */ = { 389 | isa = PBXSourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | C5A125F11CFEE91900FEA77A /* ViewController.m in Sources */, 393 | C51FB2411D547DEF00A766E1 /* UIView+Toast.m in Sources */, 394 | C5BD1B6C1ECEA611007F45DD /* MKASOrientationConfig.m in Sources */, 395 | C52062FA1EBC218A0005F3D2 /* MKASRootViewController.m in Sources */, 396 | C53D40AE1D524DB1003E1545 /* InfoModel.m in Sources */, 397 | C56728551D9054F2002D0245 /* MKActionSheet.m in Sources */, 398 | C5AEE5BD1EB0483C00D3BF3C /* MKActionSheetAdd.m in Sources */, 399 | C5A125F01CFEE91900FEA77A /* main.m in Sources */, 400 | C5A125EB1CFEE91900FEA77A /* AppDelegate.m in Sources */, 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | C5A125BE1CFEE7E700FEA77A /* Sources */ = { 405 | isa = PBXSourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | C5A125C71CFEE7E700FEA77A /* MKActionSheetTests.m in Sources */, 409 | ); 410 | runOnlyForDeploymentPostprocessing = 0; 411 | }; 412 | C5A125C91CFEE7E700FEA77A /* Sources */ = { 413 | isa = PBXSourcesBuildPhase; 414 | buildActionMask = 2147483647; 415 | files = ( 416 | C5A125D21CFEE7E700FEA77A /* MKActionSheetUITests.m in Sources */, 417 | ); 418 | runOnlyForDeploymentPostprocessing = 0; 419 | }; 420 | /* End PBXSourcesBuildPhase section */ 421 | 422 | /* Begin PBXTargetDependency section */ 423 | C5A125C41CFEE7E700FEA77A /* PBXTargetDependency */ = { 424 | isa = PBXTargetDependency; 425 | target = C5A125A81CFEE7E700FEA77A /* MKActionSheet */; 426 | targetProxy = C5A125C31CFEE7E700FEA77A /* PBXContainerItemProxy */; 427 | }; 428 | C5A125CF1CFEE7E700FEA77A /* PBXTargetDependency */ = { 429 | isa = PBXTargetDependency; 430 | target = C5A125A81CFEE7E700FEA77A /* MKActionSheet */; 431 | targetProxy = C5A125CE1CFEE7E700FEA77A /* PBXContainerItemProxy */; 432 | }; 433 | /* End PBXTargetDependency section */ 434 | 435 | /* Begin PBXVariantGroup section */ 436 | C5A125E31CFEE91900FEA77A /* LaunchScreen.storyboard */ = { 437 | isa = PBXVariantGroup; 438 | children = ( 439 | C5A125E41CFEE91900FEA77A /* Base */, 440 | ); 441 | name = LaunchScreen.storyboard; 442 | sourceTree = ""; 443 | }; 444 | C5A125E51CFEE91900FEA77A /* Main.storyboard */ = { 445 | isa = PBXVariantGroup; 446 | children = ( 447 | C5A125E61CFEE91900FEA77A /* Base */, 448 | ); 449 | name = Main.storyboard; 450 | sourceTree = ""; 451 | }; 452 | /* End PBXVariantGroup section */ 453 | 454 | /* Begin XCBuildConfiguration section */ 455 | C5A125D41CFEE7E700FEA77A /* Debug */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | ALWAYS_SEARCH_USER_PATHS = NO; 459 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 460 | CLANG_ANALYZER_NONNULL = YES; 461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 462 | CLANG_CXX_LIBRARY = "libc++"; 463 | CLANG_ENABLE_MODULES = YES; 464 | CLANG_ENABLE_OBJC_ARC = YES; 465 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 466 | CLANG_WARN_BOOL_CONVERSION = YES; 467 | CLANG_WARN_COMMA = YES; 468 | CLANG_WARN_CONSTANT_CONVERSION = YES; 469 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 470 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 471 | CLANG_WARN_EMPTY_BODY = YES; 472 | CLANG_WARN_ENUM_CONVERSION = YES; 473 | CLANG_WARN_INFINITE_RECURSION = YES; 474 | CLANG_WARN_INT_CONVERSION = YES; 475 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 476 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 477 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 478 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 479 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 480 | CLANG_WARN_STRICT_PROTOTYPES = YES; 481 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 482 | CLANG_WARN_UNREACHABLE_CODE = YES; 483 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 484 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 485 | COPY_PHASE_STRIP = NO; 486 | DEBUG_INFORMATION_FORMAT = dwarf; 487 | ENABLE_STRICT_OBJC_MSGSEND = YES; 488 | ENABLE_TESTABILITY = YES; 489 | GCC_C_LANGUAGE_STANDARD = gnu99; 490 | GCC_DYNAMIC_NO_PIC = NO; 491 | GCC_NO_COMMON_BLOCKS = YES; 492 | GCC_OPTIMIZATION_LEVEL = 0; 493 | GCC_PREPROCESSOR_DEFINITIONS = ( 494 | "DEBUG=1", 495 | "$(inherited)", 496 | ); 497 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 498 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 499 | GCC_WARN_UNDECLARED_SELECTOR = YES; 500 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 501 | GCC_WARN_UNUSED_FUNCTION = YES; 502 | GCC_WARN_UNUSED_VARIABLE = YES; 503 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 504 | MTL_ENABLE_DEBUG_INFO = YES; 505 | ONLY_ACTIVE_ARCH = YES; 506 | SDKROOT = iphoneos; 507 | TARGETED_DEVICE_FAMILY = "1,2"; 508 | }; 509 | name = Debug; 510 | }; 511 | C5A125D51CFEE7E700FEA77A /* Release */ = { 512 | isa = XCBuildConfiguration; 513 | buildSettings = { 514 | ALWAYS_SEARCH_USER_PATHS = NO; 515 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 516 | CLANG_ANALYZER_NONNULL = YES; 517 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 518 | CLANG_CXX_LIBRARY = "libc++"; 519 | CLANG_ENABLE_MODULES = YES; 520 | CLANG_ENABLE_OBJC_ARC = YES; 521 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 522 | CLANG_WARN_BOOL_CONVERSION = YES; 523 | CLANG_WARN_COMMA = YES; 524 | CLANG_WARN_CONSTANT_CONVERSION = YES; 525 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 526 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 527 | CLANG_WARN_EMPTY_BODY = YES; 528 | CLANG_WARN_ENUM_CONVERSION = YES; 529 | CLANG_WARN_INFINITE_RECURSION = YES; 530 | CLANG_WARN_INT_CONVERSION = YES; 531 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 532 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 533 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 534 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 535 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 536 | CLANG_WARN_STRICT_PROTOTYPES = YES; 537 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 538 | CLANG_WARN_UNREACHABLE_CODE = YES; 539 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 540 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 541 | COPY_PHASE_STRIP = NO; 542 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 543 | ENABLE_NS_ASSERTIONS = NO; 544 | ENABLE_STRICT_OBJC_MSGSEND = YES; 545 | GCC_C_LANGUAGE_STANDARD = gnu99; 546 | GCC_NO_COMMON_BLOCKS = YES; 547 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 548 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 549 | GCC_WARN_UNDECLARED_SELECTOR = YES; 550 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 551 | GCC_WARN_UNUSED_FUNCTION = YES; 552 | GCC_WARN_UNUSED_VARIABLE = YES; 553 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 554 | MTL_ENABLE_DEBUG_INFO = NO; 555 | SDKROOT = iphoneos; 556 | TARGETED_DEVICE_FAMILY = "1,2"; 557 | VALIDATE_PRODUCT = YES; 558 | }; 559 | name = Release; 560 | }; 561 | C5A125D71CFEE7E700FEA77A /* Debug */ = { 562 | isa = XCBuildConfiguration; 563 | baseConfigurationReference = 1A0AB92F45101B2D7A88190B /* Pods-MKActionSheet.debug.xcconfig */; 564 | buildSettings = { 565 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 566 | CODE_SIGN_IDENTITY = "iPhone Developer"; 567 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 568 | CURRENT_PROJECT_VERSION = 3.0.1.0; 569 | DEVELOPMENT_TEAM = HT92EFC285; 570 | INFOPLIST_FILE = MKActionSheetDemo/Info.plist; 571 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 572 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 573 | MARKETING_VERSION = 3.0.1; 574 | PRODUCT_BUNDLE_IDENTIFIER = com.mk.MKActionSheet; 575 | PRODUCT_NAME = "$(TARGET_NAME)"; 576 | PROVISIONING_PROFILE_SPECIFIER = ""; 577 | }; 578 | name = Debug; 579 | }; 580 | C5A125D81CFEE7E700FEA77A /* Release */ = { 581 | isa = XCBuildConfiguration; 582 | baseConfigurationReference = D452706DB8406564AF8A4BBE /* Pods-MKActionSheet.release.xcconfig */; 583 | buildSettings = { 584 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 585 | CODE_SIGN_IDENTITY = "iPhone Developer"; 586 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 587 | CURRENT_PROJECT_VERSION = 3.0.1.0; 588 | DEVELOPMENT_TEAM = HT92EFC285; 589 | INFOPLIST_FILE = MKActionSheetDemo/Info.plist; 590 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 591 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 592 | MARKETING_VERSION = 3.0.1; 593 | PRODUCT_BUNDLE_IDENTIFIER = com.mk.MKActionSheet; 594 | PRODUCT_NAME = "$(TARGET_NAME)"; 595 | PROVISIONING_PROFILE_SPECIFIER = ""; 596 | }; 597 | name = Release; 598 | }; 599 | C5A125DA1CFEE7E700FEA77A /* Debug */ = { 600 | isa = XCBuildConfiguration; 601 | buildSettings = { 602 | BUNDLE_LOADER = "$(TEST_HOST)"; 603 | INFOPLIST_FILE = MKActionSheetTests/Info.plist; 604 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 605 | PRODUCT_BUNDLE_IDENTIFIER = com.mk.MKActionSheetTests; 606 | PRODUCT_NAME = "$(TARGET_NAME)"; 607 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MKActionSheet.app/MKActionSheet"; 608 | }; 609 | name = Debug; 610 | }; 611 | C5A125DB1CFEE7E700FEA77A /* Release */ = { 612 | isa = XCBuildConfiguration; 613 | buildSettings = { 614 | BUNDLE_LOADER = "$(TEST_HOST)"; 615 | INFOPLIST_FILE = MKActionSheetTests/Info.plist; 616 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 617 | PRODUCT_BUNDLE_IDENTIFIER = com.mk.MKActionSheetTests; 618 | PRODUCT_NAME = "$(TARGET_NAME)"; 619 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MKActionSheet.app/MKActionSheet"; 620 | }; 621 | name = Release; 622 | }; 623 | C5A125DD1CFEE7E700FEA77A /* Debug */ = { 624 | isa = XCBuildConfiguration; 625 | buildSettings = { 626 | INFOPLIST_FILE = MKActionSheetUITests/Info.plist; 627 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 628 | PRODUCT_BUNDLE_IDENTIFIER = com.mk.MKActionSheetUITests; 629 | PRODUCT_NAME = "$(TARGET_NAME)"; 630 | TEST_TARGET_NAME = MKActionSheet; 631 | }; 632 | name = Debug; 633 | }; 634 | C5A125DE1CFEE7E700FEA77A /* Release */ = { 635 | isa = XCBuildConfiguration; 636 | buildSettings = { 637 | INFOPLIST_FILE = MKActionSheetUITests/Info.plist; 638 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 639 | PRODUCT_BUNDLE_IDENTIFIER = com.mk.MKActionSheetUITests; 640 | PRODUCT_NAME = "$(TARGET_NAME)"; 641 | TEST_TARGET_NAME = MKActionSheet; 642 | }; 643 | name = Release; 644 | }; 645 | /* End XCBuildConfiguration section */ 646 | 647 | /* Begin XCConfigurationList section */ 648 | C5A125A41CFEE7E700FEA77A /* Build configuration list for PBXProject "MKActionSheet" */ = { 649 | isa = XCConfigurationList; 650 | buildConfigurations = ( 651 | C5A125D41CFEE7E700FEA77A /* Debug */, 652 | C5A125D51CFEE7E700FEA77A /* Release */, 653 | ); 654 | defaultConfigurationIsVisible = 0; 655 | defaultConfigurationName = Release; 656 | }; 657 | C5A125D61CFEE7E700FEA77A /* Build configuration list for PBXNativeTarget "MKActionSheet" */ = { 658 | isa = XCConfigurationList; 659 | buildConfigurations = ( 660 | C5A125D71CFEE7E700FEA77A /* Debug */, 661 | C5A125D81CFEE7E700FEA77A /* Release */, 662 | ); 663 | defaultConfigurationIsVisible = 0; 664 | defaultConfigurationName = Release; 665 | }; 666 | C5A125D91CFEE7E700FEA77A /* Build configuration list for PBXNativeTarget "MKActionSheetTests" */ = { 667 | isa = XCConfigurationList; 668 | buildConfigurations = ( 669 | C5A125DA1CFEE7E700FEA77A /* Debug */, 670 | C5A125DB1CFEE7E700FEA77A /* Release */, 671 | ); 672 | defaultConfigurationIsVisible = 0; 673 | defaultConfigurationName = Release; 674 | }; 675 | C5A125DC1CFEE7E700FEA77A /* Build configuration list for PBXNativeTarget "MKActionSheetUITests" */ = { 676 | isa = XCConfigurationList; 677 | buildConfigurations = ( 678 | C5A125DD1CFEE7E700FEA77A /* Debug */, 679 | C5A125DE1CFEE7E700FEA77A /* Release */, 680 | ); 681 | defaultConfigurationIsVisible = 0; 682 | defaultConfigurationName = Release; 683 | }; 684 | /* End XCConfigurationList section */ 685 | }; 686 | rootObject = C5A125A11CFEE7E700FEA77A /* Project object */; 687 | } 688 | -------------------------------------------------------------------------------- /MKActionSheet/MKASOrientationConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKASOrientationConfig.h 3 | // MKActionSheet 4 | // 5 | // Created by xmk on 2017/5/19. 6 | // Copyright © 2017年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #ifndef MK_SCREEN_WIDTH 13 | #define MK_SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 14 | #endif 15 | 16 | #ifndef MK_SCREEN_HEIGHT 17 | #define MK_SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 18 | #endif 19 | 20 | #ifndef MK_IS_IPHONE_XX 21 | #define MK_IS_IPHONE_X_XS ([UIScreen instancesRespondToSelector:@selector(currentMode)] ?\ 22 | CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) 23 | #define MK_IS_IPHONE_XSMAX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ?\ 24 | CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size) : NO) 25 | #define MK_IS_IPHONE_XR ([UIScreen instancesRespondToSelector:@selector(currentMode)] ?\ 26 | CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) : NO) 27 | #define MK_IS_IPHONE_XX MK_IS_IPHONE_X_XS || MK_IS_IPHONE_XSMAX || MK_IS_IPHONE_XR 28 | #endif 29 | 30 | #ifndef MK_WEAK_SELF 31 | #define MK_WEAK_SELF __weak typeof(self) weakSelf = self; 32 | #endif 33 | 34 | #ifndef MK_BLOCK_EXEC 35 | #define MK_BLOCK_EXEC(block, ...) if (block) { block(__VA_ARGS__); }; 36 | #endif 37 | 38 | #ifndef MK_COLOR_RGBA 39 | #define MK_COLOR_RGBA(r, g, b, a) [UIColor colorWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:(a)] 40 | #endif 41 | 42 | #ifdef DEBUG 43 | # define MKASLog(fmt, ...) NSLog((@"[Elog] " fmt), ##__VA_ARGS__); 44 | #else 45 | # define MKASLog(...); 46 | #endif 47 | 48 | 49 | #pragma mark - ***** 枚举 ****** 50 | typedef NS_ENUM(NSInteger, MKActionSheetSelectType) { 51 | MKActionSheetSelectType_common = 1, //default 52 | MKActionSheetSelectType_selected, //have a selected button 53 | MKActionSheetSelectType_multiselect, //multiselect 54 | }; 55 | 56 | /** Alignment type of button title,default:center (if button have icon,default:left) */ 57 | typedef NS_ENUM(NSInteger, MKActionSheetButtonTitleAlignment) { 58 | MKActionSheetButtonTitleAlignment_center = 1, //default 59 | MKActionSheetButtonTitleAlignment_left, 60 | MKActionSheetButtonTitleAlignment_right, 61 | }; 62 | 63 | /** if button have icon, type for the 'imageKey' */ 64 | typedef NS_ENUM(NSInteger, MKActionSheetButtonImageValueType) { 65 | MKActionSheetButtonImageValueType_none = 1, //default 66 | MKActionSheetButtonImageValueType_image, 67 | MKActionSheetButtonImageValueType_name, 68 | MKActionSheetButtonImageValueType_url, 69 | }; 70 | 71 | 72 | 73 | @interface MKASOrientationConfig : NSObject 74 | @property (nonatomic, assign) NSTextAlignment titleAlignment; /*!< 标题 对齐方式 [default: center] */ 75 | @property (nonatomic, assign) MKActionSheetButtonTitleAlignment buttonTitleAlignment; /*!< button title Alignment style [default: center] */ 76 | @property (nonatomic, assign) CGFloat buttonHeight; /*!< 按钮高度 [default: 48.0f] */ 77 | @property (nonatomic, assign) CGFloat maxShowButtonCount; /*!< 显示按钮最大个数,支持小数 [default:5.6,全部显示,可设置成 0] */ 78 | @end 79 | -------------------------------------------------------------------------------- /MKActionSheet/MKASOrientationConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKASOrientationConfig.m 3 | // MKActionSheet 4 | // 5 | // Created by xmk on 2017/5/19. 6 | // Copyright © 2017年 MK. All rights reserved. 7 | // 8 | 9 | #import "MKASOrientationConfig.h" 10 | 11 | @implementation MKASOrientationConfig 12 | - (instancetype)init{ 13 | if (self = [super init]) { 14 | _titleAlignment = NSTextAlignmentCenter; 15 | _buttonTitleAlignment = MKActionSheetButtonTitleAlignment_center; 16 | _buttonHeight = 48.0f; 17 | _maxShowButtonCount = 4.6; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /MKActionSheet/MKASRootViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKASRootViewController.h 3 | // MKActionSheet 4 | // 5 | // Created by xmk on 2017/5/5. 6 | // Copyright © 2017年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MKASRootViewController : UIViewController 12 | @property (nonatomic, weak) UIViewController *vc; 13 | @end 14 | -------------------------------------------------------------------------------- /MKActionSheet/MKASRootViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKASRootViewController.m 3 | // MKActionSheet 4 | // 5 | // Created by xmk on 2017/5/5. 6 | // Copyright © 2017年 MK. All rights reserved. 7 | // 8 | 9 | #import "MKASRootViewController.h" 10 | 11 | @interface MKASRootViewController () 12 | 13 | @end 14 | 15 | @implementation MKASRootViewController 16 | 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | } 21 | 22 | - (BOOL)shouldAutorotate{ 23 | return YES; 24 | } 25 | 26 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations{ 27 | return UIInterfaceOrientationMaskAllButUpsideDown; 28 | } 29 | 30 | - (BOOL)prefersStatusBarHidden{ 31 | if (self.vc) { 32 | return [self.vc prefersStatusBarHidden]; 33 | }else{ 34 | return [super prefersStatusBarHidden]; 35 | } 36 | } 37 | 38 | - (UIStatusBarStyle)preferredStatusBarStyle{ 39 | if (self.vc) { 40 | return [self.vc preferredStatusBarStyle]; 41 | }else{ 42 | return [super preferredStatusBarStyle]; 43 | } 44 | } 45 | 46 | - (void)didReceiveMemoryWarning { 47 | [super didReceiveMemoryWarning]; 48 | // Dispose of any resources that can be recreated. 49 | } 50 | 51 | /* 52 | #pragma mark - Navigation 53 | 54 | // In a storyboard-based application, you will often want to do a little preparation before navigation 55 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 56 | // Get the new view controller using [segue destinationViewController]. 57 | // Pass the selected object to the new view controller. 58 | } 59 | */ 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.bundle/img_select_0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheet/MKActionSheet.bundle/img_select_0@2x.png -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.bundle/img_select_0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheet/MKActionSheet.bundle/img_select_0@3x.png -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.bundle/img_select_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheet/MKActionSheet.bundle/img_select_1@2x.png -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.bundle/img_select_1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheet/MKActionSheet.bundle/img_select_1@3x.png -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.bundle/img_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheet/MKActionSheet.bundle/img_selected@2x.png -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKActionSheet.h 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MKASOrientationConfig.h" 11 | 12 | 13 | 14 | @class MKActionSheet, MASConstraintMaker; 15 | #pragma mark - ***** MKActionSheet Block ****** 16 | /** 17 | * clicked block 18 | * 19 | * @param actionSheet self 20 | * @param buttonIndex index with clicked button 21 | */ 22 | typedef void(^MKActionSheetBlock)(MKActionSheet *actionSheet, NSInteger buttonIndex); 23 | 24 | /** 25 | * multiselect block 26 | * 27 | * @param actionSheet self 28 | * @param array selected array 29 | */ 30 | typedef void(^MKActionSheetMultiselectBlock)(MKActionSheet *actionSheet, NSArray *array); 31 | 32 | /** 33 | * load image block 34 | * @param button need loader button 35 | * @param index button index 36 | */ 37 | typedef void(^MKActionSheetLoadImageBlock)(MKActionSheet *actionSheet, UIButton *button, NSInteger index, NSURL *imageUrl); 38 | 39 | typedef void(^MKActionSheetCustomTitleViewLayoutBlock)(MASConstraintMaker *make, UIView *superview); 40 | /** 41 | * PS: 42 | * 有使用者反馈,status bar原来白色会变为黑色,这是由于新建了 window 导致的。 43 | * 可以将 currentVC 设置为当前 viewController 44 | */ 45 | 46 | // default UI setting 47 | // _selected and multiselect style, default no cancel button, title alignment default: Portrait-left, Landscape-center 48 | // init with object array ,default no cancel button 49 | 50 | #pragma mark - ***** MKActionSheet ****** 51 | @interface MKActionSheet : UIView 52 | 53 | /** block */ 54 | @property (nonatomic, copy) MKActionSheetBlock block; /*!< callback for click button */ 55 | @property (nonatomic, copy) MKActionSheetMultiselectBlock multiselectBlock; /*!< callback for multiselect style, return selected array */ 56 | @property (nonatomic, copy) MKActionSheetLoadImageBlock loadUrlImageblock; 57 | 58 | /** custom UI */ 59 | @property (nonatomic, assign) CGFloat windowLevel; /*!< default: UIWindowLevelStatusBar - 1 */ 60 | @property (nonatomic, weak) UIViewController *currentVC; /*!< current viewController, statusBar keep the same style */ 61 | @property (nonatomic, assign) BOOL enabledForBgTap; /*!< default: YES */ 62 | @property (nonatomic, assign) BOOL manualDismiss; /*!< default: NO. if set 'YES', you need calling the method of 63 | 'dismiss' to hide actionSheet by manual */ 64 | @property (nonatomic, assign) BOOL showsVerticalScrollIndicator; /*!< default: NO */ 65 | 66 | /** action sheet */ 67 | @property (nonatomic, assign) CGFloat animationDuration; /*!< 动画化时间 [default: 0.3f] */ 68 | @property (nonatomic, assign) CGFloat blurOpacity; /*!< 毛玻璃透明度 [default: 0.3f] */ 69 | @property (nonatomic, assign) CGFloat blackgroundOpacity; /*!< 灰色背景透明度 [default: 0.3f] */ 70 | 71 | //title 72 | @property (nonatomic, strong) UIColor *titleColor; /*!< 标题颜色 [default: RGBA(100.0f, 100.0f, 100.0f, 1.0f)]*/ 73 | @property (nonatomic, strong) UIFont *titleFont; /*!< 标题字体 [default: sys 14] */ 74 | @property (nonatomic, assign) CGFloat titleMargin; /*!< title side spacee [default: 20] */ 75 | 76 | //button 77 | @property (nonatomic, strong) UIColor *buttonTitleColor; /*!< 按钮 titile 颜色 [default:RBGA(51.0f, 51.0f, 51.0f, 1.0f)] */ 78 | @property (nonatomic, strong) UIFont *buttonTitleFont; /*!< 按钮 字体 [default: sys 18] */ 79 | @property (nonatomic, assign) CGFloat buttonOpacity; /*!< 按钮透明度 [default: 0.6] */ 80 | @property (nonatomic, assign) CGFloat buttonImageRightSpace; /*!< 带图片样式 图片右边离 title 的距离 [default: 12.f] */ 81 | 82 | //destructive Button 83 | @property (nonatomic, assign) NSInteger destructiveButtonIndex; /*!< [default:-1]*/ 84 | @property (nonatomic, strong) UIColor *destructiveButtonTitleColor; /*!< [default:RBGA(250.0f, 10.0f, 10.0f, 1.0f)]*/ 85 | 86 | //cancel Title 87 | @property (nonatomic, assign) BOOL needCancelButton; /*!< 是否需要取消按钮 */ 88 | @property (nonatomic, copy) NSString *cancelTitle; /*!< cancel button title [dafault:取消] */ 89 | 90 | 91 | //MKActionSheetSelectType_selected 92 | @property (nonatomic, assign) NSInteger selectedIndex; /*!< selected button index */ 93 | @property (nonatomic, copy) NSString *selectedBtnImageName; /*!< image name for selected button */ 94 | 95 | //MKActionSheetSelectType_multiselect 96 | @property (nonatomic, copy) NSString *selectBtnImageNameNormal; /*!< image name for select button normal state */ 97 | @property (nonatomic, copy) NSString *selectBtnImageNameSelected; /*!< image name for select button selected state )*/ 98 | @property (nonatomic, strong) NSString *multiselectConfirmButtonTitle; /*!< confirm button title */ 99 | @property (nonatomic, strong) UIColor *multiselectConfirmButtonTitleColor; /*!< confirm button title color */ 100 | @property (nonatomic, strong) UIImage *placeholderImage; 101 | 102 | @property (nonatomic, strong) MKASOrientationConfig *portraitConfig; /*!< 竖屏 配置 */ 103 | @property (nonatomic, strong) MKASOrientationConfig *landscapeConfig; /*!< 横屏 配置 */ 104 | 105 | #pragma mark - ***** init method ****** 106 | /** 107 | * init MKActionSheet with buttonTitles array and selectType 108 | * 109 | * @param title title string 110 | * @param buttonTitleArray button titles Array 111 | * @param selectType select type 112 | * 113 | * @return self 114 | */ 115 | - (instancetype)initWithTitle:(NSString *)title 116 | buttonTitleArray:(NSArray *)buttonTitleArray 117 | selectType:(MKActionSheetSelectType)selectType; 118 | 119 | /** selectType default: MKActionSheetSelectType_common */ 120 | - (instancetype)initWithTitle:(NSString *)title 121 | buttonTitleArray:(NSArray *)buttonTitleArray; 122 | 123 | /** 124 | * init MKActionSheet with buttonTitles array and selectType 125 | * 126 | * @param title title string 127 | * @param objArray object array 128 | * @param buttonTitleKey the button title key in object 129 | * @prram imageKey the image key in object 130 | * @param imageValueType the image value type 131 | * @param selectType the select type 132 | * 133 | * @return self 134 | */ 135 | - (instancetype)initWithTitle:(NSString *)title 136 | objArray:(NSArray *)objArray 137 | buttonTitleKey:(NSString *)buttonTitleKey 138 | imageKey:(NSString *)imageKey 139 | imageValueType:(MKActionSheetButtonImageValueType)imageValueType 140 | selectType:(MKActionSheetSelectType)selectType; 141 | 142 | /** init with objArray, default: MKActionSheetButtonImageValueType_none */ 143 | - (instancetype)initWithTitle:(NSString *)title 144 | objArray:(NSArray *)objArray 145 | buttonTitleKey:(NSString *)buttonTitleKey 146 | selectType:(MKActionSheetSelectType)selectType; 147 | 148 | /** init with objArray, default: MKActionSheetSelectType_common */ 149 | - (instancetype)initWithTitle:(NSString *)title 150 | objArray:(NSArray *)objArray 151 | buttonTitleKey:(NSString *)buttonTitleKey 152 | imageKey:(NSString *)imageKey 153 | imageValueType:(MKActionSheetButtonImageValueType)imageValueType; 154 | 155 | /** init with objArray, default: MKActionSheetSelectType_common MKActionSheetButtonImageValueType_none */ 156 | - (instancetype)initWithTitle:(NSString *)title 157 | objArray:(NSArray *)objArray 158 | buttonTitleKey:(NSString *)buttonTitleKey; 159 | 160 | 161 | - (void)setCustomTitleView:(UIView *)view makeConstraints:(MKActionSheetCustomTitleViewLayoutBlock)block; 162 | 163 | - (void)addButtonWithButtonTitle:(NSString *)title; 164 | - (void)removeButtonWithButtonTitle:(NSString *)title; 165 | 166 | - (void)addButtonWithObj:(id)obj; 167 | - (void)removeButtonWithObj:(id)model; 168 | 169 | - (void)removeButtonWithIndex:(NSInteger)index; 170 | 171 | - (void)reloadWithTitleArray:(NSArray *)titleArray; 172 | - (void)reloadWithObjArray:(NSArray *)objArray; 173 | 174 | 175 | 176 | /** show method */ 177 | /** 178 | * single select block 179 | * 180 | * @param block call back (MKActionSheet* actionSheet, NSInteger buttonIndex, id obj) 181 | */ 182 | - (void)showWithBlock:(MKActionSheetBlock)block; 183 | 184 | /** 185 | * multiselect style block 186 | * 187 | * @param multiselectblock call back (MKActionSheet *actionSheet, NSArray *array) 188 | */ 189 | - (void)showWithMultiselectBlock:(MKActionSheetMultiselectBlock)multiselectblock; 190 | 191 | /** dismiss */ 192 | - (void)dismiss; 193 | @end 194 | 195 | 196 | -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheet.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKActionSheet.m 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import "MKActionSheet.h" 10 | #import "MKActionSheetAdd.h" 11 | #import "MKASRootViewController.h" 12 | #import "Masonry.h" 13 | 14 | #define MKAS_WINDOW_LEVEL UIWindowLevelStatusBar - 1 15 | #define MKAS_BUTTON_SEPARATOR_HEIGHT (1 / [UIScreen mainScreen].scale) 16 | #define MKAS_BUTTON_TAG_BASE 100 17 | #define MKAS_BUTTON_SELECT_TAG 999 18 | 19 | #pragma mark - ***** MKActionSheet ****** 20 | @interface MKActionSheet() 21 | @property (nonatomic, assign) MKActionSheetSelectType selectType; /*!< 选择模式:默认、单选(在初始选择的后面会有标示)、多选*/ 22 | //object Array 23 | @property (nonatomic, copy) NSString *titleKey; /*!< 传入为object array 时 指定 title 的字段名 */ 24 | @property (nonatomic, copy) NSString *imageKey; /*!< 传入为object array 时 指定 button image 对应的字段名 */ 25 | @property (nonatomic, assign) MKActionSheetButtonImageValueType imageValueType; /*!< imageKey对应的类型:image、imageName、imageUrl */ 26 | 27 | @property (nonatomic, strong) MKASOrientationConfig *currentConfig; /*!< 当前配置 */ 28 | 29 | @property (nonatomic, copy) NSString *title; /*!< 标题 */ 30 | @property (nonatomic, strong) NSMutableArray *buttonTitles; /*!< button titles array */ 31 | @property (nonatomic, strong) NSMutableArray *objArray; /*!< objects array */ 32 | 33 | @property (nonatomic, strong) UIWindow *bgWindow; 34 | @property (nonatomic, strong) UIView *shadeView; 35 | @property (nonatomic, strong) UIView *sheetView; 36 | @property (nonatomic, strong) UIView *blurView; 37 | 38 | @property (nonatomic, strong) UIView *titleView; 39 | @property (nonatomic, strong) UILabel *titleLabel; 40 | @property (nonatomic, strong) UIButton *confirmButton; 41 | @property (nonatomic, weak) UIView *customTitleView; /*!< 自定义标题View */ 42 | 43 | @property (nonatomic, strong) UIScrollView *scrollView; 44 | @property (nonatomic, strong) NSMutableArray *buttonViewsArray; 45 | 46 | @property (nonatomic, strong) UIView *cancelView; 47 | @property (nonatomic, strong) UIButton *btnCancel; 48 | @property (nonatomic, strong) UILabel *labCancel; 49 | @property (nonatomic, strong) UIView *cancelSeparatorView; 50 | 51 | @property (nonatomic, copy) MKActionSheetCustomTitleViewLayoutBlock customTitleViewLayoutBlock; 52 | 53 | @property (nonatomic, assign) BOOL paramIsObject; /*!< init array is model or dictionary */ 54 | @property (nonatomic, assign) BOOL isShow; 55 | @property (nonatomic, assign) BOOL initSuccess; 56 | 57 | @property (nonatomic, assign) CGFloat iPhoneXIgnoreBottomH; 58 | @end 59 | 60 | 61 | @implementation MKActionSheet 62 | 63 | #pragma mark - ***** init method ****** 64 | /** init with titles array */ 65 | - (instancetype)initWithTitle:(NSString *)title buttonTitleArray:(NSArray *)buttonTitleArray selectType:(MKActionSheetSelectType)selectType{ 66 | if (self = [super init]) { 67 | _selectType = selectType; 68 | _title = title; 69 | _buttonTitles = buttonTitleArray.mutableCopy; 70 | [self initData]; 71 | } 72 | return self; 73 | } 74 | 75 | - (instancetype)initWithTitle:(NSString *)title buttonTitleArray:(NSArray *)buttonTitleArray{ 76 | return [self initWithTitle:title 77 | buttonTitleArray:buttonTitleArray 78 | selectType:MKActionSheetSelectType_common]; 79 | } 80 | 81 | /** init with objects array */ 82 | - (instancetype)initWithTitle:(NSString *)title 83 | objArray:(NSArray *)objArray 84 | buttonTitleKey:(NSString *)buttonTitleKey 85 | imageKey:(NSString *)imageKey 86 | imageValueType:(MKActionSheetButtonImageValueType)imageValueType 87 | selectType:(MKActionSheetSelectType)selectType{ 88 | 89 | if (self = [super init]) { 90 | _selectType = selectType; 91 | _title = title; 92 | _titleKey = buttonTitleKey; 93 | _objArray = objArray.mutableCopy; 94 | _paramIsObject = YES; 95 | _imageKey = imageKey; 96 | _imageValueType = imageValueType; 97 | if (imageValueType != MKActionSheetButtonImageValueType_none) { 98 | NSAssert(imageKey && imageKey.length > 0, @"设置带 icon 图片的类型,imageKey 不能为nil 或者 空"); 99 | } 100 | [self initData]; 101 | } 102 | return self; 103 | } 104 | 105 | - (instancetype)initWithTitle:(NSString *)title objArray:(NSArray *)objArray buttonTitleKey:(NSString *)buttonTitleKey{ 106 | return [self initWithTitle:title 107 | objArray:objArray 108 | buttonTitleKey:buttonTitleKey 109 | selectType:MKActionSheetSelectType_common]; 110 | } 111 | 112 | - (instancetype)initWithTitle:(NSString *)title objArray:(NSArray *)objArray buttonTitleKey:(NSString *)buttonTitleKey selectType:(MKActionSheetSelectType)selectType{ 113 | return [self initWithTitle:title 114 | objArray:objArray 115 | buttonTitleKey:buttonTitleKey 116 | imageKey:nil 117 | imageValueType:MKActionSheetButtonImageValueType_none 118 | selectType:selectType]; 119 | } 120 | 121 | - (instancetype)initWithTitle:(NSString *)title 122 | objArray:(NSArray *)objArray 123 | buttonTitleKey:(NSString *)buttonTitleKey 124 | imageKey:(NSString *)imageKey 125 | imageValueType:(MKActionSheetButtonImageValueType)imageValueType{ 126 | return [self initWithTitle:title 127 | objArray:objArray 128 | buttonTitleKey:buttonTitleKey 129 | imageKey:imageKey 130 | imageValueType:imageValueType 131 | selectType:MKActionSheetSelectType_common]; 132 | } 133 | 134 | /** init data */ 135 | - (void)initData{ 136 | _iPhoneXIgnoreBottomH = MK_IS_IPHONE_XX ? 34 : 0; 137 | _windowLevel = MKAS_WINDOW_LEVEL; 138 | _enabledForBgTap = YES; 139 | _manualDismiss = NO; 140 | 141 | _animationDuration = 0.3f; 142 | _blurOpacity = 0.3f; 143 | _blackgroundOpacity = 0.3f; 144 | 145 | _titleColor = MK_COLOR_RGBA(100.0f, 100.0f, 100.0f, 1.0f); 146 | _titleFont = [UIFont systemFontOfSize:14]; 147 | _titleMargin = 20.0f; 148 | 149 | _buttonTitleColor = MK_COLOR_RGBA(51.0f,51.0f,51.0f,1.0f); 150 | _buttonTitleFont = [UIFont systemFontOfSize:18.0f]; 151 | _buttonOpacity = 0.6; 152 | _buttonImageRightSpace = 12.f; 153 | 154 | _destructiveButtonIndex = -1; 155 | _destructiveButtonTitleColor = MK_COLOR_RGBA(250.0f, 10.0f, 10.0f, 1.0f); 156 | 157 | _needCancelButton = YES; 158 | _cancelTitle = @"取消"; 159 | 160 | _selectedIndex = -1; 161 | _multiselectConfirmButtonTitle = @"确定"; 162 | _multiselectConfirmButtonTitleColor = MK_COLOR_RGBA(100.0f, 100.0f, 100.0f, 1.0f); 163 | _showsVerticalScrollIndicator = NO; 164 | 165 | //以 object array 初始化,默认没有取消按钮 166 | if (_paramIsObject) { 167 | self.needCancelButton = NO; 168 | } 169 | 170 | // 根据 selectType 和 方向 初始化默认样式 171 | if (self.portraitConfig == nil) { 172 | self.portraitConfig = [[MKASOrientationConfig alloc] init]; 173 | if (_selectType == MKActionSheetSelectType_multiselect || _selectType == MKActionSheetSelectType_selected) { //多选 样式, title 默认 居左对齐,无取消按钮 174 | self.portraitConfig.titleAlignment = NSTextAlignmentLeft; 175 | self.portraitConfig.buttonTitleAlignment = MKActionSheetButtonTitleAlignment_left; 176 | self.portraitConfig.maxShowButtonCount = 5.6; 177 | } 178 | } 179 | 180 | if (self.landscapeConfig == nil) { 181 | self.landscapeConfig = [[MKASOrientationConfig alloc] init]; 182 | if (_selectType == MKActionSheetSelectType_multiselect || _selectType == MKActionSheetSelectType_selected) { //多选 样式, title 默认 居左对齐,无取消按钮 183 | self.landscapeConfig.titleAlignment = NSTextAlignmentCenter; 184 | self.landscapeConfig.buttonTitleAlignment = MKActionSheetButtonTitleAlignment_center; 185 | self.landscapeConfig.maxShowButtonCount = 4.6; 186 | } 187 | } 188 | 189 | [self updateConfigByOrientation]; 190 | } 191 | 192 | - (void)updateConfigByOrientation{ 193 | UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 194 | self.currentConfig = self.portraitConfig; 195 | CGFloat curScreenH = MK_SCREEN_HEIGHT; 196 | if (orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationLandscapeLeft){ 197 | self.currentConfig = self.landscapeConfig; 198 | curScreenH = MK_SCREEN_WIDTH; 199 | } 200 | self.scrollView.showsVerticalScrollIndicator = self.showsVerticalScrollIndicator; 201 | self.scrollView.contentSize = CGSizeMake(curScreenH, self.buttonTitles.count*(self.currentConfig.buttonHeight+MKAS_BUTTON_SEPARATOR_HEIGHT)-MKAS_BUTTON_SEPARATOR_HEIGHT); 202 | } 203 | 204 | #pragma mark - ***** methods ****** 205 | - (void)setSelectedIndex:(NSInteger)selectedIndex{ 206 | if (_selectType == MKActionSheetSelectType_selected) { 207 | _selectedIndex = selectedIndex; 208 | }else{ 209 | MKASLog(@" selectedIndex availability just when selectType = MKActionSheetSelectType_selected"); 210 | } 211 | } 212 | 213 | #pragma mark - ***** add & remove & reload ***** 214 | - (void)addButtonWithButtonTitle:(NSString *)title{ 215 | NSAssert(!_paramIsObject, @"can't add title when init with objArray, please use addButtonWithObj:(id)obj"); 216 | if (title) { 217 | [self.buttonTitles addObject:title]; 218 | [self updateScrollViewAndLayout]; 219 | } 220 | } 221 | 222 | - (void)removeButtonWithButtonTitle:(NSString *)title{ 223 | if (title) { 224 | MK_WEAK_SELF 225 | [self.buttonTitles enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 226 | if ([obj isEqualToString:title]) { 227 | [weakSelf removeButtonWithIndex:idx]; 228 | return ; 229 | } 230 | }]; 231 | } 232 | } 233 | 234 | - (void)addButtonWithObj:(id)obj{ 235 | NSAssert(_paramIsObject, @"can't add object when init with titlesArray, please use addButtonWithButtonTitle:(NSString *)title"); 236 | if (obj) { 237 | [self.objArray addObject:obj]; 238 | [self updateScrollViewAndLayout]; 239 | } 240 | } 241 | 242 | - (void)removeButtonWithObj:(id)model{ 243 | MK_WEAK_SELF 244 | [self.objArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 245 | if (obj == model) { 246 | [weakSelf removeButtonWithIndex:idx]; 247 | return ; 248 | } 249 | }]; 250 | } 251 | 252 | - (void)removeButtonWithIndex:(NSInteger)index{ 253 | if (self.buttonViewsArray.count > index) { 254 | [[self.buttonViewsArray objectAtIndex:index] removeFromSuperview]; 255 | } 256 | if (self.buttonTitles.count > index) { 257 | [self.buttonTitles removeObjectAtIndex:index]; 258 | } 259 | if (_paramIsObject && self.objArray.count > index) { 260 | [self.objArray removeObjectAtIndex:index]; 261 | } 262 | [self updateScrollViewAndLayout]; 263 | } 264 | 265 | - (void)reloadWithTitleArray:(NSArray *)titleArray{ 266 | NSAssert(!_paramIsObject, @"plase use reloadWithObjArray:"); 267 | if (titleArray && titleArray.count > 0) { 268 | [self.buttonTitles removeAllObjects]; 269 | [self.buttonTitles addObjectsFromArray:titleArray]; 270 | [self updateScrollViewAndLayout]; 271 | } 272 | } 273 | 274 | - (void)reloadWithObjArray:(NSArray *)objArray{ 275 | NSAssert(_paramIsObject, @"plase use reloadWithTitleArray:"); 276 | if (objArray && objArray.count > 0) { 277 | [self.objArray removeAllObjects]; 278 | [self.objArray addObjectsFromArray:objArray]; 279 | [self updateScrollViewAndLayout]; 280 | } 281 | } 282 | 283 | - (void)updateScrollViewAndLayout{ 284 | if (self.initSuccess) { 285 | [self setupScrollView]; 286 | [self setNeedsUpdateConstraints]; 287 | [self updateConstraintsIfNeeded]; 288 | [self layoutIfNeeded]; 289 | } 290 | } 291 | 292 | - (void)setCustomTitleView:(UIView *)view makeConstraints:(MKActionSheetCustomTitleViewLayoutBlock)block{ 293 | if (view == nil) { 294 | return; 295 | } 296 | [_customTitleView removeFromSuperview]; 297 | _customTitleView = nil; 298 | _customTitleView = view; 299 | [self.titleView addSubview:_customTitleView]; 300 | _customTitleViewLayoutBlock = block; 301 | if (_customTitleViewLayoutBlock == nil) { 302 | CGRect tempFrame = _customTitleView.frame; 303 | if (tempFrame.origin.x != 0 || tempFrame.origin.y != 0 || tempFrame.size.width != 0 || tempFrame.size.height != 0) { 304 | _customTitleViewLayoutBlock = ^(MASConstraintMaker *make, UIView *superview) { 305 | make.left.equalTo(superview).offset(tempFrame.origin.x); 306 | make.top.equalTo(superview).offset(tempFrame.origin.y); 307 | make.width.mas_equalTo(tempFrame.size.width); 308 | make.height.mas_equalTo(tempFrame.size.height); 309 | make.bottom.equalTo(superview); 310 | }; 311 | } 312 | } 313 | if (self.initSuccess) { 314 | [self setNeedsUpdateConstraints]; 315 | [self updateConstraintsIfNeeded]; 316 | [self layoutIfNeeded]; 317 | } 318 | 319 | } 320 | 321 | 322 | #pragma mark - ***** show methods ****** 323 | - (void)showWithBlock:(MKActionSheetBlock)block{ 324 | NSAssert(_selectType != MKActionSheetSelectType_multiselect, @"multiselect style, place use: showWithMultiselectBlock:"); 325 | _block = block; 326 | [self show]; 327 | } 328 | 329 | - (void)showWithMultiselectBlock:(MKActionSheetMultiselectBlock)multiselectblock{ 330 | NSAssert(_selectType == MKActionSheetSelectType_multiselect, @"single select style,place use showWithBlock:"); 331 | _multiselectBlock = multiselectblock; 332 | [self show]; 333 | } 334 | 335 | - (void)show{ 336 | if (_blackgroundOpacity < 0.1f) { 337 | _blackgroundOpacity = 0.1f; 338 | } 339 | 340 | [self setupMainView]; 341 | self.isShow = YES; 342 | [self setNeedsUpdateConstraints]; 343 | [self updateConstraintsIfNeeded]; 344 | [UIView animateWithDuration:self.animationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 345 | self.shadeView.alpha = self.blackgroundOpacity; 346 | self.shadeView.userInteractionEnabled = YES; 347 | [self layoutIfNeeded]; 348 | } completion:nil]; 349 | } 350 | 351 | 352 | #pragma mark - ***** dismiss ****** 353 | /** 点击取消按钮 */ 354 | - (void)btnCancelOnclicked:(UIButton *)sender{ 355 | NSInteger index = sender.tag; 356 | [self dismissWithButtonIndex:index]; 357 | } 358 | 359 | /** 单选 点击按钮 */ 360 | - (void)btnClick:(UIButton *)sender{ 361 | NSInteger index = sender.tag-MKAS_BUTTON_TAG_BASE; 362 | if (self.selectType == MKActionSheetSelectType_multiselect){ //多选 363 | NSString *title = [self.buttonTitles objectAtIndex:index]; 364 | title.mkas_selected = !title.mkas_selected; 365 | UIView *view = self.buttonViewsArray[index]; 366 | UIButton *btn = [view viewWithTag:MKAS_BUTTON_SELECT_TAG]; 367 | btn.selected = title.mkas_selected; 368 | }else if(self.selectType == MKActionSheetSelectType_selected){ 369 | self.selectedIndex = index; 370 | [self dismissWithButtonIndex:index]; 371 | }else{ 372 | [self dismissWithButtonIndex:index]; 373 | } 374 | } 375 | 376 | - (void)dismissWithButtonIndex:(NSInteger)index{ 377 | if (self.selectType == MKActionSheetSelectType_multiselect) { 378 | //多选样式下 只有 取消按钮才会走这里 379 | MK_BLOCK_EXEC(self.multiselectBlock, self, nil); 380 | }else{ 381 | MK_BLOCK_EXEC(self.block, self, index) 382 | } 383 | [self checkManualDismiss]; 384 | } 385 | 386 | /** 多选确认按钮 */ 387 | - (void)confirmButtonOnclick:(UIButton *)sender{ 388 | 389 | NSMutableArray *selectedArray = [[NSMutableArray alloc] init]; 390 | 391 | for (NSInteger i = 0; i < self.buttonTitles.count; i++) { 392 | NSString *title = [self.buttonTitles objectAtIndex:i]; 393 | if (title.mkas_selected) { 394 | if (self.paramIsObject){ 395 | [selectedArray addObject:[self.objArray objectAtIndex:i]]; 396 | }else{ 397 | [selectedArray addObject:[self.buttonTitles objectAtIndex:i]]; 398 | } 399 | } 400 | } 401 | MK_BLOCK_EXEC(self.multiselectBlock, self, selectedArray); 402 | [self checkManualDismiss]; 403 | } 404 | 405 | - (void)checkManualDismiss{ 406 | if (self.manualDismiss) { 407 | return; 408 | } 409 | [self dismiss]; 410 | } 411 | 412 | - (void)dismiss{ 413 | if (self.selectType == MKActionSheetSelectType_multiselect) { 414 | for (NSString *title in self.buttonTitles) { 415 | title.mkas_selected = NO; 416 | } 417 | } 418 | self.isShow = NO; 419 | [self setNeedsUpdateConstraints]; 420 | [self updateConstraintsIfNeeded]; 421 | [UIView animateWithDuration:self.animationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 422 | [self.shadeView setAlpha:0]; 423 | [self.shadeView setUserInteractionEnabled:NO]; 424 | [self layoutIfNeeded]; 425 | } completion:^(BOOL finished) { 426 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 427 | [self removeFromSuperview]; 428 | self.bgWindow.hidden = YES; 429 | self.bgWindow = nil; 430 | }]; 431 | } 432 | 433 | 434 | 435 | #pragma mark - ***** setup UI ****** 436 | - (void)statusBarOrientationChange:(NSNotification *)notification{ 437 | [self updateConfigByOrientation]; 438 | [self setNeedsUpdateConstraints]; 439 | [self updateConstraintsIfNeeded]; 440 | [self layoutIfNeeded]; 441 | 442 | } 443 | 444 | - (void)setupMainView{ 445 | [self updateConfigByOrientation]; 446 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; 447 | 448 | [self addSubview:self.shadeView]; 449 | [self addSubview:self.sheetView]; 450 | 451 | self.blurView.backgroundColor = MK_COLOR_RGBA(100, 100, 100, _blurOpacity); 452 | UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; 453 | UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:effect]; 454 | [self.blurView addSubview:effectView]; 455 | [self.sheetView addSubview:self.blurView]; 456 | 457 | [effectView mas_makeConstraints:^(MASConstraintMaker *make) { 458 | make.edges.equalTo(self.blurView); 459 | }]; 460 | 461 | [self.sheetView addSubview:self.titleView]; 462 | [self.sheetView addSubview:self.scrollView]; 463 | [self.sheetView addSubview:self.cancelView]; 464 | [self.cancelView addSubview:self.btnCancel]; 465 | self.btnCancel.userInteractionEnabled = self.needCancelButton; 466 | if (self.needCancelButton) { 467 | [self.cancelView addSubview:self.cancelSeparatorView]; 468 | [self.cancelView addSubview:self.labCancel]; 469 | } 470 | 471 | //UIScrollView 472 | [self setupScrollView]; 473 | 474 | //title 475 | if (self.selectType == MKActionSheetSelectType_multiselect && !self.title) { 476 | self.title = @""; 477 | } 478 | 479 | if (self.title){ 480 | [self.titleView addSubview:self.titleLabel]; 481 | self.titleLabel.text = self.title; 482 | 483 | if (self.selectType == MKActionSheetSelectType_multiselect) { 484 | [self.titleView addSubview:self.confirmButton]; 485 | UIView *leftLine = [[UIView alloc] init]; 486 | leftLine.backgroundColor = MK_COLOR_RGBA(0, 0, 0, 0.2); 487 | [_confirmButton addSubview:leftLine]; 488 | 489 | [leftLine mas_makeConstraints:^(MASConstraintMaker *make) { 490 | make.left.centerY.equalTo(self.confirmButton); 491 | make.width.mas_equalTo(1); 492 | make.height.mas_equalTo(20); 493 | }]; 494 | } 495 | } 496 | 497 | [self.bgWindow.rootViewController.view addSubview:self]; 498 | [self mas_makeConstraints:^(MASConstraintMaker *make) { 499 | make.edges.equalTo(self.bgWindow.rootViewController.view); 500 | }]; 501 | [_bgWindow layoutIfNeeded]; 502 | } 503 | 504 | - (void)setupScrollView{ 505 | //UIScrollView 506 | if (_paramIsObject) { 507 | NSAssert(_titleKey && _titleKey.length > 0, @"titleKey must is validity string"); 508 | NSAssert(_objArray, @"_objArray must no nil"); 509 | for (id obj in _objArray) { 510 | id titleValue = [obj valueForKey:_titleKey]; 511 | if (!titleValue || ![titleValue isKindOfClass:[NSString class]]) { 512 | NSAssert(NO, @"obj.titleKey must is validity string"); 513 | } 514 | _buttonTitles = [[NSMutableArray alloc] initWithArray:[_objArray valueForKey:_titleKey]]; 515 | } 516 | } 517 | self.scrollView.contentSize = CGSizeMake(MK_SCREEN_WIDTH, self.buttonTitles.count*(self.currentConfig.buttonHeight+MKAS_BUTTON_SEPARATOR_HEIGHT)-MKAS_BUTTON_SEPARATOR_HEIGHT); 518 | if (self.buttonViewsArray.count > 0) { 519 | [self.buttonViewsArray makeObjectsPerformSelector:@selector(removeFromSuperview)]; 520 | [self.buttonViewsArray removeAllObjects]; 521 | } 522 | 523 | for (NSInteger i = 0; i < self.buttonTitles.count; i++) { 524 | UIView *view = [[UIView alloc] init]; 525 | view.backgroundColor = [UIColor clearColor]; 526 | [self.scrollView addSubview:view]; 527 | [self.buttonViewsArray addObject:view]; 528 | CGRect viewFrame = CGRectMake(0, self.currentConfig.buttonHeight*i, MK_SCREEN_WIDTH, self.currentConfig.buttonHeight); 529 | view.frame = viewFrame; 530 | 531 | UIButton *btn = [self createButton]; 532 | [view addSubview:btn]; 533 | btn.frame = CGRectMake(0, 0, viewFrame.size.width, viewFrame.size.height-MKAS_BUTTON_SEPARATOR_HEIGHT); 534 | btn.tag = i + MKAS_BUTTON_TAG_BASE; 535 | [btn setTitle:self.buttonTitles[i] forState:UIControlStateNormal]; 536 | [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; 537 | 538 | if (i == self.destructiveButtonIndex) { 539 | [btn setTitleColor:self.destructiveButtonTitleColor forState:UIControlStateNormal]; 540 | } 541 | 542 | if (self.selectType != MKActionSheetSelectType_common) { 543 | UIButton *btnSelect = [self createSelectButton]; 544 | [view addSubview:btnSelect]; 545 | 546 | [btnSelect mas_makeConstraints:^(MASConstraintMaker *make) { 547 | make.right.equalTo(view).offset(-16); 548 | make.centerY.equalTo(view); 549 | }]; 550 | 551 | if (self.selectType == MKActionSheetSelectType_selected){ //单选 552 | if (self.selectedBtnImageName && self.selectedBtnImageName.length > 0) { 553 | [btnSelect setImage:[UIImage imageNamed:self.selectedBtnImageName] forState:UIControlStateDisabled]; 554 | } 555 | btnSelect.hidden = YES; 556 | btnSelect.enabled = NO; 557 | if (self.selectedIndex == i) { 558 | btnSelect.hidden = NO; 559 | } 560 | }else if (self.selectType == MKActionSheetSelectType_multiselect) { //多选 561 | if (self.selectBtnImageNameNormal && self.selectBtnImageNameNormal.length > 0) { 562 | [btnSelect setImage:[UIImage imageNamed:self.selectedBtnImageName] forState:UIControlStateNormal]; 563 | } 564 | if (self.selectBtnImageNameSelected && self.selectBtnImageNameSelected.length > 0) { 565 | [btnSelect setImage:[UIImage imageNamed:self.selectBtnImageNameSelected] forState:UIControlStateSelected]; 566 | [btnSelect setImage:[UIImage imageNamed:self.selectBtnImageNameSelected] forState:UIControlStateHighlighted]; 567 | } 568 | btnSelect.hidden = NO; 569 | NSString *title = [self.buttonTitles objectAtIndex:i]; 570 | btnSelect.selected = title.mkas_selected; 571 | } 572 | } 573 | 574 | if (self.paramIsObject && self.imageKey && self.imageKey.length > 0 && self.imageValueType) { 575 | btn.imageView.contentMode = UIViewContentModeScaleAspectFit; 576 | btn.titleEdgeInsets = UIEdgeInsetsMake(0, _buttonImageRightSpace, 0, 0); 577 | btn.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, _buttonImageRightSpace); 578 | id obj = [self.objArray objectAtIndex:i]; 579 | id imageValue = [obj valueForKey:self.imageKey]; 580 | 581 | if (self.imageValueType == MKActionSheetButtonImageValueType_name) { 582 | if ([imageValue isKindOfClass:[NSString class]]) { 583 | [btn setImage:[UIImage imageNamed:imageValue] forState:UIControlStateNormal]; 584 | } 585 | }else if (self.imageValueType == MKActionSheetButtonImageValueType_image){ 586 | if ([imageValue isKindOfClass:[UIImage class]]) { 587 | [btn setImage:imageValue forState:UIControlStateNormal]; 588 | } 589 | }else if (self.imageValueType == MKActionSheetButtonImageValueType_url){ 590 | if ([imageValue isKindOfClass:[NSString class]] || [imageValue isKindOfClass:[NSURL class]]) { 591 | NSURL *url = nil; 592 | if ([imageValue isKindOfClass:[NSString class]]) { 593 | url = [NSURL URLWithString:imageValue]; 594 | }else if ([imageValue isKindOfClass:[NSURL class]]){ 595 | url = imageValue; 596 | } 597 | if (self.placeholderImage) { 598 | [btn setImage:self.placeholderImage forState:UIControlStateNormal]; 599 | } 600 | // [btn sd_setImageWithURL:url forState:UIControlStateNormal placeholderImage:self.placeholderImage]; 601 | MK_BLOCK_EXEC(self.loadUrlImageblock, self, btn, i, url); 602 | } 603 | } 604 | } 605 | [self updateButtonConstraints:btn]; 606 | 607 | } 608 | } 609 | 610 | - (void)updateButtonConstraints:(UIButton *)btn{ 611 | if (self.currentConfig.buttonTitleAlignment == MKActionSheetButtonTitleAlignment_left) { 612 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 613 | [btn setContentEdgeInsets:UIEdgeInsetsMake(0, self.titleMargin, 0, 0)]; 614 | }else if (self.currentConfig.buttonTitleAlignment == MKActionSheetButtonTitleAlignment_right){ 615 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight; 616 | if (self.selectType == MKActionSheetSelectType_selected || self.selectType == MKActionSheetSelectType_multiselect) { 617 | [btn setContentEdgeInsets:UIEdgeInsetsMake(0, 0, 0, self.titleMargin+60)]; 618 | }else{ 619 | [btn setContentEdgeInsets:UIEdgeInsetsMake(0, 0, 0, self.titleMargin)]; 620 | } 621 | }else if (self.currentConfig.buttonTitleAlignment == MKActionSheetButtonTitleAlignment_center){ 622 | btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 623 | [btn setContentEdgeInsets:UIEdgeInsetsZero]; 624 | } 625 | } 626 | 627 | - (void)updateConstraints{ 628 | self.initSuccess = YES; 629 | 630 | [self.shadeView mas_remakeConstraints:^(MASConstraintMaker *make) { 631 | make.left.right.top.equalTo(self); 632 | make.bottom.equalTo(self.sheetView.mas_top); 633 | }]; 634 | 635 | if (self.isShow) { 636 | [self.sheetView mas_remakeConstraints:^(MASConstraintMaker *make) { 637 | make.left.right.equalTo(self); 638 | make.bottom.equalTo(self.mas_bottom); 639 | }]; 640 | }else{ 641 | [self.sheetView mas_remakeConstraints:^(MASConstraintMaker *make) { 642 | make.left.right.equalTo(self); 643 | make.top.equalTo(self.mas_bottom); 644 | }]; 645 | } 646 | 647 | [self.blurView mas_remakeConstraints:^(MASConstraintMaker *make) { 648 | make.edges.equalTo(self.sheetView); 649 | }]; 650 | 651 | //titleView 652 | [self.titleView mas_remakeConstraints:^(MASConstraintMaker *make) { 653 | make.left.right.top.equalTo(self.sheetView); 654 | }]; 655 | 656 | if (self.customTitleView) { 657 | [self.customTitleView mas_remakeConstraints:^(MASConstraintMaker *make) { 658 | MK_BLOCK_EXEC(self.customTitleViewLayoutBlock, make, self.titleView); 659 | }]; 660 | } else if (self.title){ 661 | self.titleLabel.textAlignment = self.currentConfig.titleAlignment; 662 | if (self.selectType == MKActionSheetSelectType_multiselect) { 663 | [self.confirmButton mas_remakeConstraints:^(MASConstraintMaker *make) { 664 | make.centerY.equalTo(self.titleView); 665 | make.width.mas_equalTo(80); 666 | make.right.equalTo(self.titleView); 667 | make.top.bottom.equalTo(self.titleView); 668 | }]; 669 | 670 | [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { 671 | make.centerY.equalTo(self.titleView); 672 | make.left.equalTo(self.titleView).offset(self.titleMargin); 673 | make.right.equalTo(self.confirmButton.mas_left).offset(-4); 674 | make.top.equalTo(self.titleView).offset(10); 675 | make.bottom.equalTo(self.titleView).offset(-10); 676 | }]; 677 | }else{ 678 | [self.titleLabel mas_remakeConstraints:^(MASConstraintMaker *make) { 679 | make.centerY.equalTo(self.titleView); 680 | make.left.equalTo(self.titleView).offset(self.titleMargin); 681 | make.right.equalTo(self.titleView).offset(-self.titleMargin); 682 | make.top.equalTo(self.titleView).offset(10); 683 | make.bottom.equalTo(self.titleView).offset(-10); 684 | }]; 685 | } 686 | }else{ 687 | [self.titleView mas_remakeConstraints:^(MASConstraintMaker *make) { 688 | make.left.right.top.equalTo(self.sheetView); 689 | make.height.mas_equalTo(0); 690 | }]; 691 | } 692 | 693 | if (self.needCancelButton) { 694 | self.cancelView.hidden = NO; 695 | 696 | [self.cancelView mas_remakeConstraints:^(MASConstraintMaker *make) { 697 | make.top.equalTo(self.scrollView.mas_bottom); 698 | make.left.right.bottom.equalTo(self.sheetView); 699 | }]; 700 | 701 | [self.cancelSeparatorView mas_remakeConstraints:^(MASConstraintMaker *make) { 702 | make.left.right.top.equalTo(self.cancelView); 703 | make.height.mas_equalTo(6); 704 | }]; 705 | 706 | self.btnCancel.tag = _buttonTitles.count; 707 | [self.btnCancel mas_remakeConstraints:^(MASConstraintMaker *make) { 708 | make.left.right.bottom.equalTo(self.cancelView); 709 | make.top.equalTo(self.cancelSeparatorView.mas_bottom); 710 | make.height.mas_equalTo(self.currentConfig.buttonHeight+self.iPhoneXIgnoreBottomH); 711 | }]; 712 | [self.labCancel mas_remakeConstraints:^(MASConstraintMaker *make) { 713 | make.left.right.equalTo(self.cancelView); 714 | make.top.equalTo(self.cancelView).offset(8); 715 | make.bottom.equalTo(self.cancelView).offset(-self.iPhoneXIgnoreBottomH); 716 | // make.edges.equalTo(self.cancelView); 717 | }]; 718 | 719 | }else{ 720 | [self.cancelView mas_remakeConstraints:^(MASConstraintMaker *make) { 721 | make.left.right.bottom.equalTo(self.sheetView); 722 | }]; 723 | self.btnCancel.userInteractionEnabled = NO; 724 | if (MK_IS_IPHONE_XX) { 725 | self.cancelView.hidden = NO; 726 | [self.btnCancel mas_remakeConstraints:^(MASConstraintMaker *make) { 727 | make.edges.equalTo(self.cancelView); 728 | make.height.mas_equalTo(self.iPhoneXIgnoreBottomH+0.1); 729 | }]; 730 | }else{ 731 | self.cancelView.hidden = YES; 732 | } 733 | if (_labCancel) { 734 | _labCancel.hidden = YES; 735 | } 736 | } 737 | 738 | CGFloat maxCount = self.buttonTitles.count; 739 | if (self.currentConfig.maxShowButtonCount > 0) { 740 | maxCount = self.buttonTitles.count > self.currentConfig.maxShowButtonCount ? self.currentConfig.maxShowButtonCount : self.buttonTitles.count; 741 | } 742 | CGFloat viewH = maxCount * (self.currentConfig.buttonHeight+MKAS_BUTTON_SEPARATOR_HEIGHT)-MKAS_BUTTON_SEPARATOR_HEIGHT; 743 | [self.scrollView mas_remakeConstraints:^(MASConstraintMaker *make) { 744 | make.left.right.equalTo(self.sheetView); 745 | make.height.mas_equalTo(viewH); 746 | make.top.equalTo(self.titleView.mas_bottom).offset(MKAS_BUTTON_SEPARATOR_HEIGHT); 747 | make.bottom.equalTo(self.cancelView.mas_top); 748 | }]; 749 | 750 | for (NSInteger i = 0; i < self.buttonViewsArray.count; i++) { 751 | UIView *view = self.buttonViewsArray[i]; 752 | view.frame = CGRectMake(0, (self.currentConfig.buttonHeight+MKAS_BUTTON_SEPARATOR_HEIGHT)*i, MK_SCREEN_WIDTH, self.currentConfig.buttonHeight); 753 | UIButton *btn = [view viewWithTag:i + MKAS_BUTTON_TAG_BASE]; 754 | if (btn) { 755 | btn.frame = CGRectMake(0, 0, MK_SCREEN_WIDTH, self.currentConfig.buttonHeight); 756 | [self updateButtonConstraints:btn]; 757 | } 758 | } 759 | [super updateConstraints]; 760 | } 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | #pragma mark - ***** lazy ****** 770 | - (UIWindow *)bgWindow{ 771 | if (!_bgWindow) { 772 | MKASRootViewController *rootVC = [[MKASRootViewController alloc] init]; 773 | rootVC.vc = _currentVC; 774 | _bgWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 775 | _bgWindow.windowLevel = _windowLevel; 776 | _bgWindow.backgroundColor = [UIColor clearColor]; 777 | _bgWindow.hidden = NO; 778 | _bgWindow.rootViewController = rootVC; 779 | } 780 | return _bgWindow; 781 | } 782 | 783 | - (UIView *)shadeView{ 784 | if (!_shadeView) { 785 | _shadeView = [[UIView alloc] init]; 786 | [_shadeView setBackgroundColor:MK_COLOR_RGBA(0, 0, 0, 1)]; 787 | [_shadeView setUserInteractionEnabled:NO]; 788 | [_shadeView setAlpha:0]; 789 | if (_enabledForBgTap) { 790 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]; 791 | [_shadeView addGestureRecognizer:tap]; 792 | } 793 | } 794 | return _shadeView; 795 | } 796 | 797 | - (UIView *)sheetView{ 798 | if (!_sheetView) { 799 | _sheetView = [[UIView alloc] init]; 800 | [_sheetView setBackgroundColor:[UIColor clearColor]]; 801 | } 802 | return _sheetView; 803 | } 804 | 805 | - (UIView *)blurView{ 806 | if (!_blurView) { 807 | _blurView = [[UIView alloc] init]; 808 | } 809 | return _blurView; 810 | } 811 | 812 | - (UIView *)titleView{ 813 | if (!_titleView) { 814 | _titleView = [[UIView alloc] init]; 815 | _titleView.backgroundColor = MK_COLOR_RGBA(255, 255, 255, _buttonOpacity); 816 | } 817 | return _titleView; 818 | } 819 | 820 | - (UILabel *)titleLabel{ 821 | if (!_titleLabel) { 822 | _titleLabel = [[UILabel alloc] init]; 823 | _titleLabel.text = _title; 824 | _titleLabel.numberOfLines = 0; 825 | _titleLabel.textColor = _titleColor; 826 | _titleLabel.font = _titleFont; 827 | } 828 | return _titleLabel; 829 | } 830 | 831 | - (UIButton *)confirmButton{ 832 | if (!_confirmButton) { 833 | _confirmButton = [UIButton buttonWithType:UIButtonTypeSystem]; 834 | [_confirmButton setTitle:self.multiselectConfirmButtonTitle forState:UIControlStateNormal]; 835 | [_confirmButton setTitleColor:self.multiselectConfirmButtonTitleColor forState:UIControlStateNormal]; 836 | _confirmButton.titleLabel.font = [UIFont systemFontOfSize:16]; 837 | [_confirmButton addTarget:self action:@selector(confirmButtonOnclick:) forControlEvents:UIControlEventTouchUpInside]; 838 | } 839 | return _confirmButton; 840 | } 841 | 842 | 843 | - (UIScrollView *)scrollView{ 844 | if (!_scrollView) { 845 | _scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero]; 846 | _scrollView.delegate = self; 847 | // _scrollView.showsVerticalScrollIndicator = NO; 848 | _scrollView.showsHorizontalScrollIndicator = NO; 849 | _scrollView.bounces = NO; 850 | _scrollView.backgroundColor = [UIColor clearColor]; 851 | } 852 | return _scrollView; 853 | } 854 | 855 | - (UIView *)cancelView{ 856 | if (!_cancelView) { 857 | _cancelView = [[UIView alloc] init]; 858 | } 859 | return _cancelView; 860 | } 861 | 862 | - (UIButton *)btnCancel{ 863 | if (!_btnCancel) { 864 | _btnCancel = [self createButton]; 865 | // [_cancelButton setTitle:_cancelTitle forState:UIControlStateNormal]; 866 | [_btnCancel addTarget:self action:@selector(btnCancelOnclicked:) forControlEvents:UIControlEventTouchUpInside]; 867 | } 868 | return _btnCancel; 869 | } 870 | 871 | - (UIButton *)createButton{ 872 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; 873 | btn.backgroundColor = [UIColor clearColor]; 874 | [btn setBackgroundImage:[UIImage mkas_imageWithColor:[UIColor colorWithRed:1.f green:1.f blue:1.f alpha:_buttonOpacity]] forState:UIControlStateNormal]; 875 | [btn setBackgroundImage:[UIImage mkas_imageWithColor:[UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.1]] forState:UIControlStateHighlighted]; 876 | [btn setTitleColor:_buttonTitleColor forState:UIControlStateNormal]; 877 | btn.titleLabel.font = _buttonTitleFont; 878 | return btn; 879 | } 880 | 881 | - (UIButton *)createSelectButton{ 882 | NSString *bundle = [[NSBundle bundleForClass:self.class] pathForResource:@"MKActionSheet" ofType:@"bundle"]; 883 | NSString *selectImgPath0 = [bundle stringByAppendingPathComponent:@"img_select_0.png"]; 884 | NSString *selectImgPath1 = [bundle stringByAppendingPathComponent:@"img_select_1.png"]; 885 | NSString *selectImgPath2 = [bundle stringByAppendingPathComponent:@"img_selected.png"]; 886 | UIImage *selectImg0 = [UIImage imageWithContentsOfFile:selectImgPath0]; 887 | UIImage *selectImg1 = [UIImage imageWithContentsOfFile:selectImgPath1]; 888 | UIImage *selectImg2 = [UIImage imageWithContentsOfFile:selectImgPath2]; 889 | 890 | UIButton *selectBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 891 | selectBtn.tag = MKAS_BUTTON_SELECT_TAG; 892 | selectBtn.userInteractionEnabled = NO; 893 | [selectBtn setImage:selectImg0 forState:UIControlStateNormal]; 894 | [selectBtn setImage:selectImg1 forState:UIControlStateSelected]; 895 | [selectBtn setImage:selectImg1 forState:UIControlStateHighlighted]; 896 | [selectBtn setImage:selectImg2 forState:UIControlStateDisabled]; 897 | return selectBtn; 898 | } 899 | 900 | - (UIView *)cancelSeparatorView{ 901 | if (!_cancelSeparatorView) { 902 | _cancelSeparatorView = [[UIView alloc] init]; 903 | _cancelSeparatorView.backgroundColor = [UIColor clearColor]; 904 | } 905 | return _cancelSeparatorView; 906 | } 907 | 908 | - (UILabel *)labCancel{ 909 | if (!_labCancel) { 910 | _labCancel = [[UILabel alloc] init]; 911 | _labCancel.text = self.cancelTitle; 912 | _labCancel.textColor = self.buttonTitleColor; 913 | _labCancel.font = self.buttonTitleFont; 914 | _labCancel.textAlignment = NSTextAlignmentCenter; 915 | } 916 | return _labCancel; 917 | } 918 | 919 | 920 | - (NSMutableArray *)buttonViewsArray{ 921 | if (!_buttonViewsArray) { 922 | _buttonViewsArray = @[].mutableCopy; 923 | } 924 | return _buttonViewsArray; 925 | } 926 | 927 | - (NSMutableArray *)buttonTitles{ 928 | if (!_buttonTitles) { 929 | _buttonTitles = @[].mutableCopy; 930 | } 931 | return _buttonTitles; 932 | } 933 | 934 | - (NSMutableArray *)objArray{ 935 | if (!_objArray) { 936 | _objArray = @[].mutableCopy; 937 | } 938 | return _objArray; 939 | } 940 | @end 941 | 942 | 943 | 944 | -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheetAdd.h: -------------------------------------------------------------------------------- 1 | // 2 | // MKActionSheetAdd.h 3 | // MKActionSheet 4 | // 5 | // Created by xmk on 2017/4/26. 6 | // Copyright © 2017年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSObject (MKASAdditions) 13 | @property (nonatomic, assign) BOOL mkas_selected; 14 | @end 15 | 16 | @interface UIImage (MKASAdditions) 17 | + (UIImage *)mkas_imageWithColor:(UIColor *)color; 18 | @end 19 | -------------------------------------------------------------------------------- /MKActionSheet/MKActionSheetAdd.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKActionSheetAdd.m 3 | // MKActionSheet 4 | // 5 | // Created by xmk on 2017/4/26. 6 | // Copyright © 2017年 MK. All rights reserved. 7 | // 8 | 9 | #import "MKActionSheetAdd.h" 10 | #import 11 | 12 | @implementation NSObject (MKASAdditions) 13 | - (void)setMkas_selected:(BOOL)mkas_selected{ 14 | objc_setAssociatedObject(self, @selector(mkas_selected), @(mkas_selected), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 15 | } 16 | 17 | - (BOOL)mkas_selected{ 18 | NSNumber *selected = objc_getAssociatedObject(self, @selector(mkas_selected)); 19 | return [selected boolValue]; 20 | } 21 | 22 | @end 23 | 24 | @implementation UIImage (MKASAdditions) 25 | + (UIImage *)mkas_imageWithColor:(UIColor *)color;{ 26 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 27 | UIGraphicsBeginImageContext(rect.size); 28 | CGContextRef context = UIGraphicsGetCurrentContext(); 29 | CGContextSetFillColorWithColor(context, [color CGColor]); 30 | CGContextFillRect(context, rect); 31 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 32 | UIGraphicsEndImageContext(); 33 | return image; 34 | } 35 | @end 36 | -------------------------------------------------------------------------------- /MKActionSheetDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. 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 | -------------------------------------------------------------------------------- /MKActionSheetDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.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 | 22 | #if DEBUG 23 | // [[MKFPSStatus sharedInstance] open]; 24 | #endif 25 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 26 | 27 | UINavigationBar *navBar = [UINavigationBar appearance]; 28 | navBar.barTintColor = [UIColor colorWithRed:39/255.0f green:39/255.0f blue:39/255.0f alpha:0.94]; 29 | navBar.tintColor = [UIColor whiteColor]; 30 | navBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor whiteColor], 31 | NSFontAttributeName:[UIFont boldSystemFontOfSize:18] 32 | }; 33 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES]; 34 | [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone]; 35 | [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone]; 36 | ViewController* vc = [[ViewController alloc] init]; 37 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; 38 | self.window.rootViewController = nav; 39 | [self.window makeKeyWindow]; 40 | 41 | return YES; 42 | } 43 | 44 | - (void)applicationWillResignActive:(UIApplication *)application { 45 | // 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. 46 | // 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. 47 | } 48 | 49 | - (void)applicationDidEnterBackground:(UIApplication *)application { 50 | // 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. 51 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 52 | } 53 | 54 | - (void)applicationWillEnterForeground:(UIApplication *)application { 55 | // 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. 56 | } 57 | 58 | - (void)applicationDidBecomeActive:(UIApplication *)application { 59 | // 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. 60 | } 61 | 62 | - (void)applicationWillTerminate:(UIApplication *)application { 63 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image_0@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_0.imageset/image_0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/Resource/image_0.imageset/image_0@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image_1@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_1.imageset/image_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/Resource/image_1.imageset/image_1@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image_2@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_2.imageset/image_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/Resource/image_2.imageset/image_2@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image_3@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_3.imageset/image_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/Resource/image_3.imageset/image_3@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image_4@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_4.imageset/image_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/Resource/image_4.imageset/image_4@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image_5@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/Resource/image_5.imageset/image_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/Resource/image_5.imageset/image_5@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/img_bg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "img_bg.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /MKActionSheetDemo/Assets.xcassets/img_bg.imageset/img_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Assets.xcassets/img_bg.imageset/img_bg.png -------------------------------------------------------------------------------- /MKActionSheetDemo/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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MKActionSheetDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /MKActionSheetDemo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/MKActionSheetDemo/Default-568h@2x.png -------------------------------------------------------------------------------- /MKActionSheetDemo/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 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UIRequiresFullScreen 39 | 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | UISupportedInterfaceOrientations~ipad 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationPortraitUpsideDown 50 | UIInterfaceOrientationLandscapeLeft 51 | UIInterfaceOrientationLandscapeRight 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /MKActionSheetDemo/InfoModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // InfoModel.h 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/8/4. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class OtherModel; 13 | @interface InfoModel : NSObject 14 | @property (nonatomic, copy) NSString *titleStr; 15 | @property (nonatomic, copy) NSString *testData; 16 | @property (nonatomic, copy) NSNumber *testNum; 17 | @property (nonatomic, copy) NSString *imageName; 18 | @property (nonatomic, copy) NSString *imageUrl; 19 | @property (nonatomic, strong) UIImage *image; 20 | @property (nonatomic, strong) OtherModel *otherInfo; 21 | @end 22 | 23 | 24 | @interface OtherModel : NSObject 25 | @property (nonatomic, copy) NSString *titleStr; 26 | @property (nonatomic, copy) NSString *otherData; 27 | @property (nonatomic, copy) NSNumber *otherNum; 28 | @end -------------------------------------------------------------------------------- /MKActionSheetDemo/InfoModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // InfoModel.m 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/8/4. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import "InfoModel.h" 10 | @implementation InfoModel 11 | @end 12 | 13 | @implementation OtherModel 14 | @end 15 | -------------------------------------------------------------------------------- /MKActionSheetDemo/Toast/UIView+Toast.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Toast.h 3 | // Toast 4 | // 5 | // Copyright (c) 2011-2015 Charles Scalesse. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a 8 | // copy of this software and associated documentation files (the 9 | // "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, 11 | // distribute, sublicense, and/or sell copies of the Software, and to 12 | // permit persons to whom the Software is furnished to do so, subject to 13 | // the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included 16 | // in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | #import 27 | 28 | extern const NSString * CSToastPositionTop; 29 | extern const NSString * CSToastPositionCenter; 30 | extern const NSString * CSToastPositionBottom; 31 | 32 | @class CSToastStyle; 33 | 34 | /** 35 | Toast is an Objective-C category that adds toast notifications to the UIView 36 | object class. It is intended to be simple, lightweight, and easy to use. Most 37 | toast notifications can be triggered with a single line of code. 38 | 39 | The `makeToast:` methods create a new view and then display it as toast. 40 | 41 | The `showToast:` methods display any view as toast. 42 | 43 | */ 44 | @interface UIView (Toast) 45 | 46 | /** 47 | Creates and presents a new toast view with a message and displays it with the 48 | default duration and position. Styled using the shared style. 49 | 50 | @param message The message to be displayed 51 | */ 52 | - (void)makeToast:(NSString *)message; 53 | 54 | /** 55 | Creates and presents a new toast view with a message. Duration and position 56 | can be set explicitly. Styled using the shared style. 57 | 58 | @param message The message to be displayed 59 | @param duration The toast duration 60 | @param position The toast's center point. Can be one of the predefined CSToastPosition 61 | constants or a `CGPoint` wrapped in an `NSValue` object. 62 | */ 63 | - (void)makeToast:(NSString *)message 64 | duration:(NSTimeInterval)duration 65 | position:(id)position; 66 | 67 | /** 68 | Creates and presents a new toast view with a message. Duration, position, and 69 | style can be set explicitly. 70 | 71 | @param message The message to be displayed 72 | @param duration The toast duration 73 | @param position The toast's center point. Can be one of the predefined CSToastPosition 74 | constants or a `CGPoint` wrapped in an `NSValue` object. 75 | @param style The style. The shared style will be used when nil 76 | */ 77 | - (void)makeToast:(NSString *)message 78 | duration:(NSTimeInterval)duration 79 | position:(id)position 80 | style:(CSToastStyle *)style; 81 | 82 | /** 83 | Creates and presents a new toast view with a message, title, and image. Duration, 84 | position, and style can be set explicitly. The completion block executes when the 85 | toast view completes. `didTap` will be `YES` if the toast view was dismissed from 86 | a tap. 87 | 88 | @param message The message to be displayed 89 | @param duration The toast duration 90 | @param position The toast's center point. Can be one of the predefined CSToastPosition 91 | constants or a `CGPoint` wrapped in an `NSValue` object. 92 | @param title The title 93 | @param image The image 94 | @param style The style. The shared style will be used when nil 95 | @param completion The completion block, executed after the toast view disappears. 96 | didTap will be `YES` if the toast view was dismissed from a tap. 97 | */ 98 | - (void)makeToast:(NSString *)message 99 | duration:(NSTimeInterval)duration 100 | position:(id)position 101 | title:(NSString *)title 102 | image:(UIImage *)image 103 | style:(CSToastStyle *)style 104 | completion:(void(^)(BOOL didTap))completion; 105 | 106 | /** 107 | Creates a new toast view with any combination of message, title, and image. 108 | The look and feel is configured via the style. Unlike the `makeToast:` methods, 109 | this method does not present the toast view automatically. One of the showToast: 110 | methods must be used to present the resulting view. 111 | 112 | @warning if message, title, and image are all nil, this method will return nil. 113 | 114 | @param message The message to be displayed 115 | @param title The title 116 | @param image The image 117 | @param style The style. The shared style will be used when nil 118 | @return The newly created toast view 119 | */ 120 | - (UIView *)toastViewForMessage:(NSString *)message 121 | title:(NSString *)title 122 | image:(UIImage *)image 123 | style:(CSToastStyle *)style; 124 | 125 | /** 126 | Creates and displays a new toast activity indicator view at a specified position. 127 | 128 | @warning Only one toast activity indicator view can be presented per superview. Subsequent 129 | calls to `makeToastActivity:` will be ignored until hideToastActivity is called. 130 | 131 | @warning `makeToastActivity:` works independently of the showToast: methods. Toast activity 132 | views can be presented and dismissed while toast views are being displayed. `makeToastActivity:` 133 | has no effect on the queueing behavior of the showToast: methods. 134 | 135 | @param position The toast's center point. Can be one of the predefined CSToastPosition 136 | constants or a `CGPoint` wrapped in an `NSValue` object. 137 | */ 138 | - (void)makeToastActivity:(id)position; 139 | 140 | /** 141 | Dismisses the active toast activity indicator view. 142 | */ 143 | - (void)hideToastActivity; 144 | 145 | /** 146 | Displays any view as toast using the default duration and position. 147 | 148 | @param toast The view to be displayed as toast 149 | */ 150 | - (void)showToast:(UIView *)toast; 151 | 152 | /** 153 | Displays any view as toast at a provided position and duration. The completion block 154 | executes when the toast view completes. `didTap` will be `YES` if the toast view was 155 | dismissed from a tap. 156 | 157 | @param toast The view to be displayed as toast 158 | @param duration The notification duration 159 | @param position The toast's center point. Can be one of the predefined CSToastPosition 160 | constants or a `CGPoint` wrapped in an `NSValue` object. 161 | @param completion The completion block, executed after the toast view disappears. 162 | didTap will be `YES` if the toast view was dismissed from a tap. 163 | */ 164 | - (void)showToast:(UIView *)toast 165 | duration:(NSTimeInterval)duration 166 | position:(id)position 167 | completion:(void(^)(BOOL didTap))completion; 168 | 169 | @end 170 | 171 | /** 172 | `CSToastStyle` instances define the look and feel for toast views created via the 173 | `makeToast:` methods as well for toast views created directly with 174 | `toastViewForMessage:title:image:style:`. 175 | 176 | @warning `CSToastStyle` offers relatively simple styling options for the default 177 | toast view. If you require a toast view with more complex UI, it probably makes more 178 | sense to create your own custom UIView subclass and present it with the `showToast:` 179 | methods. 180 | */ 181 | @interface CSToastStyle : NSObject 182 | 183 | /** 184 | The background color. Default is `[UIColor blackColor]` at 80% opacity. 185 | */ 186 | @property (strong, nonatomic) UIColor *backgroundColor; 187 | 188 | /** 189 | The title color. Default is `[UIColor whiteColor]`. 190 | */ 191 | @property (strong, nonatomic) UIColor *titleColor; 192 | 193 | /** 194 | The message color. Default is `[UIColor whiteColor]`. 195 | */ 196 | @property (strong, nonatomic) UIColor *messageColor; 197 | 198 | /** 199 | A percentage value from 0.0 to 1.0, representing the maximum width of the toast 200 | view relative to it's superview. Default is 0.8 (80% of the superview's width). 201 | */ 202 | @property (assign, nonatomic) CGFloat maxWidthPercentage; 203 | 204 | /** 205 | A percentage value from 0.0 to 1.0, representing the maximum height of the toast 206 | view relative to it's superview. Default is 0.8 (80% of the superview's height). 207 | */ 208 | @property (assign, nonatomic) CGFloat maxHeightPercentage; 209 | 210 | /** 211 | The spacing from the horizontal edge of the toast view to the content. When an image 212 | is present, this is also used as the padding between the image and the text. 213 | Default is 10.0. 214 | */ 215 | @property (assign, nonatomic) CGFloat horizontalPadding; 216 | 217 | /** 218 | The spacing from the vertical edge of the toast view to the content. When a title 219 | is present, this is also used as the padding between the title and the message. 220 | Default is 10.0. 221 | */ 222 | @property (assign, nonatomic) CGFloat verticalPadding; 223 | 224 | /** 225 | The corner radius. Default is 10.0. 226 | */ 227 | @property (assign, nonatomic) CGFloat cornerRadius; 228 | 229 | /** 230 | The title font. Default is `[UIFont boldSystemFontOfSize:16.0]`. 231 | */ 232 | @property (strong, nonatomic) UIFont *titleFont; 233 | 234 | /** 235 | The message font. Default is `[UIFont systemFontOfSize:16.0]`. 236 | */ 237 | @property (strong, nonatomic) UIFont *messageFont; 238 | 239 | /** 240 | The title text alignment. Default is `NSTextAlignmentLeft`. 241 | */ 242 | @property (assign, nonatomic) NSTextAlignment titleAlignment; 243 | 244 | /** 245 | The message text alignment. Default is `NSTextAlignmentLeft`. 246 | */ 247 | @property (assign, nonatomic) NSTextAlignment messageAlignment; 248 | 249 | /** 250 | The maximum number of lines for the title. The default is 0 (no limit). 251 | */ 252 | @property (assign, nonatomic) NSInteger titleNumberOfLines; 253 | 254 | /** 255 | The maximum number of lines for the message. The default is 0 (no limit). 256 | */ 257 | @property (assign, nonatomic) NSInteger messageNumberOfLines; 258 | 259 | /** 260 | Enable or disable a shadow on the toast view. Default is `NO`. 261 | */ 262 | @property (assign, nonatomic) BOOL displayShadow; 263 | 264 | /** 265 | The shadow color. Default is `[UIColor blackColor]`. 266 | */ 267 | @property (strong, nonatomic) UIColor *shadowColor; 268 | 269 | /** 270 | A value from 0.0 to 1.0, representing the opacity of the shadow. 271 | Default is 0.8 (80% opacity). 272 | */ 273 | @property (assign, nonatomic) CGFloat shadowOpacity; 274 | 275 | /** 276 | The shadow radius. Default is 6.0. 277 | */ 278 | @property (assign, nonatomic) CGFloat shadowRadius; 279 | 280 | /** 281 | The shadow offset. The default is `CGSizeMake(4.0, 4.0)`. 282 | */ 283 | @property (assign, nonatomic) CGSize shadowOffset; 284 | 285 | /** 286 | The image size. The default is `CGSizeMake(80.0, 80.0)`. 287 | */ 288 | @property (assign, nonatomic) CGSize imageSize; 289 | 290 | /** 291 | The size of the toast activity view when `makeToastActivity:` is called. 292 | Default is `CGSizeMake(100.0, 100.0)`. 293 | */ 294 | @property (assign, nonatomic) CGSize activitySize; 295 | 296 | /** 297 | The fade in/out animation duration. Default is 0.2. 298 | */ 299 | @property (assign, nonatomic) NSTimeInterval fadeDuration; 300 | 301 | /** 302 | Creates a new instance of `CSToastStyle` with all the default values set. 303 | */ 304 | - (instancetype)initWithDefaultStyle NS_DESIGNATED_INITIALIZER; 305 | 306 | /** 307 | @warning Only the designated initializer should be used to create 308 | an instance of `CSToastStyle`. 309 | */ 310 | - (instancetype)init NS_UNAVAILABLE; 311 | 312 | @end 313 | 314 | /** 315 | `CSToastManager` provides general configuration options for all toast 316 | notifications. Backed by a singleton instance. 317 | */ 318 | @interface CSToastManager : NSObject 319 | 320 | /** 321 | Sets the shared style on the singleton. The shared style is used whenever 322 | a `makeToast:` method (or `toastViewForMessage:title:image:style:`) is called 323 | with with a nil style. By default, this is set to `CSToastStyle`'s default 324 | style. 325 | 326 | @param sharedStyle 327 | */ 328 | + (void)setSharedStyle:(CSToastStyle *)sharedStyle; 329 | 330 | /** 331 | Gets the shared style from the singlton. By default, this is 332 | `CSToastStyle`'s default style. 333 | 334 | @return the shared style 335 | */ 336 | + (CSToastStyle *)sharedStyle; 337 | 338 | /** 339 | Enables or disables tap to dismiss on toast views. Default is `YES`. 340 | 341 | @param allowTapToDismiss 342 | */ 343 | + (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled; 344 | 345 | /** 346 | Returns `YES` if tap to dismiss is enabled, otherwise `NO`. 347 | Default is `YES`. 348 | 349 | @return BOOL 350 | */ 351 | + (BOOL)isTapToDismissEnabled; 352 | 353 | /** 354 | Enables or disables queueing behavior for toast views. When `YES`, 355 | toast views will appear one after the other. When `NO`, multiple Toast 356 | views will appear at the same time (potentially overlapping depending 357 | on their positions). This has no effect on the toast activity view, 358 | which operates independently of normal toast views. Default is `YES`. 359 | 360 | @param queueEnabled 361 | */ 362 | + (void)setQueueEnabled:(BOOL)queueEnabled; 363 | 364 | /** 365 | Returns `YES` if the queue is enabled, otherwise `NO`. 366 | Default is `YES`. 367 | 368 | @return BOOL 369 | */ 370 | + (BOOL)isQueueEnabled; 371 | 372 | /** 373 | Sets the default duration. Used for the `makeToast:` and 374 | `showToast:` methods that don't require an explicit duration. 375 | Default is 3.0. 376 | 377 | @param duration The toast duration 378 | */ 379 | + (void)setDefaultDuration:(NSTimeInterval)duration; 380 | 381 | /** 382 | Returns the default duration. Default is 3.0. 383 | 384 | @return duration The toast duration 385 | */ 386 | + (NSTimeInterval)defaultDuration; 387 | 388 | /** 389 | Sets the default position. Used for the `makeToast:` and 390 | `showToast:` methods that don't require an explicit position. 391 | Default is `CSToastPositionBottom`. 392 | 393 | @param position The default center point. Can be one of the predefined 394 | CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object. 395 | */ 396 | + (void)setDefaultPosition:(id)position; 397 | 398 | /** 399 | Returns the default toast position. Default is `CSToastPositionBottom`. 400 | 401 | @return position The default center point. Will be one of the predefined 402 | CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object. 403 | */ 404 | + (id)defaultPosition; 405 | 406 | @end 407 | -------------------------------------------------------------------------------- /MKActionSheetDemo/Toast/UIView+Toast.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Toast.m 3 | // Toast 4 | // 5 | // Copyright (c) 2011-2015 Charles Scalesse. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a 8 | // copy of this software and associated documentation files (the 9 | // "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, 11 | // distribute, sublicense, and/or sell copies of the Software, and to 12 | // permit persons to whom the Software is furnished to do so, subject to 13 | // the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included 16 | // in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | #import "UIView+Toast.h" 27 | #import 28 | #import 29 | 30 | NSString * CSToastPositionTop = @"CSToastPositionTop"; 31 | NSString * CSToastPositionCenter = @"CSToastPositionCenter"; 32 | NSString * CSToastPositionBottom = @"CSToastPositionBottom"; 33 | 34 | // Keys for values associated with toast views 35 | static const NSString * CSToastTimerKey = @"CSToastTimerKey"; 36 | static const NSString * CSToastDurationKey = @"CSToastDurationKey"; 37 | static const NSString * CSToastPositionKey = @"CSToastPositionKey"; 38 | static const NSString * CSToastCompletionKey = @"CSToastCompletionKey"; 39 | 40 | // Keys for values associated with self 41 | static const NSString * CSToastActiveToastViewKey = @"CSToastActiveToastViewKey"; 42 | static const NSString * CSToastActivityViewKey = @"CSToastActivityViewKey"; 43 | static const NSString * CSToastQueueKey = @"CSToastQueueKey"; 44 | 45 | @interface UIView (ToastPrivate) 46 | 47 | /** 48 | These private methods are being prefixed with "cs_" to reduce the likelihood of non-obvious 49 | naming conflicts with other UIView methods. 50 | 51 | @discussion Should the public API also use the cs_ prefix? Technically it should, but it 52 | results in code that is less legible. The current public method names seem unlikely to cause 53 | conflicts so I think we should favor the cleaner API for now. 54 | */ 55 | - (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position; 56 | - (void)cs_hideToast:(UIView *)toast; 57 | - (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap; 58 | - (void)cs_toastTimerDidFinish:(NSTimer *)timer; 59 | - (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer; 60 | - (CGPoint)cs_centerPointForPosition:(id)position withToast:(UIView *)toast; 61 | - (NSMutableArray *)cs_toastQueue; 62 | 63 | @end 64 | 65 | @implementation UIView (Toast) 66 | 67 | #pragma mark - Make Toast Methods 68 | 69 | - (void)makeToast:(NSString *)message { 70 | [self makeToast:message duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] style:nil]; 71 | } 72 | 73 | - (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position { 74 | [self makeToast:message duration:duration position:position style:nil]; 75 | } 76 | 77 | - (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position style:(CSToastStyle *)style { 78 | UIView *toast = [self toastViewForMessage:message title:nil image:nil style:style]; 79 | [self showToast:toast duration:duration position:position completion:nil]; 80 | } 81 | 82 | - (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style completion:(void(^)(BOOL didTap))completion { 83 | UIView *toast = [self toastViewForMessage:message title:title image:image style:style]; 84 | [self showToast:toast duration:duration position:position completion:completion]; 85 | } 86 | 87 | #pragma mark - Show Toast Methods 88 | 89 | - (void)showToast:(UIView *)toast { 90 | [self showToast:toast duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] completion:nil]; 91 | } 92 | 93 | - (void)showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position completion:(void(^)(BOOL didTap))completion { 94 | // sanity 95 | if (toast == nil) return; 96 | 97 | // store the completion block on the toast view 98 | objc_setAssociatedObject(toast, &CSToastCompletionKey, completion, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 99 | 100 | if ([CSToastManager isQueueEnabled] && objc_getAssociatedObject(self, &CSToastActiveToastViewKey) != nil) { 101 | // we're about to queue this toast view so we need to store the duration and position as well 102 | objc_setAssociatedObject(toast, &CSToastDurationKey, @(duration), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 103 | objc_setAssociatedObject(toast, &CSToastPositionKey, position, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 104 | 105 | // enqueue 106 | [self.cs_toastQueue addObject:toast]; 107 | } else { 108 | // present 109 | [self cs_showToast:toast duration:duration position:position]; 110 | } 111 | } 112 | 113 | #pragma mark - Private Show/Hide Methods 114 | 115 | - (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position { 116 | toast.center = [self cs_centerPointForPosition:position withToast:toast]; 117 | toast.alpha = 0.0; 118 | 119 | if ([CSToastManager isTapToDismissEnabled]) { 120 | UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cs_handleToastTapped:)]; 121 | [toast addGestureRecognizer:recognizer]; 122 | toast.userInteractionEnabled = YES; 123 | toast.exclusiveTouch = YES; 124 | } 125 | 126 | // set the active toast 127 | objc_setAssociatedObject(self, &CSToastActiveToastViewKey, toast, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 128 | 129 | [self addSubview:toast]; 130 | 131 | [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] 132 | delay:0.0 133 | options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction) 134 | animations:^{ 135 | toast.alpha = 1.0; 136 | } completion:^(BOOL finished) { 137 | NSTimer *timer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(cs_toastTimerDidFinish:) userInfo:toast repeats:NO]; 138 | [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 139 | objc_setAssociatedObject(toast, &CSToastTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 140 | }]; 141 | } 142 | 143 | - (void)cs_hideToast:(UIView *)toast { 144 | [self cs_hideToast:toast fromTap:NO]; 145 | } 146 | 147 | - (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap { 148 | [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] 149 | delay:0.0 150 | options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) 151 | animations:^{ 152 | toast.alpha = 0.0; 153 | } completion:^(BOOL finished) { 154 | [toast removeFromSuperview]; 155 | 156 | // clear the active toast 157 | objc_setAssociatedObject(self, &CSToastActiveToastViewKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 158 | 159 | // execute the completion block, if necessary 160 | void (^completion)(BOOL didTap) = objc_getAssociatedObject(toast, &CSToastCompletionKey); 161 | if (completion) { 162 | completion(fromTap); 163 | } 164 | 165 | if ([self.cs_toastQueue count] > 0) { 166 | // dequeue 167 | UIView *nextToast = [[self cs_toastQueue] firstObject]; 168 | [[self cs_toastQueue] removeObjectAtIndex:0]; 169 | 170 | // present the next toast 171 | NSTimeInterval duration = [objc_getAssociatedObject(nextToast, &CSToastDurationKey) doubleValue]; 172 | id position = objc_getAssociatedObject(nextToast, &CSToastPositionKey); 173 | [self cs_showToast:nextToast duration:duration position:position]; 174 | } 175 | }]; 176 | } 177 | 178 | #pragma mark - View Construction 179 | 180 | - (UIView *)toastViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style { 181 | // sanity 182 | if(message == nil && title == nil && image == nil) return nil; 183 | 184 | // default to the shared style 185 | if (style == nil) { 186 | style = [CSToastManager sharedStyle]; 187 | } 188 | 189 | // dynamically build a toast view with any combination of message, title, & image 190 | UILabel *messageLabel = nil; 191 | UILabel *titleLabel = nil; 192 | UIImageView *imageView = nil; 193 | 194 | UIView *wrapperView = [[UIView alloc] init]; 195 | wrapperView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); 196 | wrapperView.layer.cornerRadius = style.cornerRadius; 197 | 198 | if (style.displayShadow) { 199 | wrapperView.layer.shadowColor = style.shadowColor.CGColor; 200 | wrapperView.layer.shadowOpacity = style.shadowOpacity; 201 | wrapperView.layer.shadowRadius = style.shadowRadius; 202 | wrapperView.layer.shadowOffset = style.shadowOffset; 203 | } 204 | 205 | wrapperView.backgroundColor = style.backgroundColor; 206 | 207 | if(image != nil) { 208 | imageView = [[UIImageView alloc] initWithImage:image]; 209 | imageView.contentMode = UIViewContentModeScaleAspectFit; 210 | imageView.frame = CGRectMake(style.horizontalPadding, style.verticalPadding, style.imageSize.width, style.imageSize.height); 211 | } 212 | 213 | CGRect imageRect = CGRectZero; 214 | 215 | if(imageView != nil) { 216 | imageRect.origin.x = style.horizontalPadding; 217 | imageRect.origin.y = style.verticalPadding; 218 | imageRect.size.width = imageView.bounds.size.width; 219 | imageRect.size.height = imageView.bounds.size.height; 220 | } 221 | 222 | if (title != nil) { 223 | titleLabel = [[UILabel alloc] init]; 224 | titleLabel.numberOfLines = style.titleNumberOfLines; 225 | titleLabel.font = style.titleFont; 226 | titleLabel.textAlignment = style.titleAlignment; 227 | titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; 228 | titleLabel.textColor = style.titleColor; 229 | titleLabel.backgroundColor = [UIColor clearColor]; 230 | titleLabel.alpha = 1.0; 231 | titleLabel.text = title; 232 | 233 | // size the title label according to the length of the text 234 | CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage); 235 | CGSize expectedSizeTitle = [titleLabel sizeThatFits:maxSizeTitle]; 236 | // UILabel can return a size larger than the max size when the number of lines is 1 237 | expectedSizeTitle = CGSizeMake(MIN(maxSizeTitle.width, expectedSizeTitle.width), MIN(maxSizeTitle.height, expectedSizeTitle.height)); 238 | titleLabel.frame = CGRectMake(0.0, 0.0, expectedSizeTitle.width, expectedSizeTitle.height); 239 | } 240 | 241 | if (message != nil) { 242 | messageLabel = [[UILabel alloc] init]; 243 | messageLabel.numberOfLines = style.messageNumberOfLines; 244 | messageLabel.font = style.messageFont; 245 | messageLabel.textAlignment = style.messageAlignment; 246 | messageLabel.lineBreakMode = NSLineBreakByTruncatingTail; 247 | messageLabel.textColor = style.messageColor; 248 | messageLabel.backgroundColor = [UIColor clearColor]; 249 | messageLabel.alpha = 1.0; 250 | messageLabel.text = message; 251 | 252 | CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage); 253 | CGSize expectedSizeMessage = [messageLabel sizeThatFits:maxSizeMessage]; 254 | // UILabel can return a size larger than the max size when the number of lines is 1 255 | expectedSizeMessage = CGSizeMake(MIN(maxSizeMessage.width, expectedSizeMessage.width), MIN(maxSizeMessage.height, expectedSizeMessage.height)); 256 | messageLabel.frame = CGRectMake(0.0, 0.0, expectedSizeMessage.width, expectedSizeMessage.height); 257 | } 258 | 259 | CGRect titleRect = CGRectZero; 260 | 261 | if(titleLabel != nil) { 262 | titleRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding; 263 | titleRect.origin.y = style.verticalPadding; 264 | titleRect.size.width = titleLabel.bounds.size.width; 265 | titleRect.size.height = titleLabel.bounds.size.height; 266 | } 267 | 268 | CGRect messageRect = CGRectZero; 269 | 270 | if(messageLabel != nil) { 271 | messageRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding; 272 | messageRect.origin.y = titleRect.origin.y + titleRect.size.height + style.verticalPadding; 273 | messageRect.size.width = messageLabel.bounds.size.width; 274 | messageRect.size.height = messageLabel.bounds.size.height; 275 | } 276 | 277 | CGFloat longerWidth = MAX(titleRect.size.width, messageRect.size.width); 278 | CGFloat longerX = MAX(titleRect.origin.x, messageRect.origin.x); 279 | 280 | // Wrapper width uses the longerWidth or the image width, whatever is larger. Same logic applies to the wrapper height. 281 | CGFloat wrapperWidth = MAX((imageRect.size.width + (style.horizontalPadding * 2.0)), (longerX + longerWidth + style.horizontalPadding)); 282 | CGFloat wrapperHeight = MAX((messageRect.origin.y + messageRect.size.height + style.verticalPadding), (imageRect.size.height + (style.verticalPadding * 2.0))); 283 | 284 | wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight); 285 | 286 | if(titleLabel != nil) { 287 | titleLabel.frame = titleRect; 288 | [wrapperView addSubview:titleLabel]; 289 | } 290 | 291 | if(messageLabel != nil) { 292 | messageLabel.frame = messageRect; 293 | [wrapperView addSubview:messageLabel]; 294 | } 295 | 296 | if(imageView != nil) { 297 | [wrapperView addSubview:imageView]; 298 | } 299 | 300 | return wrapperView; 301 | } 302 | 303 | #pragma mark - Queue 304 | 305 | - (NSMutableArray *)cs_toastQueue { 306 | NSMutableArray *cs_toastQueue = objc_getAssociatedObject(self, &CSToastQueueKey); 307 | if (cs_toastQueue == nil) { 308 | cs_toastQueue = [[NSMutableArray alloc] init]; 309 | objc_setAssociatedObject(self, &CSToastQueueKey, cs_toastQueue, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 310 | } 311 | return cs_toastQueue; 312 | } 313 | 314 | #pragma mark - Events 315 | 316 | - (void)cs_toastTimerDidFinish:(NSTimer *)timer { 317 | [self cs_hideToast:(UIView *)timer.userInfo]; 318 | } 319 | 320 | - (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer { 321 | UIView *toast = recognizer.view; 322 | NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey); 323 | [timer invalidate]; 324 | 325 | [self cs_hideToast:toast fromTap:YES]; 326 | } 327 | 328 | #pragma mark - Activity Methods 329 | 330 | - (void)makeToastActivity:(id)position { 331 | // sanity 332 | UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey); 333 | if (existingActivityView != nil) return; 334 | 335 | CSToastStyle *style = [CSToastManager sharedStyle]; 336 | 337 | UIView *activityView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, style.activitySize.width, style.activitySize.height)]; 338 | activityView.center = [self cs_centerPointForPosition:position withToast:activityView]; 339 | activityView.backgroundColor = style.backgroundColor; 340 | activityView.alpha = 0.0; 341 | activityView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); 342 | activityView.layer.cornerRadius = style.cornerRadius; 343 | 344 | if (style.displayShadow) { 345 | activityView.layer.shadowColor = style.shadowColor.CGColor; 346 | activityView.layer.shadowOpacity = style.shadowOpacity; 347 | activityView.layer.shadowRadius = style.shadowRadius; 348 | activityView.layer.shadowOffset = style.shadowOffset; 349 | } 350 | 351 | UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; 352 | activityIndicatorView.center = CGPointMake(activityView.bounds.size.width / 2, activityView.bounds.size.height / 2); 353 | [activityView addSubview:activityIndicatorView]; 354 | [activityIndicatorView startAnimating]; 355 | 356 | // associate the activity view with self 357 | objc_setAssociatedObject (self, &CSToastActivityViewKey, activityView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 358 | 359 | [self addSubview:activityView]; 360 | 361 | [UIView animateWithDuration:style.fadeDuration 362 | delay:0.0 363 | options:UIViewAnimationOptionCurveEaseOut 364 | animations:^{ 365 | activityView.alpha = 1.0; 366 | } completion:nil]; 367 | } 368 | 369 | - (void)hideToastActivity { 370 | UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey); 371 | if (existingActivityView != nil) { 372 | [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] 373 | delay:0.0 374 | options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) 375 | animations:^{ 376 | existingActivityView.alpha = 0.0; 377 | } completion:^(BOOL finished) { 378 | [existingActivityView removeFromSuperview]; 379 | objc_setAssociatedObject (self, &CSToastActivityViewKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 380 | }]; 381 | } 382 | } 383 | 384 | #pragma mark - Helpers 385 | 386 | - (CGPoint)cs_centerPointForPosition:(id)point withToast:(UIView *)toast { 387 | CSToastStyle *style = [CSToastManager sharedStyle]; 388 | 389 | if([point isKindOfClass:[NSString class]]) { 390 | if([point caseInsensitiveCompare:CSToastPositionTop] == NSOrderedSame) { 391 | return CGPointMake(self.bounds.size.width/2, (toast.frame.size.height / 2) + style.verticalPadding); 392 | } else if([point caseInsensitiveCompare:CSToastPositionCenter] == NSOrderedSame) { 393 | return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2); 394 | } 395 | } else if ([point isKindOfClass:[NSValue class]]) { 396 | return [point CGPointValue]; 397 | } 398 | 399 | // default to bottom 400 | return CGPointMake(self.bounds.size.width/2, (self.bounds.size.height - (toast.frame.size.height / 2)) - style.verticalPadding); 401 | } 402 | 403 | @end 404 | 405 | @implementation CSToastStyle 406 | 407 | #pragma mark - Constructors 408 | 409 | - (instancetype)initWithDefaultStyle { 410 | self = [super init]; 411 | if (self) { 412 | self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8]; 413 | self.titleColor = [UIColor whiteColor]; 414 | self.messageColor = [UIColor whiteColor]; 415 | self.maxWidthPercentage = 0.8; 416 | self.maxHeightPercentage = 0.8; 417 | self.horizontalPadding = 10.0; 418 | self.verticalPadding = 10.0; 419 | self.cornerRadius = 10.0; 420 | self.titleFont = [UIFont boldSystemFontOfSize:16.0]; 421 | self.messageFont = [UIFont systemFontOfSize:16.0]; 422 | self.titleAlignment = NSTextAlignmentLeft; 423 | self.messageAlignment = NSTextAlignmentLeft; 424 | self.titleNumberOfLines = 0; 425 | self.messageNumberOfLines = 0; 426 | self.displayShadow = NO; 427 | self.shadowOpacity = 0.8; 428 | self.shadowRadius = 6.0; 429 | self.shadowOffset = CGSizeMake(4.0, 4.0); 430 | self.imageSize = CGSizeMake(80.0, 80.0); 431 | self.activitySize = CGSizeMake(100.0, 100.0); 432 | self.fadeDuration = 0.2; 433 | } 434 | return self; 435 | } 436 | 437 | - (void)setMaxWidthPercentage:(CGFloat)maxWidthPercentage { 438 | _maxWidthPercentage = MAX(MIN(maxWidthPercentage, 1.0), 0.0); 439 | } 440 | 441 | - (void)setMaxHeightPercentage:(CGFloat)maxHeightPercentage { 442 | _maxHeightPercentage = MAX(MIN(maxHeightPercentage, 1.0), 0.0); 443 | } 444 | 445 | - (instancetype)init NS_UNAVAILABLE { 446 | return nil; 447 | } 448 | 449 | @end 450 | 451 | @interface CSToastManager () 452 | 453 | @property (strong, nonatomic) CSToastStyle *sharedStyle; 454 | @property (assign, nonatomic, getter=isTapToDismissEnabled) BOOL tapToDismissEnabled; 455 | @property (assign, nonatomic, getter=isQueueEnabled) BOOL queueEnabled; 456 | @property (assign, nonatomic) NSTimeInterval defaultDuration; 457 | @property (strong, nonatomic) id defaultPosition; 458 | 459 | @end 460 | 461 | @implementation CSToastManager 462 | 463 | #pragma mark - Constructors 464 | 465 | + (instancetype)sharedManager { 466 | static CSToastManager *_sharedManager = nil; 467 | static dispatch_once_t oncePredicate; 468 | dispatch_once(&oncePredicate, ^{ 469 | _sharedManager = [[self alloc] init]; 470 | }); 471 | 472 | return _sharedManager; 473 | } 474 | 475 | - (instancetype)init { 476 | self = [super init]; 477 | if (self) { 478 | self.sharedStyle = [[CSToastStyle alloc] initWithDefaultStyle]; 479 | self.tapToDismissEnabled = YES; 480 | self.queueEnabled = NO; 481 | self.defaultDuration = 2.0; 482 | self.defaultPosition = CSToastPositionCenter; 483 | } 484 | return self; 485 | } 486 | 487 | #pragma mark - Singleton Methods 488 | 489 | + (void)setSharedStyle:(CSToastStyle *)sharedStyle { 490 | [[self sharedManager] setSharedStyle:sharedStyle]; 491 | } 492 | 493 | + (CSToastStyle *)sharedStyle { 494 | return [[self sharedManager] sharedStyle]; 495 | } 496 | 497 | + (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled { 498 | [[self sharedManager] setTapToDismissEnabled:tapToDismissEnabled]; 499 | } 500 | 501 | + (BOOL)isTapToDismissEnabled { 502 | return [[self sharedManager] isTapToDismissEnabled]; 503 | } 504 | 505 | + (void)setQueueEnabled:(BOOL)queueEnabled { 506 | [[self sharedManager] setQueueEnabled:queueEnabled]; 507 | } 508 | 509 | + (BOOL)isQueueEnabled { 510 | return [[self sharedManager] isQueueEnabled]; 511 | } 512 | 513 | + (void)setDefaultDuration:(NSTimeInterval)duration { 514 | [[self sharedManager] setDefaultDuration:duration]; 515 | } 516 | 517 | + (NSTimeInterval)defaultDuration { 518 | return [[self sharedManager] defaultDuration]; 519 | } 520 | 521 | + (void)setDefaultPosition:(id)position { 522 | if ([position isKindOfClass:[NSString class]] || [position isKindOfClass:[NSValue class]]) { 523 | [[self sharedManager] setDefaultPosition:position]; 524 | } 525 | } 526 | 527 | + (id)defaultPosition { 528 | return [[self sharedManager] defaultPosition]; 529 | } 530 | 531 | @end 532 | -------------------------------------------------------------------------------- /MKActionSheetDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | @end 13 | 14 | @interface MKCellModel : NSObject 15 | @property (nonatomic, copy) NSString *title; 16 | @property (nonatomic, copy) NSString *detail; 17 | @end 18 | -------------------------------------------------------------------------------- /MKActionSheetDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MKActionSheet.h" 11 | #import "InfoModel.h" 12 | #import "UIButton+WebCache.h" 13 | #import "UIImageView+WebCache.h" 14 | #import "MKActionSheetAdd.h" 15 | #import "UIView+Toast.h" 16 | #import "Masonry.h" 17 | 18 | @interface ViewController () 19 | 20 | @property (nonatomic, strong) UITableView *tableView; 21 | @property (nonatomic, strong) NSMutableArray *sectionTitleArray; 22 | @property (nonatomic, strong) NSMutableArray *datasArray; 23 | 24 | @property (nonatomic, strong) NSMutableArray *detailArray; 25 | @property (nonatomic, strong) NSMutableArray *modelArray; 26 | @property (nonatomic, strong) NSMutableArray *dicArray; 27 | 28 | @property (nonatomic, weak) MKActionSheet *customTitleSheet; 29 | @end 30 | 31 | @implementation ViewController 32 | 33 | - (BOOL)prefersStatusBarHidden{ 34 | return NO; 35 | } 36 | 37 | - (BOOL)shouldAutorotate{ 38 | return YES; 39 | } 40 | 41 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations{ 42 | return UIInterfaceOrientationMaskAllButUpsideDown; 43 | } 44 | 45 | - (UIStatusBarStyle)preferredStatusBarStyle{ 46 | return UIStatusBarStyleLightContent; 47 | } 48 | 49 | - (void)viewDidLoad { 50 | [super viewDidLoad]; 51 | 52 | self.view.backgroundColor = [UIColor whiteColor]; 53 | self.title = @"DEMO"; 54 | 55 | [self initTestData]; 56 | 57 | [self initTableViewDatas]; 58 | 59 | self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; 60 | self.tableView.delegate = self; 61 | self.tableView.dataSource = self; 62 | self.tableView.backgroundColor = [UIColor clearColor]; 63 | self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"img_bg"]]; 64 | self.tableView.showsVerticalScrollIndicator = NO; 65 | self.tableView.estimatedSectionFooterHeight = 0; 66 | self.tableView.estimatedSectionHeaderHeight = 0; 67 | [self.view addSubview:self.tableView]; 68 | [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { 69 | make.edges.equalTo(self.view); 70 | }]; 71 | 72 | 73 | } 74 | 75 | - (void)initTestData{ 76 | 77 | //init model data array 78 | self.modelArray = [[NSMutableArray alloc] init]; 79 | for (NSInteger i = 0; i < 3; i++) { 80 | InfoModel *model = [[InfoModel alloc] init]; 81 | model.titleStr = [NSString stringWithFormat:@"button%ld", (long)i]; 82 | model.testData = [NSString stringWithFormat:@"test data %ld", (long)i]; 83 | model.testNum = @(i); 84 | model.imageName = [NSString stringWithFormat:@"image_%ld",(long)i]; 85 | model.image = [UIImage imageNamed:model.imageName]; 86 | // model.imageUrl = [NSString stringWithFormat:@"https://github.com/mk2016/MKActionSheet/raw/MKActionSheet_dev/Resource/image_%ld@2x.png",(long)i]; 87 | model.imageUrl = @"http://taoqi-saas-public-prod.oss-cn-shenzhen.aliyuncs.com/saas/default/png/20191120/1574220880064--1016255442.png"; 88 | [self.modelArray addObject:model]; 89 | } 90 | 91 | //init dictionary data array 92 | self.dicArray = [[NSMutableArray alloc] init]; 93 | for (NSInteger i = 0; i < 4; i++) { 94 | 95 | NSDictionary *dic = @{@"titleStr" :[NSString stringWithFormat:@"button%ld", (long)i], 96 | @"testData" :[NSString stringWithFormat:@"test data %ld", (long)i], 97 | @"testNum" :@(i), 98 | @"imageName" :[NSString stringWithFormat:@"image_%ld",(long)i], 99 | @"image" :[UIImage imageNamed:[NSString stringWithFormat:@"image_%ld",(long)i]], 100 | @"imageUrl" : @"http://taoqi-saas-public-prod.oss-cn-shenzhen.aliyuncs.com/saas/default/png/20191120/1574220897629-324204560.png" 101 | // @"imageUrl" :[NSString stringWithFormat:@"https://github.com/mk2016/MKActionSheet/raw/MKActionSheet_dev/Resource/image_%ld@2x.png",(long)i], 102 | }; 103 | [self.dicArray addObject:dic]; 104 | } 105 | 106 | } 107 | 108 | - (void)initTableViewDatas{ 109 | 110 | [self.sectionTitleArray removeAllObjects]; 111 | [self.sectionTitleArray addObject:@"change bg image"]; 112 | [self.sectionTitleArray addObject:@"3 selectType type default UI"]; 113 | [self.sectionTitleArray addObject:@"3 selectType type have icon"]; 114 | [self.sectionTitleArray addObject:@"Portrait and Landscape config"]; 115 | [self.sectionTitleArray addObject:@"add button and reload"]; 116 | [self.sectionTitleArray addObject:@"custom titleView & UI"]; 117 | 118 | [self.datasArray removeAllObjects]; 119 | 120 | NSMutableArray *section0 = @[].mutableCopy; 121 | { 122 | MKCellModel *model = [[MKCellModel alloc] init]; 123 | model.title = @"change tableViewBackground image"; 124 | [section0 addObject:model]; 125 | [self.datasArray addObject:section0]; 126 | } 127 | 128 | NSMutableArray *section1 = @[].mutableCopy; 129 | { 130 | MKCellModel *model1 = [[MKCellModel alloc] init]; 131 | model1.title = @"selectType:_common"; 132 | model1.detail = @"default UI & long title"; 133 | [section1 addObject:model1]; 134 | 135 | MKCellModel *model2 = [[MKCellModel alloc] init]; 136 | model2.title = @"selectType:_selected"; 137 | model2.detail = @"default UI & title = nil"; 138 | [section1 addObject:model2]; 139 | 140 | MKCellModel *model3 = [[MKCellModel alloc] init]; 141 | model3.title = @"selectType:_multiselect"; 142 | model3.detail = @"title default left , default no cancel butto"; 143 | [section1 addObject:model3]; 144 | } 145 | [self.datasArray addObject:section1]; 146 | 147 | NSMutableArray *section2 = @[].mutableCopy; 148 | { 149 | MKCellModel *model1 = [[MKCellModel alloc] init]; 150 | model1.title = @"selectType:_common & icon"; 151 | model1.detail = @"imagetype: name & init with model Array"; 152 | [section2 addObject:model1]; 153 | 154 | MKCellModel *model2 = [[MKCellModel alloc] init]; 155 | model2.title = @"selectType:_selected & icon"; 156 | model2.detail = @"imagetype: image & init with dictionary Array"; 157 | [section2 addObject:model2]; 158 | 159 | MKCellModel *model3 = [[MKCellModel alloc] init]; 160 | model3.title = @"selectType:_multiselect & icon"; 161 | model3.detail = @"imagetype: url & init with dictionary Array"; 162 | [section2 addObject:model3]; 163 | } 164 | [self.datasArray addObject:section2]; 165 | 166 | NSMutableArray *section3 = @[].mutableCopy; 167 | { 168 | MKCellModel *model1 = [[MKCellModel alloc] init]; 169 | model1.title = @"max show buton count"; 170 | model1.detail = @"dufault : Portrait:5.6 , Landscape:4.6"; 171 | [section3 addObject:model1]; 172 | 173 | MKCellModel *model2 = [[MKCellModel alloc] init]; 174 | model2.title = @"custom Portrait & Landscape config"; 175 | model2.detail = @""; 176 | [section3 addObject:model2]; 177 | 178 | MKCellModel *model3 = [[MKCellModel alloc] init]; 179 | model3.title = @"custom Portrait & Landscape config & icon"; 180 | [section3 addObject:model3]; 181 | } 182 | [self.datasArray addObject:section3]; 183 | 184 | NSMutableArray *section4 = @[].mutableCopy; 185 | { 186 | MKCellModel *model1 = [[MKCellModel alloc] init]; 187 | model1.title = @"delay add button"; 188 | model1.detail = @"add button with title"; 189 | [section4 addObject:model1]; 190 | 191 | MKCellModel *model2 = [[MKCellModel alloc] init]; 192 | model2.title = @"add button by manual"; 193 | model2.detail = @"add button with objece"; 194 | [section4 addObject:model2]; 195 | 196 | MKCellModel *model3 = [[MKCellModel alloc] init]; 197 | model3.title = @"reload with array"; 198 | model3.detail = @"manual dismiss"; 199 | 200 | [section4 addObject:model3]; 201 | 202 | } 203 | [self.datasArray addObject:section4]; 204 | 205 | NSMutableArray *section5 = @[].mutableCopy; 206 | { 207 | MKCellModel *model1 = [[MKCellModel alloc] init]; 208 | model1.title = @"custom title View"; 209 | model1.detail = @"change title view"; 210 | [section5 addObject:model1]; 211 | 212 | MKCellModel *model2 = [[MKCellModel alloc] init]; 213 | model2.title = @"custom UI"; 214 | [section5 addObject:model2]; 215 | } 216 | [self.datasArray addObject:section5]; 217 | 218 | } 219 | 220 | - (void)delayTask:(float)time onTimeEnd:(void(^)(void))block { 221 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)); 222 | dispatch_after(popTime, dispatch_get_main_queue(), block); 223 | } 224 | 225 | #pragma mark - ***** UITableView delegate ****** 226 | 227 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 228 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 229 | if (indexPath.section >= self.datasArray.count) { 230 | return; 231 | } 232 | if (indexPath.row >= [self.datasArray[indexPath.section] count]) { 233 | return; 234 | } 235 | 236 | MKCellModel *model = self.datasArray[indexPath.section][indexPath.row]; 237 | NSString *cellTitle = model.title; 238 | MK_WEAK_SELF 239 | if ([cellTitle isEqualToString:@"selectType:_common"]) { 240 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"init with longgggggggg gggggggggggggggggggggggggggggggggggg title \n default UI" buttonTitleArray:@[@"button0", @"button1", @"button2"]]; 241 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 242 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button index: %ld" ,(long)buttonIndex]]; 243 | }]; 244 | } 245 | 246 | //带默认选中 按钮 样式 247 | else if ([cellTitle isEqualToString:@"selectType:_selected"]){ 248 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:nil buttonTitleArray:@[@"button0", @"button1", @"button2",@"button3"] selectType:MKActionSheetSelectType_selected]; 249 | sheet.selectedIndex = 2; 250 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 251 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button Index : %ld" ,(long)buttonIndex]]; 252 | }]; 253 | } 254 | 255 | //多选样式 无图片 256 | else if ([cellTitle isEqualToString:@"selectType:_multiselect"]) { 257 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@" titiititititiit " objArray:self.modelArray buttonTitleKey:@"titleStr" selectType:MKActionSheetSelectType_multiselect]; 258 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 259 | NSLog(@"array:%@",array); 260 | [weakSelf.view makeToast:[NSString stringWithFormat:@"array count : %ld ",(unsigned long)array.count]]; 261 | }]; 262 | } 263 | 264 | else if ([cellTitle isEqualToString:@"selectType:_common & icon"]) { 265 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:nil objArray:self.modelArray buttonTitleKey:@"titleStr" imageKey:@"imageName" imageValueType:MKActionSheetButtonImageValueType_name]; 266 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 267 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button index: %ld" ,(long)buttonIndex]]; 268 | }]; 269 | } 270 | 271 | else if ([cellTitle isEqualToString:@"selectType:_selected & icon"]) { 272 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:nil objArray:self.dicArray buttonTitleKey:@"titleStr" imageKey:@"image" imageValueType:MKActionSheetButtonImageValueType_image selectType:MKActionSheetSelectType_selected]; 273 | sheet.selectedIndex = 1; 274 | sheet.needCancelButton = YES; 275 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 276 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button index: %ld" ,(long)buttonIndex]]; 277 | }]; 278 | } 279 | 280 | else if ([cellTitle isEqualToString:@"selectType:_multiselect & icon"]) { 281 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"load url image" 282 | objArray:self.dicArray 283 | buttonTitleKey:@"titleStr" 284 | imageKey:@"imageUrl" 285 | imageValueType:MKActionSheetButtonImageValueType_url 286 | selectType:MKActionSheetSelectType_multiselect]; 287 | sheet.loadUrlImageblock = ^(MKActionSheet *actionSheet, UIButton *button, NSInteger index, NSURL *imageUrl) { 288 | [button sd_setImageWithURL:imageUrl forState:UIControlStateNormal]; 289 | }; 290 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 291 | NSLog(@"array:%@",array); 292 | [weakSelf.view makeToast:[NSString stringWithFormat:@"array count : %ld ",(unsigned long)array.count]]; 293 | }]; 294 | } 295 | 296 | else if ([cellTitle isEqualToString:@"max show buton count"]){ 297 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:nil buttonTitleArray:@[@"button0", @"button1", @"button2",@"button3",@"button4",@"button5",@"button6"] selectType:MKActionSheetSelectType_selected]; 298 | sheet.selectedIndex = 2; 299 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 300 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button Index : %ld" ,(long)buttonIndex]]; 301 | }]; 302 | } 303 | 304 | else if ([cellTitle isEqualToString:@"custom Portrait & Landscape config"]){ 305 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"custom config" objArray:self.dicArray buttonTitleKey:@"titleStr" selectType:MKActionSheetSelectType_multiselect]; 306 | 307 | MKASOrientationConfig *portraitConfig = [[MKASOrientationConfig alloc] init]; 308 | portraitConfig.titleAlignment = NSTextAlignmentCenter; 309 | portraitConfig.buttonTitleAlignment = MKActionSheetButtonTitleAlignment_left; 310 | portraitConfig.buttonHeight = 48.0f; 311 | portraitConfig.maxShowButtonCount = 4.6; 312 | 313 | MKASOrientationConfig *landscapeConfig = [[MKASOrientationConfig alloc] init]; 314 | landscapeConfig.titleAlignment = NSTextAlignmentRight; 315 | landscapeConfig.buttonTitleAlignment = MKActionSheetButtonTitleAlignment_right; 316 | landscapeConfig.buttonHeight = 36.0f; 317 | landscapeConfig.maxShowButtonCount = 3.6; 318 | [sheet setPortraitConfig:portraitConfig]; 319 | [sheet setLandscapeConfig:landscapeConfig]; 320 | 321 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 322 | NSLog(@"array:%@",array); 323 | [weakSelf.view makeToast:[NSString stringWithFormat:@"array count : %ld ",(unsigned long)array.count]]; 324 | }]; 325 | } 326 | 327 | else if ([cellTitle isEqualToString:@"custom Portrait & Landscape config & icon"]){ 328 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"custom config" objArray:self.dicArray buttonTitleKey:@"titleStr" imageKey:@"imageUrl" imageValueType:MKActionSheetButtonImageValueType_url selectType:MKActionSheetSelectType_multiselect]; 329 | 330 | MKASOrientationConfig *portraitConfig = [[MKASOrientationConfig alloc] init]; 331 | portraitConfig.titleAlignment = NSTextAlignmentRight; 332 | portraitConfig.buttonTitleAlignment = MKActionSheetButtonTitleAlignment_right; 333 | portraitConfig.buttonHeight = 48.0f; 334 | portraitConfig.maxShowButtonCount = 4.6; 335 | 336 | MKASOrientationConfig *landscapeConfig = [[MKASOrientationConfig alloc] init]; 337 | landscapeConfig.titleAlignment = NSTextAlignmentLeft; 338 | landscapeConfig.buttonTitleAlignment = MKActionSheetButtonTitleAlignment_left; 339 | landscapeConfig.buttonHeight = 36.0f; 340 | landscapeConfig.maxShowButtonCount = 3.6; 341 | [sheet setPortraitConfig:portraitConfig]; 342 | [sheet setLandscapeConfig:landscapeConfig]; 343 | 344 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 345 | NSLog(@"array:%@",array); 346 | [weakSelf.view makeToast:[NSString stringWithFormat:@"array count : %ld ",(unsigned long)array.count]]; 347 | }]; 348 | } 349 | 350 | else if ([cellTitle isEqualToString:@"delay add button"]){ 351 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"title" buttonTitleArray:@[@"button0", @"button1"]]; 352 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 353 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button index: %ld" ,(long)buttonIndex]]; 354 | }]; 355 | 356 | [self delayTask:0.1 onTimeEnd:^{ 357 | [sheet addButtonWithButtonTitle:[NSString stringWithFormat:@"add delay 0.1 second"]]; 358 | }]; 359 | [self delayTask:0.5 onTimeEnd:^{ 360 | [sheet addButtonWithButtonTitle:[NSString stringWithFormat:@"add delay 0.5 second"]]; 361 | }]; 362 | [self delayTask:1 onTimeEnd:^{ 363 | [sheet addButtonWithButtonTitle:[NSString stringWithFormat:@"add delay 1 second"]]; 364 | }]; 365 | } 366 | 367 | else if ([cellTitle isEqualToString:@"add button by manual"]){ 368 | InfoModel *model1 = [[InfoModel alloc] init]; 369 | model1.titleStr = [NSString stringWithFormat:@"add button 3"]; 370 | model1.testData = [NSString stringWithFormat:@"test data"]; 371 | model1.testNum = @(3); 372 | model1.imageName = [NSString stringWithFormat:@"image_3"]; 373 | model1.image = [UIImage imageNamed:model1.imageName]; 374 | model1.imageUrl = [NSString stringWithFormat:@"http://taoqi-saas-public-prod.oss-cn-shenzhen.aliyuncs.com/saas/default/png/20191120/1574220909014--1291393306.png"]; 375 | 376 | InfoModel *model2 = [[InfoModel alloc] init]; 377 | model2.titleStr = [NSString stringWithFormat:@"add button 4"]; 378 | model2.testData = [NSString stringWithFormat:@"test data"]; 379 | model2.testNum = @(3); 380 | model2.imageName = [NSString stringWithFormat:@"image_4"]; 381 | model2.image = [UIImage imageNamed:model2.imageName]; 382 | model2.imageUrl = [NSString stringWithFormat:@"http://taoqi-saas-public-prod.oss-cn-shenzhen.aliyuncs.com/saas/default/png/20191120/1574220920214--437715014.png"]; 383 | 384 | 385 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@" titiititititiit " 386 | objArray:self.modelArray 387 | buttonTitleKey:@"titleStr" 388 | imageKey:@"imageUrl" 389 | imageValueType:MKActionSheetButtonImageValueType_url 390 | selectType:MKActionSheetSelectType_multiselect]; 391 | 392 | [sheet addButtonWithObj:model1]; 393 | sheet.loadUrlImageblock = ^(MKActionSheet *actionSheet, UIButton *button, NSInteger index, NSURL *imageUrl) { 394 | [button sd_setImageWithURL:imageUrl forState:UIControlStateNormal]; 395 | }; 396 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 397 | NSLog(@"actionSheet:%@",actionSheet); 398 | NSLog(@"array:%@",array); 399 | [weakSelf.view makeToast:[NSString stringWithFormat:@"array count : %ld ",(unsigned long)array.count]]; 400 | 401 | }]; 402 | [sheet addButtonWithObj:model2]; 403 | 404 | } 405 | 406 | 407 | else if ([cellTitle isEqualToString:@"reload with array"]){ 408 | NSMutableArray *titlesAry = [[NSMutableArray alloc] initWithObjects:@"add 1", @"add 2", @"add 3", nil]; 409 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"manual dismiss" buttonTitleArray:titlesAry]; 410 | sheet.manualDismiss = YES; 411 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 412 | [weakSelf.view makeToast:[NSString stringWithFormat:@"button Index : %ld" ,(long)buttonIndex]]; 413 | if (buttonIndex < 3) { 414 | [titlesAry addObject:@"new button"]; 415 | [sheet reloadWithTitleArray:titlesAry]; 416 | }else{ 417 | [sheet dismiss]; 418 | } 419 | }]; 420 | } 421 | 422 | 423 | 424 | 425 | else if ([cellTitle isEqualToString:@"custom title View"]){ 426 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:nil buttonTitleArray:@[@"button1", @"button2",@"button3",@"button4"]]; 427 | self.customTitleSheet = sheet; 428 | sheet.manualDismiss = YES; 429 | UIView *titleView = [[UIView alloc] init]; 430 | titleView.backgroundColor = [UIColor redColor]; 431 | 432 | UILabel *labTitle = [[UILabel alloc] init]; 433 | labTitle.text = @"自定义titleView"; 434 | labTitle.textColor = [UIColor greenColor]; 435 | labTitle.font = [UIFont boldSystemFontOfSize:17]; 436 | labTitle.textAlignment = NSTextAlignmentCenter; 437 | [titleView addSubview:labTitle]; 438 | 439 | UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; 440 | [btn setTitle:@"title button" forState:UIControlStateNormal]; 441 | btn.backgroundColor = [UIColor greenColor]; 442 | [btn addTarget:self action:@selector(btnTitleOnclick:) forControlEvents:UIControlEventTouchUpInside]; 443 | [titleView addSubview:btn]; 444 | 445 | [labTitle mas_makeConstraints:^(MASConstraintMaker *make) { 446 | make.left.right.top.equalTo(titleView); 447 | make.centerX.equalTo(titleView); 448 | make.bottom.equalTo(btn.mas_top); 449 | }]; 450 | 451 | [btn mas_makeConstraints:^(MASConstraintMaker *make) { 452 | make.centerX.equalTo(titleView); 453 | make.width.mas_equalTo(200); 454 | make.height.mas_equalTo(40); 455 | make.top.equalTo(labTitle.mas_bottom); 456 | }]; 457 | 458 | [sheet setCustomTitleView:titleView makeConstraints:^(MASConstraintMaker *make, UIView *superview) { 459 | make.left.right.top.equalTo(superview); 460 | make.bottom.equalTo(superview); 461 | make.height.mas_equalTo(100); 462 | }]; 463 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 464 | UIView *view = [[UIView alloc] init]; 465 | view.backgroundColor = [UIColor blueColor]; 466 | [sheet setCustomTitleView:view makeConstraints:^(MASConstraintMaker *make, UIView *superview) { 467 | make.edges.equalTo(superview); 468 | make.height.mas_equalTo(120); 469 | }]; 470 | }]; 471 | 472 | } 473 | 474 | //自定义UI 475 | else if ([cellTitle isEqualToString:@"custom UI"]){ 476 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"custom UI" buttonTitleArray:@[@"button1", @"button2",@"button3",@"button4", @"button5",@"button6",@"button7"]]; 477 | sheet.titleColor = [UIColor greenColor]; 478 | sheet.titleFont = [UIFont boldSystemFontOfSize:24]; 479 | sheet.buttonTitleColor = [UIColor redColor]; 480 | sheet.buttonTitleFont = [UIFont boldSystemFontOfSize:14]; 481 | sheet.buttonOpacity = 1; 482 | sheet.destructiveButtonTitleColor = [UIColor grayColor]; 483 | sheet.destructiveButtonIndex = 2; 484 | sheet.cancelTitle = @"关闭"; 485 | sheet.animationDuration = 0.2f; 486 | sheet.blurOpacity = 0.7f; 487 | sheet.blackgroundOpacity = 0.6f; 488 | sheet.needCancelButton = YES; 489 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 490 | NSLog(@"buttonIndex:%ld",(long)buttonIndex); 491 | }]; 492 | } 493 | 494 | else if ([cellTitle isEqualToString:@"change tableViewBackground image"]) { 495 | if (self.tableView.backgroundView) { 496 | self.tableView.backgroundView = nil; 497 | }else{ 498 | self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"img_bg"]]; 499 | } 500 | } 501 | } 502 | 503 | - (UIImage *)getDefaultIcon{ 504 | return [UIImage imageNamed:@"image_5"]; 505 | } 506 | 507 | - (void)btnTitleOnclick:(UIButton *)sender{ 508 | [self.view makeToast:@"custom title button onclicked"]; 509 | [self.customTitleSheet dismiss]; 510 | 511 | // if (self.customTitleSheet.delegate && [self.customTitleSheet.delegate respondsToSelector:@selector(actionSheet:didClickButtonAtIndex:)]) { 512 | // [self.customTitleSheet.delegate actionSheet:self.customTitleSheet didClickButtonAtIndex:0]; 513 | // } 514 | // if (self.customTitleSheet.block) { 515 | // self.customTitleSheet.block(self.customTitleSheet, 0); 516 | // } 517 | } 518 | 519 | 520 | #pragma mark - ***** UITableView delegate ****** 521 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 522 | static NSString *cellIdentifier = @"cell"; 523 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 524 | if (!cell) { 525 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; 526 | cell.backgroundColor = [UIColor clearColor]; 527 | cell.detailTextLabel.numberOfLines = 0; 528 | } 529 | if (indexPath.section < self.datasArray.count) { 530 | if (indexPath.row < [self.datasArray[indexPath.section] count]) { 531 | MKCellModel *model = self.datasArray[indexPath.section][indexPath.row]; 532 | cell.textLabel.text = model.title; 533 | cell.detailTextLabel.text = model.detail; 534 | } 535 | } 536 | return cell; 537 | } 538 | 539 | 540 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 541 | if (section < self.datasArray.count) { 542 | return [self.datasArray[section] count]; 543 | } 544 | return 0; 545 | } 546 | 547 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 548 | return self.datasArray.count; 549 | } 550 | 551 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 552 | return 60;; 553 | } 554 | 555 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 556 | return 30; 557 | } 558 | 559 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ 560 | UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, MK_SCREEN_WIDTH, 30)]; 561 | view.backgroundColor = MK_COLOR_RGBA(255, 255, 255, 0.3); 562 | UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, MK_SCREEN_WIDTH-32, 30)]; 563 | lab.textColor = [UIColor blackColor]; 564 | lab.font = [UIFont systemFontOfSize:14]; 565 | if (section < self.sectionTitleArray.count) { 566 | lab.text = self.sectionTitleArray[section]; 567 | } 568 | [view addSubview:lab]; 569 | return view; 570 | } 571 | 572 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ 573 | return 0.1; 574 | } 575 | 576 | - (NSMutableArray *)sectionTitleArray{ 577 | if (!_sectionTitleArray) { 578 | _sectionTitleArray = @[].mutableCopy; 579 | } 580 | return _sectionTitleArray; 581 | } 582 | 583 | - (NSMutableArray *)datasArray{ 584 | if (!_datasArray) { 585 | _datasArray = @[].mutableCopy; 586 | } 587 | return _datasArray; 588 | } 589 | - (void)didReceiveMemoryWarning { 590 | [super didReceiveMemoryWarning]; 591 | // Dispose of any resources that can be recreated. 592 | } 593 | 594 | @end 595 | 596 | 597 | 598 | @implementation MKCellModel 599 | @end 600 | -------------------------------------------------------------------------------- /MKActionSheetDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MKActionSheet 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. 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 | -------------------------------------------------------------------------------- /MKActionSheetTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MKActionSheetTests/MKActionSheetTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKActionSheetTests.m 3 | // MKActionSheetTests 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MKActionSheetTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation MKActionSheetTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /MKActionSheetUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MKActionSheetUITests/MKActionSheetUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // MKActionSheetUITests.m 3 | // MKActionSheetUITests 4 | // 5 | // Created by xiaomk on 16/6/1. 6 | // Copyright © 2016年 MK. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MKActionSheetUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation MKActionSheetUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '8.0' 3 | inhibit_all_warnings! 4 | 5 | target 'MKActionSheet' do 6 | pod 'Masonry', '~> 1.1.0' 7 | pod 'SDWebImage', '~> 5.5.2' 8 | end 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MKActionSheet 2 | 3 | [![Travis](https://img.shields.io/travis/mk2016/MKActionSheet.svg?style=flat)](https://travis-ci.org/mk2016/MKActionSheet) 4 | [![CocoaPods Version](https://img.shields.io/cocoapods/v/MKActionSheet.svg)](http://cocoadocs.org/docsets/MKActionSheet) 5 | [![CocoaPods](https://img.shields.io/dub/l/vibe-d.svg)](https://raw.githubusercontent.com/mk2016/MKActionSheet/master/LICENSE) 6 | [![CocoaPods](https://img.shields.io/cocoapods/p/MKActionSheet.svg)](http://cocoadocs.org/docsets/MKActionSheet) 7 | [![MKDev](https://img.shields.io/badge/blog-MK-brightgreen.svg)](https://mk2016.github.io/) 8 | 9 | ## 多样式 ActionSheet 10 | * 高斯模糊效果 11 | * 支持横屏 12 | * 支持无标题、无取消按钮样式 13 | * 支持带默认选中模式 14 | * 支持多选模式 15 | * 支持带 icon 图片样式 16 | * 支持多按钮,可设置最大显示数量(支持小数),超过最大数量滚动 17 | * 支持 Model 或 NSDictionary 数组初始化 18 | * 支持 block 19 | * 支持动态添加 button 20 | * 支持动态 修改 titleView 21 | 22 | #### 先上效果图 23 | ![image](https://github.com/mk2016/MKActionSheet/raw/master/Screenshots/gif2.gif) 24 | 25 | 26 | ## 使用 27 | * cocoapods 28 | pod 'MKActionSheet', '~> 2.1.0' 29 | 30 | * Manually (手动导入) 31 | 只需将 MKActionSheet 文件添加到项目中即可 32 | 33 | * 依赖 34 | Masonry ~> 1.1.0 35 | SDWebImage ~> 4.4.5 36 | 37 | ## 用法 详细用法参见demo 38 | ##### 1.4.0 版本之后 化烦为简 去除 delegate 用法, 适配到iOS8。  需要delegate或者想支持iOS7可以使用V1.3.2版本。 39 | ##### 2.0.1 版本重构了代码,后支持横屏 和之前版本有较大差异,旧版升级上来的请检查是否需要修改你的代码 40 | ##### 有使用者反馈,status bar原来白色会变为黑色,这是由于新建了 window 导致的。 可以将 currentVC 设置为当前 viewController 41 | 42 | 43 | ``` 44 | //单选 block 45 | - (void)showWithBlock:(MKActionSheetBlock)block; 46 | //多选 block 47 | - (void)showWithMultiselectBlock:(MKActionSheetMultiselectBlock)multiselectblock; 48 | ``` 49 | 50 | ##### 枚举 51 | * selectType 52 | ``` 53 | typedef NS_ENUM(NSInteger, MKActionSheetSelectType) { 54 | MKActionSheetSelectType_common = 1, //default 55 | MKActionSheetSelectType_selected, //have a selected button 56 | MKActionSheetSelectType_multiselect, //multiselect 57 | }; 58 | ``` 59 | * button title Alignment 60 | ``` 61 | typedef NS_ENUM(NSInteger, MKActionSheetButtonTitleAlignment) { 62 | MKActionSheetButtonTitleAlignment_center = 1, //default 63 | MKActionSheetButtonTitleAlignment_left, 64 | MKActionSheetButtonTitleAlignment_right, 65 | }; 66 | ``` 67 | 68 | * button image value type 69 | ``` 70 | typedef NS_ENUM(NSInteger, MKActionSheetButtonImageValueType) { 71 | MKActionSheetButtonImageValueType_none = 1, //default 72 | MKActionSheetButtonImageValueType_image, 73 | MKActionSheetButtonImageValueType_name, 74 | MKActionSheetButtonImageValueType_url, 75 | }; 76 | ``` 77 | * 普通样式,多参数初始化 78 | 79 | ``` 80 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"title" buttonTitleArray:@[@"button0", @"button1", @"button2"]]; 81 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 82 | }]; 83 | ``` 84 | 85 | * 对象数组初始化,支持 model 和 NSDictionary 数组。titleKey是对象中用来显示按钮title对应的字段。 86 | 87 | ``` 88 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@" titiititititiit " objArray:self.modelArray buttonTitleKey:@"titleStr" selectType:MKActionSheetSelectType_multiselect]; 89 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 90 | NSLog(@"array:%@",array); 91 | }]; 92 | ``` 93 | 94 | * 带icon图标的样式 95 | 96 | ``` 97 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:nil objArray:self.modelArray buttonTitleKey:@"titleStr" imageKey:@"imageName" imageValueType:MKActionSheetButtonImageValueType_name]; 98 | [sheet showWithBlock:^(MKActionSheet *actionSheet, NSInteger buttonIndex) { 99 | }]; 100 | 101 | 102 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:@"load url image" objArray:self.dicArray buttonTitleKey:@"titleStr" imageKey:@"imageUrl" imageValueType:MKActionSheetButtonImageValueType_url selectType:MKActionSheetSelectType_multiselect]; 103 | [sheet showWithMultiselectBlock:^(MKActionSheet *actionSheet, NSArray *array) { 104 | NSLog(@"array:%@",array); 105 | [weakSelf.view makeToast:[NSString stringWithFormat:@"array count : %ld ",(unsigned long)array.count]]; 106 | }]; 107 | ``` 108 | 109 | 110 | 111 | #### 可以根据自己的需求定制UI 112 | ``` 113 | /** custom UI */ 114 | @property (nonatomic, assign) CGFloat windowLevel; /*!< default: UIWindowLevelStatusBar - 1 */ 115 | @property (nonatomic, weak) UIViewController *currentVC; /*!< current viewController, for statusBar keep the same style */ 116 | @property (nonatomic, assign) BOOL enabledForBgTap; /*!< default: YES */ 117 | @property (nonatomic, assign) BOOL manualDismiss; /** [default: NO]. if set 'YES', you need calling the method of 'dismiss' to hide actionSheet by manual */ 118 | 119 | /** action sheet */ 120 | @property (nonatomic, assign) CGFloat animationDuration; /*!< 动画化时间 [default: 0.3f] */ 121 | @property (nonatomic, assign) CGFloat blurOpacity; /*!< 毛玻璃透明度 [default: 0.3f] */ 122 | @property (nonatomic, assign) CGFloat blackgroundOpacity; /*!< 灰色背景透明度 [default: 0.3f] */ 123 | 124 | //title 125 | @property (nonatomic, strong) UIColor *titleColor; /*!< 标题颜色 [default: RGBA(100.0f, 100.0f, 100.0f, 1.0f)]*/ 126 | @property (nonatomic, strong) UIFont *titleFont; /*!< 标题字体 [default: sys 14] */ 127 | @property (nonatomic, assign) CGFloat titleMargin; /*!< title side spacee [default: 20] */ 128 | 129 | //button 130 | @property (nonatomic, strong) UIColor *buttonTitleColor; /*!< 按钮 titile 颜色 [default:RBGA(51.0f, 51.0f, 51.0f, 1.0f)] */ 131 | @property (nonatomic, strong) UIFont *buttonTitleFont; /*!< 按钮 字体 [default: sys 18] */ 132 | @property (nonatomic, assign) CGFloat buttonOpacity; /*!< 按钮透明度 [default: 0.6] */ 133 | @property (nonatomic, assign) CGFloat buttonImageRightSpace; /*!< 带图片样式 图片右边离 title 的距离 [default: 12.f] */ 134 | 135 | //destructive Button 136 | @property (nonatomic, assign) NSInteger destructiveButtonIndex; /*!< [default:-1]*/ 137 | @property (nonatomic, strong) UIColor *destructiveButtonTitleColor; /*!< [default:RBGA(250.0f, 10.0f, 10.0f, 1.0f)]*/ 138 | 139 | //cancel Title 140 | @property (nonatomic, assign) BOOL needCancelButton; /*!< 是否需要取消按钮 */ 141 | @property (nonatomic, copy) NSString *cancelTitle; /*!< cancel button title [dafault:取消] */ 142 | 143 | 144 | //MKActionSheetSelectType_selected 145 | @property (nonatomic, assign) NSInteger selectedIndex; /*!< selected button index */ 146 | @property (nonatomic, copy) NSString *selectedBtnImageName; /*!< image name for selected button */ 147 | 148 | //MKActionSheetSelectType_multiselect 149 | @property (nonatomic, copy) NSString *selectBtnImageNameNormal; /*!< image name for select button normal state */ 150 | @property (nonatomic, copy) NSString *selectBtnImageNameSelected; /*!< image name for select button selected state )*/ 151 | @property (nonatomic, strong) NSString *multiselectConfirmButtonTitle; /*!< confirm button title */ 152 | @property (nonatomic, strong) UIColor *multiselectConfirmButtonTitleColor; /*!< confirm button title color */ 153 | @property (nonatomic, strong) UIImage *placeholderImage; 154 | ``` 155 | 156 | 157 | 建议可以根据需求自定义几种样式的类调用方法,在项目中直接使用。例: 158 | 159 | ``` 160 | + (void)sheetWithTitle:(NSString *)title buttonTitleArray:(NSArray *)buttonTitleArray destructiveButtonIndex:(NSInteger)destructiveButtonIndex block:(MKActionSheetBlock)block{ 161 | MKActionSheet *sheet = [[MKActionSheet alloc] initWithTitle:title buttonTitleArray:buttonTitleArray]; 162 | sheet.needCancelButton = YES; 163 | sheet.buttonTitleFont = [UIFont systemFontOfSize:17]; 164 | sheet.buttonTitleColor = [UIColor redColor]; 165 | sheet.buttonOpacity = 1; 166 | sheet.buttonHeight = 40.0f; 167 | sheet.destructiveButtonTitleColor = [UIColor grayColor]; 168 | sheet.animationDuration = 0.2f; 169 | sheet.blackgroundOpacity = 0.0f; 170 | sheet.blurOpacity = 0.7f; 171 | sheet.tag = 200; 172 | [sheet showWithBlock:block]; 173 | } 174 | ``` 175 | 176 | 177 | ## 版本记录 178 | ### V3.0.1 179 | * 'SDWebImage' 版本跟新比较频繁,移除 'SDWebImage' 依赖 180 | * 新增 loadUrlImageblock 181 | 182 | ### V2.1.1 183 | * 'SDWebImage', '~> 5.0.6' 184 | ### V2.1.0 185 | * support iPhoneX 、XS、XMAX 186 | * SDWebImage ~> 4.4.5 187 | ### V2.0.4 188 | * 升级依赖 189 | * Masonry ~> 1.1.0 190 | * SDWebImage ~> 4.1.2 191 | ### V2.0.3 192 | * fix:高度每个按钮缺少1个像素 193 | * 升级依赖 SDWebImage ~> 4.1.0 194 | ### V2.0.2 195 | * 依赖 SDWebImage 版本改为当前最新的V4.0.0 196 | ### V2.0.1 197 | * 重构,支持横屏,动态添加 button 198 | * PS:此版本有重大改动,旧版升级上来的,请检查代码 199 | ### V1.4.1 200 | * fix: blurOpacity 设置毛玻璃透明度无效的bug 201 | ### V1.4.0 202 | * 去除 delegate 模式 203 | * 适配到iOS8 204 | * 模态改为使用 UIVisualEffectView,优化样式。 205 | 206 | ### V1.3.0 207 | * 新增属性 208 | ``` 209 | @property (nonatomic, assign) BOOL enableBgTap; /*!< 蒙版是否可以点击 收起*/ 210 | @property (nonatomic, assign) BOOL needNewWindow; /*!< 是否新建window 默认为 NO */ 211 | ``` 212 | * 有使用者反馈,status bar原来白色会变为黑色,这是由于新建了 window 导致的。 213 | * 现默认使用不新建window的模式, 214 | * 但如果您的项目使用了多个window,当顶部window不是keywindow时,sheetView会被顶部window遮住。 215 | * 此时建议 将 needNewWindow 设置为 YES; 并在项目info.plist 中 新增 “View controller-based status bar appearance” 设置为 NO。 216 | * 这样也可以让 status bar 不变色 217 | 218 | 感谢 [@leshengping](https://github.com/leshengping) 的建议和反馈 219 | 220 | ### V1.2.0 221 | * 默认最大显示按钮个数为5.6, 既 maxShowButtonCount 默认为 5.6; 222 | * 添加自定义属性 223 | 224 | ``` 225 | @property (nonatomic, assign,getter=isShowSeparator) BOOL showSeparator; /*!< 是否显示分割线 [default: YES]*/ 226 | @property (nonatomic, assign) CGFloat separatorLeftMargin; /*!< 分割线离左边的边距 [default:0] */ 227 | @property (nonatomic, strong) UIColor *multiselectConfirmButtonTitleColor; /*!< 多选 确定按钮 颜色 */ 228 | ``` 229 | * 添加 界面展示前后的 delegate 和 block 230 | 231 | ``` 232 | /** before and after animation delegate */ 233 | - (void)willPresentActionSheet:(MKActionSheet *)actionSheet; /*!< before animation and showing view */ 234 | - (void)didPresentActionSheet:(MKActionSheet *)actionSheet; /*!< after animation */ 235 | - (void)actionSheet:(MKActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex; /*!< before animation and hiding view */ 236 | - (void)actionSheet:(MKActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex; /*!< after animation */ 237 | - (void)actionSheet:(MKActionSheet *)actionSheet willDismissWithSelectArray:(NSArray *)selectArray; /*!< before animation and hiding view */ 238 | - (void)actionSheet:(MKActionSheet *)actionSheet didDismissWithSelectArray:(NSArray *)selectArray; /*!< after animation */ 239 | /** before and after animation block */ 240 | @property (nonatomic, copy) MKActionSheetWillPresentBlock willPresentBlock; 241 | @property (nonatomic, copy) MKActionSheetDidPresentBlock didPresentBlock; 242 | @property (nonatomic, copy) MKActionSheetWillDismissBlock willDismissBlock; 243 | @property (nonatomic, copy) MKActionSheetDidDismissBlock didDismissBlock; 244 | @property (nonatomic, copy) MKActionSheetWillDismissMultiselectBlock willDismissMultiselectBlock; 245 | @property (nonatomic, copy) MKActionSheetDidDismissMultiselectBlock didDismissMultiselectBlock; 246 | ``` 247 | 248 | ### V1.1.1 249 | * 高斯模糊效果 250 | * 支持无标题、无取消按钮样式 251 | * 支持带默认选中模式 252 | * 支持多选模式 253 | * 支持带 icon 图片样式 254 | * 支持多按钮,可设置最大显示数量(支持小数),超过最大数量,以tableView模式显示 255 | * 支持 Model 或 NSDictionary 数组初始化 256 | * 支持 block 和 delegate 257 | * 添加 cocoapod 258 | 259 | 260 | ### V1.0.3 261 | * MKActionSheet 基础功能,高斯模糊效果。 262 | * 支持无title、无取消按钮样式。 263 | * 支持自定义UI样式 264 | * 支持 block 和 delegate 265 | 266 | 267 | MIT License 268 | ----------- 269 | ``` 270 | Copyright (c) 2016 MK Xiao 271 | 272 | Permission is hereby granted, free of charge, to any person obtaining a copy 273 | of this software and associated documentation files (the "Software"), to deal 274 | in the Software without restriction, including without limitation the rights 275 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 276 | copies of the Software, and to permit persons to whom the Software is 277 | furnished to do so, subject to the following conditions: 278 | 279 | The above copyright notice and this permission notice shall be included in all 280 | copies or substantial portions of the Software. 281 | 282 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 283 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 284 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 285 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 286 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 287 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 288 | SOFTWARE. 289 | ``` 290 | -------------------------------------------------------------------------------- /Resource/image_0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/image_0@2x.png -------------------------------------------------------------------------------- /Resource/image_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/image_1@2x.png -------------------------------------------------------------------------------- /Resource/image_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/image_2@2x.png -------------------------------------------------------------------------------- /Resource/image_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/image_3@2x.png -------------------------------------------------------------------------------- /Resource/image_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/image_4@2x.png -------------------------------------------------------------------------------- /Resource/image_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/image_5@2x.png -------------------------------------------------------------------------------- /Resource/img_separator@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Resource/img_separator@3x.png -------------------------------------------------------------------------------- /Screenshots/31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/31.png -------------------------------------------------------------------------------- /Screenshots/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/32.png -------------------------------------------------------------------------------- /Screenshots/33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/33.png -------------------------------------------------------------------------------- /Screenshots/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/34.png -------------------------------------------------------------------------------- /Screenshots/35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/35.png -------------------------------------------------------------------------------- /Screenshots/36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/36.png -------------------------------------------------------------------------------- /Screenshots/37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/37.png -------------------------------------------------------------------------------- /Screenshots/38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/38.png -------------------------------------------------------------------------------- /Screenshots/39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/39.png -------------------------------------------------------------------------------- /Screenshots/gif2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mk2016/MKActionSheet/7626df6e1bde1639b7fa36ae475da02b25f8ebab/Screenshots/gif2.gif -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CMD_PATH=`dirname $0` 3 | cd $CMD_PATH 4 | pod install 5 | open MKActionSheet.xcworkspace 6 | exit 0 7 | --------------------------------------------------------------------------------