├── .gitignore ├── LICENSE ├── README.md ├── SYNavigationDropdownMenu.podspec ├── SYNavigationDropdownMenu.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SYNavigationDropdownMenu ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Arrow.imageset │ │ ├── Arrow.pdf │ │ └── Contents.json │ ├── Brand Assets.launchimage │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SYNavigationDropdownMenu │ ├── SYNavigationDropdownMenu.h │ └── SYNavigationDropdownMenu.m ├── ViewController.h ├── ViewController.m └── main.m └── Screenshot └── ScreenShot.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### OSX ### 4 | .DS_Store 5 | .AppleDouble 6 | .LSOverride 7 | 8 | # Icon must end with two \r 9 | Icon 10 | 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear on external disk 16 | .Spotlight-V100 17 | .Trashes 18 | 19 | # Directories potentially created on remote AFP share 20 | .AppleDB 21 | .AppleDesktop 22 | Network Trash Folder 23 | Temporary Items 24 | .apdisk 25 | 26 | ### Xcode ### 27 | build/ 28 | *.pbxuser 29 | !default.pbxuser 30 | *.mode1v3 31 | !default.mode1v3 32 | *.mode2v3 33 | !default.mode2v3 34 | *.perspectivev3 35 | !default.perspectivev3 36 | xcuserdata 37 | *.xccheckout 38 | *.moved-aside 39 | DerivedData 40 | *.xcuserstate 41 | 42 | 43 | ### Objective-C ### 44 | # Xcode 45 | # 46 | build/ 47 | *.pbxuser 48 | !default.pbxuser 49 | *.mode1v3 50 | !default.mode1v3 51 | *.mode2v3 52 | !default.mode2v3 53 | *.perspectivev3 54 | !default.perspectivev3 55 | xcuserdata 56 | *.xccheckout 57 | *.moved-aside 58 | DerivedData 59 | *.hmap 60 | *.ipa 61 | *.xcuserstate 62 | 63 | # CocoaPods 64 | # 65 | # We recommend against adding the Pods directory to your .gitignore. However 66 | # you should judge for yourself, the pros and cons are mentioned at: 67 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 68 | # 69 | Pods/ 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sunnyyoung 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SYNavigationDropdownMenu 2 | 3 | A lightweight dropdown menu drops underneath navigation bar. 4 | 5 | ## Screen Shot 6 | 7 | ![](https://raw.githubusercontent.com/Sunnyyoung/SYNavigationDropdownMenu/master/Screenshot/ScreenShot.gif) 8 | 9 | ## Requirments 10 | 11 | 1. iOS 7.0 and above. 12 | 13 | ## Installation 14 | 15 | Recommended way 16 | 17 | 1. Edit your `Podfile`, add one line code `pod 'SYNavigationDropdownMenu` 18 | 2. Run 'pod update' 19 | 3. `#import ` 20 | 21 | Manually way 22 | 23 | 1. Dragging `SYNavigationDropdownMenu.h` and `SYNavigationDropdownMenu.m` to your project 24 | 2. `#import "SYNavigationDropdownMenu.h"` 25 | 26 | ## Quickstart 27 | 28 | ### Setup the NavigationDropdownMenu 29 | 30 | ```objc 31 | SYNavigationDropdownMenu *menu = [[SYNavigationDropdownMenu alloc] initWithNavigationController:self.navigationController]; 32 | menu.dataSource = self; 33 | menu.delegate = self; 34 | self.navigationItem.titleView = menu; 35 | ``` 36 | 37 | ### Configure the NavigationDropdownMenu 38 | 39 | #### Required 40 | 41 | **Return the title array for the NavigationDropdownMenu:** 42 | 43 | `- (NSArray *)titleArrayForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` 44 | 45 | **The delegate action when select a cell:** 46 | 47 | `- (void)navigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu didSelectTitleAtIndex:(NSUInteger)index;` 48 | 49 | #### Optional 50 | 51 | **The font of the title text label:** 52 | 53 | `- (UIFont *)titleFontForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is [UIFont systemFontSize:17.0]** 54 | 55 | **The color of the title text label:** 56 | 57 | `- (UIColor *)titleColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is [UIColor blackColor]** 58 | 59 | **The arrow image of the menu:** 60 | 61 | `- (UIImage *)arrowImageForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is nil** 62 | 63 | **The padding between the title label and the arrow imageview:** 64 | 65 | `- (CGFloat)arrowPaddingForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is 0.0** 66 | 67 | **The animation duration of the menu:** 68 | 69 | `- (NSTimeInterval)animationDurationForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is 0.25** 70 | 71 | **Whether keep cell selected state after menu hide:** 72 | 73 | `- (BOOL)keepCellSelectionForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is YES** 74 | 75 | **The height of the cell:** 76 | 77 | `- (CGFloat)cellHeightForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is 45.0** 78 | 79 | **The insets of the tableview separator:** 80 | 81 | `- (UIEdgeInsets)cellSeparatorInsetsForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)** 82 | 83 | **The text alignment of cell:** 84 | 85 | `- (NSTextAlignment)cellTextAlignmentForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is NSTextAlignmentCenter** 86 | 87 | **The text font of cell:** 88 | 89 | `- (UIFont *)cellTextFontForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is [UIFont systemFontSize:16.0]** 90 | 91 | **The text color of cell:** 92 | 93 | `- (UIColor *)cellTextColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is [UIColor blackColor]** 94 | 95 | **The background color of cell:** 96 | 97 | `- (UIColor *)cellBackgroundColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is [UIColor whiteColor]** 98 | 99 | **The selection color of cell:** 100 | 101 | `- (UIColor *)cellSelectionColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu;` - **Default is nil** 102 | 103 | ## License 104 | The [MIT License](LICENSE). 105 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "SYNavigationDropdownMenu" 4 | s.version = "1.0" 5 | s.summary = "A lightweight dropdown menu drops underneath navigation bar." 6 | s.homepage = "https://github.com/Sunnyyoung/SYNavigationDropdownMenu" 7 | s.license = "MIT" 8 | s.authors = { 'Sunnyyoung' => 'https://github.com/Sunnyyoung' } 9 | s.platform = :ios, "7.0" 10 | s.source = { :git => "https://github.com/Sunnyyoung/SYNavigationDropdownMenu.git", :tag => s.version } 11 | s.source_files = "SYNavigationDropdownMenu/SYNavigationDropdownMenu/*.{h,m}" 12 | s.requires_arc = true 13 | 14 | end -------------------------------------------------------------------------------- /SYNavigationDropdownMenu.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7DD081B71CF6CE65005A527D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DD081B61CF6CE65005A527D /* main.m */; }; 11 | 7DD081BA1CF6CE65005A527D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DD081B91CF6CE65005A527D /* AppDelegate.m */; }; 12 | 7DD081BD1CF6CE65005A527D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DD081BC1CF6CE65005A527D /* ViewController.m */; }; 13 | 7DD081C01CF6CE65005A527D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7DD081BE1CF6CE65005A527D /* Main.storyboard */; }; 14 | 7DD081C21CF6CE65005A527D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7DD081C11CF6CE65005A527D /* Assets.xcassets */; }; 15 | 7DD081C51CF6CE65005A527D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7DD081C31CF6CE65005A527D /* LaunchScreen.storyboard */; }; 16 | 7DD081CF1CF6CE99005A527D /* SYNavigationDropdownMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DD081CE1CF6CE99005A527D /* SYNavigationDropdownMenu.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 7DD081B21CF6CE65005A527D /* SYNavigationDropdownMenu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SYNavigationDropdownMenu.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 7DD081B61CF6CE65005A527D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 22 | 7DD081B81CF6CE65005A527D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 23 | 7DD081B91CF6CE65005A527D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 24 | 7DD081BB1CF6CE65005A527D /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 25 | 7DD081BC1CF6CE65005A527D /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 26 | 7DD081BF1CF6CE65005A527D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 27 | 7DD081C11CF6CE65005A527D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | 7DD081C41CF6CE65005A527D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | 7DD081C61CF6CE65005A527D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 7DD081CD1CF6CE99005A527D /* SYNavigationDropdownMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SYNavigationDropdownMenu.h; sourceTree = ""; }; 31 | 7DD081CE1CF6CE99005A527D /* SYNavigationDropdownMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SYNavigationDropdownMenu.m; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 7DD081AF1CF6CE65005A527D /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 7DD081A91CF6CE65005A527D = { 46 | isa = PBXGroup; 47 | children = ( 48 | 7DD081B41CF6CE65005A527D /* SYNavigationDropdownMenu */, 49 | 7DD081B31CF6CE65005A527D /* Products */, 50 | ); 51 | sourceTree = ""; 52 | }; 53 | 7DD081B31CF6CE65005A527D /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 7DD081B21CF6CE65005A527D /* SYNavigationDropdownMenu.app */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | 7DD081B41CF6CE65005A527D /* SYNavigationDropdownMenu */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | 7DD081CC1CF6CE8E005A527D /* SYNavigationDropdownMenu */, 65 | 7DD081BE1CF6CE65005A527D /* Main.storyboard */, 66 | 7DD081C31CF6CE65005A527D /* LaunchScreen.storyboard */, 67 | 7DD081C11CF6CE65005A527D /* Assets.xcassets */, 68 | 7DD081B81CF6CE65005A527D /* AppDelegate.h */, 69 | 7DD081B91CF6CE65005A527D /* AppDelegate.m */, 70 | 7DD081BB1CF6CE65005A527D /* ViewController.h */, 71 | 7DD081BC1CF6CE65005A527D /* ViewController.m */, 72 | 7DD081B51CF6CE65005A527D /* Supporting Files */, 73 | ); 74 | path = SYNavigationDropdownMenu; 75 | sourceTree = ""; 76 | }; 77 | 7DD081B51CF6CE65005A527D /* Supporting Files */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 7DD081C61CF6CE65005A527D /* Info.plist */, 81 | 7DD081B61CF6CE65005A527D /* main.m */, 82 | ); 83 | name = "Supporting Files"; 84 | sourceTree = ""; 85 | }; 86 | 7DD081CC1CF6CE8E005A527D /* SYNavigationDropdownMenu */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 7DD081CD1CF6CE99005A527D /* SYNavigationDropdownMenu.h */, 90 | 7DD081CE1CF6CE99005A527D /* SYNavigationDropdownMenu.m */, 91 | ); 92 | path = SYNavigationDropdownMenu; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXNativeTarget section */ 98 | 7DD081B11CF6CE65005A527D /* SYNavigationDropdownMenu */ = { 99 | isa = PBXNativeTarget; 100 | buildConfigurationList = 7DD081C91CF6CE65005A527D /* Build configuration list for PBXNativeTarget "SYNavigationDropdownMenu" */; 101 | buildPhases = ( 102 | 7DD081AE1CF6CE65005A527D /* Sources */, 103 | 7DD081AF1CF6CE65005A527D /* Frameworks */, 104 | 7DD081B01CF6CE65005A527D /* Resources */, 105 | ); 106 | buildRules = ( 107 | ); 108 | dependencies = ( 109 | ); 110 | name = SYNavigationDropdownMenu; 111 | productName = SYNavigationDropdownMenu; 112 | productReference = 7DD081B21CF6CE65005A527D /* SYNavigationDropdownMenu.app */; 113 | productType = "com.apple.product-type.application"; 114 | }; 115 | /* End PBXNativeTarget section */ 116 | 117 | /* Begin PBXProject section */ 118 | 7DD081AA1CF6CE65005A527D /* Project object */ = { 119 | isa = PBXProject; 120 | attributes = { 121 | LastUpgradeCheck = 0800; 122 | ORGANIZATIONNAME = Sunnyyoung; 123 | TargetAttributes = { 124 | 7DD081B11CF6CE65005A527D = { 125 | CreatedOnToolsVersion = 7.3.1; 126 | }; 127 | }; 128 | }; 129 | buildConfigurationList = 7DD081AD1CF6CE65005A527D /* Build configuration list for PBXProject "SYNavigationDropdownMenu" */; 130 | compatibilityVersion = "Xcode 3.2"; 131 | developmentRegion = English; 132 | hasScannedForEncodings = 0; 133 | knownRegions = ( 134 | en, 135 | Base, 136 | ); 137 | mainGroup = 7DD081A91CF6CE65005A527D; 138 | productRefGroup = 7DD081B31CF6CE65005A527D /* Products */; 139 | projectDirPath = ""; 140 | projectRoot = ""; 141 | targets = ( 142 | 7DD081B11CF6CE65005A527D /* SYNavigationDropdownMenu */, 143 | ); 144 | }; 145 | /* End PBXProject section */ 146 | 147 | /* Begin PBXResourcesBuildPhase section */ 148 | 7DD081B01CF6CE65005A527D /* Resources */ = { 149 | isa = PBXResourcesBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | 7DD081C51CF6CE65005A527D /* LaunchScreen.storyboard in Resources */, 153 | 7DD081C21CF6CE65005A527D /* Assets.xcassets in Resources */, 154 | 7DD081C01CF6CE65005A527D /* Main.storyboard in Resources */, 155 | ); 156 | runOnlyForDeploymentPostprocessing = 0; 157 | }; 158 | /* End PBXResourcesBuildPhase section */ 159 | 160 | /* Begin PBXSourcesBuildPhase section */ 161 | 7DD081AE1CF6CE65005A527D /* Sources */ = { 162 | isa = PBXSourcesBuildPhase; 163 | buildActionMask = 2147483647; 164 | files = ( 165 | 7DD081BD1CF6CE65005A527D /* ViewController.m in Sources */, 166 | 7DD081BA1CF6CE65005A527D /* AppDelegate.m in Sources */, 167 | 7DD081B71CF6CE65005A527D /* main.m in Sources */, 168 | 7DD081CF1CF6CE99005A527D /* SYNavigationDropdownMenu.m in Sources */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXSourcesBuildPhase section */ 173 | 174 | /* Begin PBXVariantGroup section */ 175 | 7DD081BE1CF6CE65005A527D /* Main.storyboard */ = { 176 | isa = PBXVariantGroup; 177 | children = ( 178 | 7DD081BF1CF6CE65005A527D /* Base */, 179 | ); 180 | name = Main.storyboard; 181 | sourceTree = ""; 182 | }; 183 | 7DD081C31CF6CE65005A527D /* LaunchScreen.storyboard */ = { 184 | isa = PBXVariantGroup; 185 | children = ( 186 | 7DD081C41CF6CE65005A527D /* Base */, 187 | ); 188 | name = LaunchScreen.storyboard; 189 | sourceTree = ""; 190 | }; 191 | /* End PBXVariantGroup section */ 192 | 193 | /* Begin XCBuildConfiguration section */ 194 | 7DD081C71CF6CE65005A527D /* Debug */ = { 195 | isa = XCBuildConfiguration; 196 | buildSettings = { 197 | ALWAYS_SEARCH_USER_PATHS = NO; 198 | CLANG_ANALYZER_NONNULL = YES; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_ENABLE_MODULES = YES; 202 | CLANG_ENABLE_OBJC_ARC = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 206 | CLANG_WARN_EMPTY_BODY = YES; 207 | CLANG_WARN_ENUM_CONVERSION = YES; 208 | CLANG_WARN_INFINITE_RECURSION = YES; 209 | CLANG_WARN_INT_CONVERSION = YES; 210 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 211 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 212 | CLANG_WARN_UNREACHABLE_CODE = YES; 213 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 214 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 215 | COPY_PHASE_STRIP = NO; 216 | DEBUG_INFORMATION_FORMAT = dwarf; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | ENABLE_TESTABILITY = YES; 219 | GCC_C_LANGUAGE_STANDARD = gnu99; 220 | GCC_DYNAMIC_NO_PIC = NO; 221 | GCC_NO_COMMON_BLOCKS = YES; 222 | GCC_OPTIMIZATION_LEVEL = 0; 223 | GCC_PREPROCESSOR_DEFINITIONS = ( 224 | "DEBUG=1", 225 | "$(inherited)", 226 | ); 227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 229 | GCC_WARN_UNDECLARED_SELECTOR = YES; 230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 231 | GCC_WARN_UNUSED_FUNCTION = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 234 | MTL_ENABLE_DEBUG_INFO = YES; 235 | ONLY_ACTIVE_ARCH = YES; 236 | SDKROOT = iphoneos; 237 | TARGETED_DEVICE_FAMILY = "1,2"; 238 | }; 239 | name = Debug; 240 | }; 241 | 7DD081C81CF6CE65005A527D /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_ANALYZER_NONNULL = YES; 246 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 247 | CLANG_CXX_LIBRARY = "libc++"; 248 | CLANG_ENABLE_MODULES = YES; 249 | CLANG_ENABLE_OBJC_ARC = YES; 250 | CLANG_WARN_BOOL_CONVERSION = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INFINITE_RECURSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 258 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 259 | CLANG_WARN_UNREACHABLE_CODE = YES; 260 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 261 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 262 | COPY_PHASE_STRIP = NO; 263 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 264 | ENABLE_NS_ASSERTIONS = NO; 265 | ENABLE_STRICT_OBJC_MSGSEND = YES; 266 | GCC_C_LANGUAGE_STANDARD = gnu99; 267 | GCC_NO_COMMON_BLOCKS = YES; 268 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 269 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 270 | GCC_WARN_UNDECLARED_SELECTOR = YES; 271 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 272 | GCC_WARN_UNUSED_FUNCTION = YES; 273 | GCC_WARN_UNUSED_VARIABLE = YES; 274 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 275 | MTL_ENABLE_DEBUG_INFO = NO; 276 | SDKROOT = iphoneos; 277 | TARGETED_DEVICE_FAMILY = "1,2"; 278 | VALIDATE_PRODUCT = YES; 279 | }; 280 | name = Release; 281 | }; 282 | 7DD081CA1CF6CE65005A527D /* Debug */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 286 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; 287 | DEVELOPMENT_TEAM = ""; 288 | INFOPLIST_FILE = SYNavigationDropdownMenu/Info.plist; 289 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 290 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 291 | PRODUCT_BUNDLE_IDENTIFIER = net.sunnyyoung.SYNavigationDropdownMenu; 292 | PRODUCT_NAME = "$(TARGET_NAME)"; 293 | }; 294 | name = Debug; 295 | }; 296 | 7DD081CB1CF6CE65005A527D /* Release */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "Brand Assets"; 301 | DEVELOPMENT_TEAM = ""; 302 | INFOPLIST_FILE = SYNavigationDropdownMenu/Info.plist; 303 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 305 | PRODUCT_BUNDLE_IDENTIFIER = net.sunnyyoung.SYNavigationDropdownMenu; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | }; 308 | name = Release; 309 | }; 310 | /* End XCBuildConfiguration section */ 311 | 312 | /* Begin XCConfigurationList section */ 313 | 7DD081AD1CF6CE65005A527D /* Build configuration list for PBXProject "SYNavigationDropdownMenu" */ = { 314 | isa = XCConfigurationList; 315 | buildConfigurations = ( 316 | 7DD081C71CF6CE65005A527D /* Debug */, 317 | 7DD081C81CF6CE65005A527D /* Release */, 318 | ); 319 | defaultConfigurationIsVisible = 0; 320 | defaultConfigurationName = Release; 321 | }; 322 | 7DD081C91CF6CE65005A527D /* Build configuration list for PBXNativeTarget "SYNavigationDropdownMenu" */ = { 323 | isa = XCConfigurationList; 324 | buildConfigurations = ( 325 | 7DD081CA1CF6CE65005A527D /* Debug */, 326 | 7DD081CB1CF6CE65005A527D /* Release */, 327 | ); 328 | defaultConfigurationIsVisible = 0; 329 | defaultConfigurationName = Release; 330 | }; 331 | /* End XCConfigurationList section */ 332 | }; 333 | rootObject = 7DD081AA1CF6CE65005A527D /* Project object */; 334 | } 335 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. 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 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Assets.xcassets/Arrow.imageset/Arrow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunnyyoung/SYNavigationDropdownMenu/a6470b49adbe9686df6b50b694a7e450ff974248/SYNavigationDropdownMenu/Assets.xcassets/Arrow.imageset/Arrow.pdf -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Assets.xcassets/Arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Arrow.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Assets.xcassets/Brand Assets.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "8.0", 8 | "subtype" : "736h", 9 | "scale" : "3x" 10 | }, 11 | { 12 | "orientation" : "portrait", 13 | "idiom" : "iphone", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "8.0", 16 | "subtype" : "667h", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "orientation" : "portrait", 21 | "idiom" : "iphone", 22 | "extent" : "full-screen", 23 | "minimum-system-version" : "7.0", 24 | "scale" : "2x" 25 | }, 26 | { 27 | "orientation" : "portrait", 28 | "idiom" : "iphone", 29 | "extent" : "full-screen", 30 | "minimum-system-version" : "7.0", 31 | "subtype" : "retina4", 32 | "scale" : "2x" 33 | } 34 | ], 35 | "info" : { 36 | "version" : 1, 37 | "author" : "xcode" 38 | } 39 | } -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/SYNavigationDropdownMenu/SYNavigationDropdownMenu.h: -------------------------------------------------------------------------------- 1 | // 2 | // SYNavigationDropdownMenu.h 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class SYNavigationDropdownMenu; 12 | 13 | @protocol SYNavigationDropdownMenuDataSource 14 | 15 | @required 16 | - (NSArray *)titleArrayForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; 17 | 18 | @optional 19 | - (UIFont *)titleFontForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is [UIFont systemFontOfSize:17.0] 20 | - (UIColor *)titleColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is [UIColor blackColor] 21 | - (UIImage *)arrowImageForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is nil 22 | - (CGFloat)arrowPaddingForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is 0.0 23 | - (NSTimeInterval)animationDurationForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is 0.25 24 | - (BOOL)keepCellSelectionForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is YES 25 | - (CGFloat)cellHeightForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is 45.0 26 | - (UIEdgeInsets)cellSeparatorInsetsForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0) 27 | - (NSTextAlignment)cellTextAlignmentForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is NSTextAlignmentCenter 28 | - (UIFont *)cellTextFontForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is [UIFont systemFontOfSize:16.0] 29 | - (UIColor *)cellTextColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is [UIColor blackColor] 30 | - (UIColor *)cellBackgroundColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is [UIColor whiteColor] 31 | - (UIColor *)cellSelectionColorForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu; // Default is nil 32 | 33 | @end 34 | 35 | @protocol SYNavigationDropdownMenuDelegate 36 | 37 | @required 38 | - (void)navigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu didSelectTitleAtIndex:(NSUInteger)index; 39 | 40 | @end 41 | 42 | @interface SYNavigationDropdownMenu : UIButton 43 | 44 | @property (nonatomic, weak) id dataSource; 45 | @property (nonatomic, weak) id delegate; 46 | 47 | - (instancetype)initWithNavigationController:(UINavigationController *)navigationController; 48 | 49 | - (void)show; 50 | - (void)hide; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/SYNavigationDropdownMenu/SYNavigationDropdownMenu.m: -------------------------------------------------------------------------------- 1 | // 2 | // SYNavigationDropdownMenu.m 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. All rights reserved. 7 | // 8 | 9 | #import "SYNavigationDropdownMenu.h" 10 | 11 | @interface SYNavigationDropdownMenu () 12 | 13 | @property (nonatomic, weak) UINavigationController *navigationController; 14 | @property (nonatomic, strong) UITableView *menuTableView; 15 | @property (nonatomic, strong) UIView *menuHeaderView; 16 | @property (nonatomic, strong) UIView *menuBackgroundView; 17 | 18 | @end 19 | 20 | @implementation SYNavigationDropdownMenu 21 | 22 | - (instancetype)init { 23 | self = [SYNavigationDropdownMenu buttonWithType:UIButtonTypeCustom]; 24 | if (self) { 25 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 26 | } 27 | return self; 28 | } 29 | 30 | - (instancetype)initWithNavigationController:(UINavigationController *)navigationController { 31 | self = [self init]; 32 | if (self) { 33 | self.frame = navigationController.navigationBar.frame; 34 | self.navigationController = navigationController; 35 | } 36 | return self; 37 | } 38 | 39 | #pragma mark Layout method 40 | 41 | - (void)layoutSubviews { 42 | [super layoutSubviews]; 43 | [self updateMenuImage]; 44 | [self updateMenuTitle]; 45 | [self updateMenuHeaderView]; 46 | [self updateMenuBackground]; 47 | } 48 | 49 | - (CGSize)sizeThatFits:(CGSize)size { 50 | return CGSizeMake([super sizeThatFits:size].width + self.arrowPadding, [super sizeThatFits:size].height); 51 | } 52 | 53 | - (CGSize)intrinsicContentSize { 54 | return CGSizeMake([super intrinsicContentSize].width + self.arrowPadding, [super intrinsicContentSize].height); 55 | } 56 | 57 | - (void)updateMenuImage { 58 | [self setImage:self.arrowImage forState:UIControlStateNormal]; 59 | [self setImageEdgeInsets:UIEdgeInsetsMake(0.0, CGRectGetWidth(self.titleLabel.frame) + self.arrowPadding, 0.0, -CGRectGetWidth(self.titleLabel.frame))]; 60 | } 61 | 62 | - (void)updateMenuTitle { 63 | [self.titleLabel setFont:self.titleFont]; 64 | [self setTitleColor:self.titleColor forState:UIControlStateNormal]; 65 | [self setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -CGRectGetWidth(self.imageView.frame), 0.0, CGRectGetWidth(self.imageView.frame) + self.arrowPadding)]; 66 | } 67 | 68 | - (void)updateMenuHeaderView { 69 | CGRect menuHeaderViewFrame = self.menuHeaderView.frame; 70 | menuHeaderViewFrame.size.width = CGRectGetWidth(self.navigationController.navigationBar.frame); 71 | menuHeaderViewFrame.size.height = self.cellHeight; 72 | self.menuHeaderView.frame = menuHeaderViewFrame; 73 | self.menuHeaderView.backgroundColor = self.cellBackgroundColor; 74 | } 75 | 76 | - (void)updateMenuBackground { 77 | CGRect menuBackgroundViewFrame = [UIScreen mainScreen].bounds; 78 | menuBackgroundViewFrame.origin.y += CGRectGetMaxY(self.navigationController.navigationBar.frame); 79 | menuBackgroundViewFrame.size.height -= CGRectGetMaxY(self.navigationController.navigationBar.frame); 80 | self.menuBackgroundView.frame = menuBackgroundViewFrame; 81 | } 82 | 83 | #pragma mark - ScrollView Delegate 84 | 85 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 86 | CGRect menuHeaderViewFrame = self.menuHeaderView.frame; 87 | menuHeaderViewFrame.size.height = MAX(0.0, -scrollView.contentOffset.y); 88 | self.menuHeaderView.frame = menuHeaderViewFrame; 89 | } 90 | 91 | #pragma mark - TableView DataSource 92 | 93 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 94 | return self.titleArray.count; 95 | } 96 | 97 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 98 | return self.cellHeight; 99 | } 100 | 101 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 102 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; 103 | cell.textLabel.text = [self.dataSource titleArrayForNavigationDropdownMenu:self][indexPath.row]; 104 | cell.textLabel.font = self.cellTextFont; 105 | cell.textLabel.textColor = self.cellTextColor; 106 | cell.textLabel.textAlignment = self.cellTextAlignment; 107 | cell.backgroundColor = self.cellBackgroundColor; 108 | if (self.cellSelectedColor) { 109 | cell.selectedBackgroundView = [[UIView alloc] init]; 110 | cell.selectedBackgroundView.backgroundColor = self.cellSelectedColor; 111 | } 112 | return cell; 113 | } 114 | 115 | #pragma mark - TableView Delegate 116 | 117 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { 118 | if ([cell respondsToSelector:@selector(setSeparatorInset:)]) { 119 | [cell setSeparatorInset:self.cellSeparatorInsets]; 120 | } 121 | if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) { 122 | [cell setPreservesSuperviewLayoutMargins:NO]; 123 | } 124 | if ([cell respondsToSelector:@selector(setLayoutMargins:)]) { 125 | [cell setLayoutMargins:self.cellSeparatorInsets]; 126 | } 127 | } 128 | 129 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 130 | self.keepCellSelection ?: [tableView deselectRowAtIndexPath:indexPath animated:YES]; 131 | if ([self.delegate respondsToSelector:@selector(navigationDropdownMenu:didSelectTitleAtIndex:)]) { 132 | [self.delegate navigationDropdownMenu:self didSelectTitleAtIndex:indexPath.row]; 133 | } 134 | [self setTitle:self.titleArray[indexPath.row] forState:UIControlStateNormal]; 135 | [self hide]; 136 | } 137 | 138 | #pragma mark - Public method 139 | 140 | - (void)show { 141 | [[UIApplication sharedApplication].keyWindow addSubview:self.menuBackgroundView]; 142 | CGRect menuTableViewFrame = self.menuTableView.frame; 143 | menuTableViewFrame.origin.y = -(MIN(self.titleArray.count * self.cellHeight, CGRectGetHeight(self.menuBackgroundView.frame))); 144 | self.menuTableView.frame = menuTableViewFrame; 145 | self.selected = YES; 146 | [UIView animateWithDuration:self.animationDuration * 1.5 delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:0.5 options:kNilOptions animations:^{ 147 | CGRect menuTableViewFrame = self.menuTableView.frame; 148 | menuTableViewFrame.origin.y = 0.0; 149 | self.menuTableView.frame = menuTableViewFrame; 150 | self.menuBackgroundView.alpha = 1.0; 151 | } completion:nil]; 152 | } 153 | 154 | - (void)hide { 155 | self.selected = NO; 156 | [UIView animateWithDuration:self.animationDuration animations:^{ 157 | CGRect menuTableViewFrame = self.menuTableView.frame; 158 | menuTableViewFrame.origin.y = -(MIN(self.titleArray.count * self.cellHeight, CGRectGetHeight(self.menuBackgroundView.frame))); 159 | self.menuTableView.frame = menuTableViewFrame; 160 | self.menuBackgroundView.alpha = 0.0; 161 | } completion:^(BOOL finished) { 162 | [self.menuBackgroundView removeFromSuperview]; 163 | }]; 164 | } 165 | 166 | #pragma mark - Event Response 167 | 168 | - (void)menuAction:(SYNavigationDropdownMenu *)sender { 169 | self.isSelected?[self hide]:[self show]; 170 | } 171 | 172 | #pragma mark - Property method 173 | 174 | - (UITableView *)menuTableView { 175 | if (_menuTableView == nil) { 176 | _menuTableView = [[UITableView alloc] initWithFrame:self.menuBackgroundView.bounds style:UITableViewStylePlain]; 177 | _menuTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin; 178 | _menuTableView.dataSource = self; 179 | _menuTableView.delegate = self; 180 | _menuTableView.backgroundColor = [UIColor clearColor]; 181 | _menuTableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, CGFLOAT_MIN)]; 182 | [_menuTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"]; 183 | [self.menuBackgroundView addSubview:_menuTableView]; 184 | } 185 | return _menuTableView; 186 | } 187 | 188 | - (UIView *)menuHeaderView { 189 | if (_menuHeaderView == nil) { 190 | _menuHeaderView = [[UIView alloc] initWithFrame:CGRectZero]; 191 | _menuHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth; 192 | [self.menuBackgroundView addSubview:_menuHeaderView]; 193 | } 194 | return _menuHeaderView; 195 | } 196 | 197 | - (UIView *)menuBackgroundView { 198 | if (_menuBackgroundView == nil) { 199 | _menuBackgroundView = [[UIView alloc] initWithFrame:CGRectZero]; 200 | _menuBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 201 | _menuBackgroundView.clipsToBounds = YES; 202 | _menuBackgroundView.alpha = 0.0; 203 | _menuBackgroundView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.6]; 204 | } 205 | return _menuBackgroundView; 206 | } 207 | 208 | - (void)setSelected:(BOOL)selected { 209 | [super setSelected:selected]; 210 | self.userInteractionEnabled = NO; 211 | [UIView animateWithDuration:self.animationDuration animations:^{ 212 | self.imageView.transform = CGAffineTransformMakeRotation(selected ? M_PI : 0.0); 213 | } completion:^(BOOL finished) { 214 | self.userInteractionEnabled = YES; 215 | }]; 216 | } 217 | 218 | - (void)setDataSource:(id)dataSource { 219 | _dataSource = dataSource; 220 | [self setTitle:self.titleArray.firstObject forState:UIControlStateNormal]; 221 | } 222 | 223 | - (void)setDelegate:(id)delegate { 224 | _delegate = delegate; 225 | if ([delegate respondsToSelector:@selector(navigationDropdownMenu:didSelectTitleAtIndex:)]) { 226 | [self addTarget:self action:@selector(menuAction:) forControlEvents:UIControlEventTouchUpInside]; 227 | } 228 | } 229 | 230 | #pragma mark - ReadOnly Property 231 | 232 | - (NSArray *)titleArray { 233 | if ([self.dataSource respondsToSelector:@selector(titleArrayForNavigationDropdownMenu:)]) { 234 | return [self.dataSource titleArrayForNavigationDropdownMenu:self]; 235 | } else { 236 | return nil; 237 | } 238 | } 239 | 240 | - (UIFont *)titleFont { 241 | if ([self.dataSource respondsToSelector:@selector(titleFontForNavigationDropdownMenu:)]) { 242 | return [self.dataSource titleFontForNavigationDropdownMenu:self]; 243 | } else { 244 | return [UIFont systemFontOfSize:17.0]; 245 | } 246 | } 247 | 248 | - (UIColor *)titleColor { 249 | if ([self.dataSource respondsToSelector:@selector(titleColorForNavigationDropdownMenu:)]) { 250 | return [self.dataSource titleColorForNavigationDropdownMenu:self]; 251 | } else { 252 | return [UIColor blackColor]; 253 | } 254 | } 255 | 256 | - (UIImage *)arrowImage { 257 | if ([self.dataSource respondsToSelector:@selector(arrowImageForNavigationDropdownMenu:)]) { 258 | return [self.dataSource arrowImageForNavigationDropdownMenu:self]; 259 | } else { 260 | return nil; 261 | } 262 | } 263 | 264 | - (CGFloat)arrowPadding { 265 | if ([self.dataSource respondsToSelector:@selector(arrowPaddingForNavigationDropdownMenu:)] && self.arrowImage) { 266 | return [self.dataSource arrowPaddingForNavigationDropdownMenu:self]; 267 | } else { 268 | return 0.0; 269 | } 270 | } 271 | 272 | - (NSTimeInterval)animationDuration { 273 | if ([self.dataSource respondsToSelector:@selector(animationDurationForNavigationDropdownMenu:)]) { 274 | return [self.dataSource animationDurationForNavigationDropdownMenu:self]; 275 | } else { 276 | return 0.25; 277 | } 278 | } 279 | 280 | - (BOOL)keepCellSelection { 281 | if ([self.dataSource respondsToSelector:@selector(keepCellSelectionForNavigationDropdownMenu:)]) { 282 | return [self.dataSource keepCellSelectionForNavigationDropdownMenu:self]; 283 | } else { 284 | return YES; 285 | } 286 | } 287 | 288 | - (CGFloat)cellHeight { 289 | if ([self.dataSource respondsToSelector:@selector(cellHeightForNavigationDropdownMenu:)]) { 290 | return [self.dataSource cellHeightForNavigationDropdownMenu:self]; 291 | } else { 292 | return 45.0; 293 | } 294 | } 295 | 296 | - (UIEdgeInsets)cellSeparatorInsets { 297 | if ([self.dataSource respondsToSelector:@selector(cellSeparatorInsetsForNavigationDropdownMenu:)]) { 298 | return [self.dataSource cellSeparatorInsetsForNavigationDropdownMenu:self]; 299 | } else { 300 | return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0); 301 | } 302 | } 303 | 304 | - (NSTextAlignment)cellTextAlignment { 305 | if ([self.dataSource respondsToSelector:@selector(cellTextAlignmentForNavigationDropdownMenu:)]) { 306 | return [self.dataSource cellTextAlignmentForNavigationDropdownMenu:self]; 307 | } else { 308 | return NSTextAlignmentCenter; 309 | } 310 | } 311 | 312 | - (UIFont *)cellTextFont { 313 | if ([self.dataSource respondsToSelector:@selector(cellTextFontForNavigationDropdownMenu:)]) { 314 | return [self.dataSource cellTextFontForNavigationDropdownMenu:self]; 315 | } else { 316 | return [UIFont systemFontOfSize:16.0]; 317 | } 318 | } 319 | 320 | - (UIColor *)cellTextColor { 321 | if ([self.dataSource respondsToSelector:@selector(cellTextColorForNavigationDropdownMenu:)]) { 322 | return [self.dataSource cellTextColorForNavigationDropdownMenu:self]; 323 | } else { 324 | return [UIColor blackColor]; 325 | } 326 | } 327 | 328 | - (UIColor *)cellBackgroundColor { 329 | if ([self.dataSource respondsToSelector:@selector(cellBackgroundColorForNavigationDropdownMenu:)]) { 330 | return [self.dataSource cellBackgroundColorForNavigationDropdownMenu:self]; 331 | } else { 332 | return [UIColor whiteColor]; 333 | } 334 | } 335 | 336 | - (UIColor *)cellSelectedColor { 337 | if ([self.dataSource respondsToSelector:@selector(cellSelectionColorForNavigationDropdownMenu:)]) { 338 | return [self.dataSource cellSelectionColorForNavigationDropdownMenu:self]; 339 | } else { 340 | return nil; 341 | } 342 | } 343 | 344 | @end 345 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SYNavigationDropdownMenu.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (weak, nonatomic) IBOutlet UILabel *label; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | [self setup]; 23 | } 24 | 25 | - (void)setup { 26 | SYNavigationDropdownMenu *menu = [[SYNavigationDropdownMenu alloc] initWithNavigationController:self.navigationController]; 27 | menu.dataSource = self; 28 | menu.delegate = self; 29 | self.navigationItem.titleView = menu; 30 | } 31 | 32 | - (NSArray *)titleArrayForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu { 33 | return self.titleArray; 34 | } 35 | 36 | - (CGFloat)arrowPaddingForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu { 37 | return 8.0; 38 | } 39 | 40 | - (UIImage *)arrowImageForNavigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu { 41 | return [UIImage imageNamed:@"Arrow"]; 42 | } 43 | 44 | - (void)navigationDropdownMenu:(SYNavigationDropdownMenu *)navigationDropdownMenu didSelectTitleAtIndex:(NSUInteger)index { 45 | self.label.text = self.titleArray[index]; 46 | } 47 | 48 | #pragma mark - Property method 49 | 50 | - (NSArray *)titleArray { 51 | return @[@"Hello", @"World", @"I am Sunnyyoung 😄", @"This is really very very very very very very very very long text!!!"]; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /SYNavigationDropdownMenu/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SYNavigationDropdownMenu 4 | // 5 | // Created by Sunnyyoung on 16/5/26. 6 | // Copyright © 2016年 Sunnyyoung. 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 | -------------------------------------------------------------------------------- /Screenshot/ScreenShot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunnyyoung/SYNavigationDropdownMenu/a6470b49adbe9686df6b50b694a7e450ff974248/Screenshot/ScreenShot.gif --------------------------------------------------------------------------------