├── HADropDown ├── HADropDown.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── hassan.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── hassan.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── MyDropDown.xcscheme │ │ └── xcschememanagement.plist └── HADropDown │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── HADropDown.swift │ ├── Info.plist │ └── ViewController.swift ├── LICENSE.rtf ├── README.md └── Simulator Screen Shot /HADropDown/HADropDown.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5CC79BAB1E607D05002A62E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC79BA21E607D05002A62E0 /* AppDelegate.swift */; }; 11 | 5CC79BAC1E607D05002A62E0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5CC79BA31E607D05002A62E0 /* Assets.xcassets */; }; 12 | 5CC79BAD1E607D05002A62E0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5CC79BA41E607D05002A62E0 /* LaunchScreen.storyboard */; }; 13 | 5CC79BAE1E607D05002A62E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5CC79BA61E607D05002A62E0 /* Main.storyboard */; }; 14 | 5CC79BAF1E607D05002A62E0 /* HADropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC79BA81E607D05002A62E0 /* HADropDown.swift */; }; 15 | 5CC79BB01E607D05002A62E0 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5CC79BA91E607D05002A62E0 /* Info.plist */; }; 16 | 5CC79BB11E607D05002A62E0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC79BAA1E607D05002A62E0 /* ViewController.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 5C1B20721E5DC43700701C3B /* HADropDown.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HADropDown.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 5CC79BA21E607D05002A62E0 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | 5CC79BA31E607D05002A62E0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | 5CC79BA51E607D05002A62E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 24 | 5CC79BA71E607D05002A62E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 25 | 5CC79BA81E607D05002A62E0 /* HADropDown.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HADropDown.swift; sourceTree = ""; }; 26 | 5CC79BA91E607D05002A62E0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | 5CC79BAA1E607D05002A62E0 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 5C1B206F1E5DC43600701C3B /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 5C1B20691E5DC43600701C3B = { 42 | isa = PBXGroup; 43 | children = ( 44 | 5CC79BA11E607D05002A62E0 /* HADropDown */, 45 | 5C1B20731E5DC43700701C3B /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 5C1B20731E5DC43700701C3B /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 5C1B20721E5DC43700701C3B /* HADropDown.app */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 5CC79BA11E607D05002A62E0 /* HADropDown */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 5CC79BA21E607D05002A62E0 /* AppDelegate.swift */, 61 | 5CC79BA31E607D05002A62E0 /* Assets.xcassets */, 62 | 5CC79BA41E607D05002A62E0 /* LaunchScreen.storyboard */, 63 | 5CC79BA61E607D05002A62E0 /* Main.storyboard */, 64 | 5CC79BA81E607D05002A62E0 /* HADropDown.swift */, 65 | 5CC79BA91E607D05002A62E0 /* Info.plist */, 66 | 5CC79BAA1E607D05002A62E0 /* ViewController.swift */, 67 | ); 68 | path = HADropDown; 69 | sourceTree = ""; 70 | }; 71 | /* End PBXGroup section */ 72 | 73 | /* Begin PBXNativeTarget section */ 74 | 5C1B20711E5DC43600701C3B /* HADropDown */ = { 75 | isa = PBXNativeTarget; 76 | buildConfigurationList = 5C1B20841E5DC43700701C3B /* Build configuration list for PBXNativeTarget "HADropDown" */; 77 | buildPhases = ( 78 | 5C1B206E1E5DC43600701C3B /* Sources */, 79 | 5C1B206F1E5DC43600701C3B /* Frameworks */, 80 | 5C1B20701E5DC43600701C3B /* Resources */, 81 | ); 82 | buildRules = ( 83 | ); 84 | dependencies = ( 85 | ); 86 | name = HADropDown; 87 | productName = MyDropDown; 88 | productReference = 5C1B20721E5DC43700701C3B /* HADropDown.app */; 89 | productType = "com.apple.product-type.application"; 90 | }; 91 | /* End PBXNativeTarget section */ 92 | 93 | /* Begin PBXProject section */ 94 | 5C1B206A1E5DC43600701C3B /* Project object */ = { 95 | isa = PBXProject; 96 | attributes = { 97 | LastSwiftUpdateCheck = 0820; 98 | LastUpgradeCheck = 0820; 99 | ORGANIZATIONNAME = "Hassan Aftab"; 100 | TargetAttributes = { 101 | 5C1B20711E5DC43600701C3B = { 102 | CreatedOnToolsVersion = 8.2.1; 103 | ProvisioningStyle = Automatic; 104 | }; 105 | }; 106 | }; 107 | buildConfigurationList = 5C1B206D1E5DC43600701C3B /* Build configuration list for PBXProject "HADropDown" */; 108 | compatibilityVersion = "Xcode 3.2"; 109 | developmentRegion = English; 110 | hasScannedForEncodings = 0; 111 | knownRegions = ( 112 | en, 113 | Base, 114 | ); 115 | mainGroup = 5C1B20691E5DC43600701C3B; 116 | productRefGroup = 5C1B20731E5DC43700701C3B /* Products */; 117 | projectDirPath = ""; 118 | projectRoot = ""; 119 | targets = ( 120 | 5C1B20711E5DC43600701C3B /* HADropDown */, 121 | ); 122 | }; 123 | /* End PBXProject section */ 124 | 125 | /* Begin PBXResourcesBuildPhase section */ 126 | 5C1B20701E5DC43600701C3B /* Resources */ = { 127 | isa = PBXResourcesBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | 5CC79BB01E607D05002A62E0 /* Info.plist in Resources */, 131 | 5CC79BAE1E607D05002A62E0 /* Main.storyboard in Resources */, 132 | 5CC79BAC1E607D05002A62E0 /* Assets.xcassets in Resources */, 133 | 5CC79BAD1E607D05002A62E0 /* LaunchScreen.storyboard in Resources */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXResourcesBuildPhase section */ 138 | 139 | /* Begin PBXSourcesBuildPhase section */ 140 | 5C1B206E1E5DC43600701C3B /* Sources */ = { 141 | isa = PBXSourcesBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | 5CC79BB11E607D05002A62E0 /* ViewController.swift in Sources */, 145 | 5CC79BAB1E607D05002A62E0 /* AppDelegate.swift in Sources */, 146 | 5CC79BAF1E607D05002A62E0 /* HADropDown.swift in Sources */, 147 | ); 148 | runOnlyForDeploymentPostprocessing = 0; 149 | }; 150 | /* End PBXSourcesBuildPhase section */ 151 | 152 | /* Begin PBXVariantGroup section */ 153 | 5CC79BA41E607D05002A62E0 /* LaunchScreen.storyboard */ = { 154 | isa = PBXVariantGroup; 155 | children = ( 156 | 5CC79BA51E607D05002A62E0 /* Base */, 157 | ); 158 | name = LaunchScreen.storyboard; 159 | sourceTree = ""; 160 | }; 161 | 5CC79BA61E607D05002A62E0 /* Main.storyboard */ = { 162 | isa = PBXVariantGroup; 163 | children = ( 164 | 5CC79BA71E607D05002A62E0 /* Base */, 165 | ); 166 | name = Main.storyboard; 167 | sourceTree = ""; 168 | }; 169 | /* End PBXVariantGroup section */ 170 | 171 | /* Begin XCBuildConfiguration section */ 172 | 5C1B20821E5DC43700701C3B /* Debug */ = { 173 | isa = XCBuildConfiguration; 174 | buildSettings = { 175 | ALWAYS_SEARCH_USER_PATHS = NO; 176 | CLANG_ANALYZER_NONNULL = YES; 177 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 178 | CLANG_CXX_LIBRARY = "libc++"; 179 | CLANG_ENABLE_MODULES = YES; 180 | CLANG_ENABLE_OBJC_ARC = YES; 181 | CLANG_WARN_BOOL_CONVERSION = YES; 182 | CLANG_WARN_CONSTANT_CONVERSION = YES; 183 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 184 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 185 | CLANG_WARN_EMPTY_BODY = YES; 186 | CLANG_WARN_ENUM_CONVERSION = YES; 187 | CLANG_WARN_INFINITE_RECURSION = YES; 188 | CLANG_WARN_INT_CONVERSION = YES; 189 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 190 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 191 | CLANG_WARN_UNREACHABLE_CODE = YES; 192 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 193 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 194 | COPY_PHASE_STRIP = NO; 195 | DEBUG_INFORMATION_FORMAT = dwarf; 196 | ENABLE_STRICT_OBJC_MSGSEND = YES; 197 | ENABLE_TESTABILITY = YES; 198 | GCC_C_LANGUAGE_STANDARD = gnu99; 199 | GCC_DYNAMIC_NO_PIC = NO; 200 | GCC_NO_COMMON_BLOCKS = YES; 201 | GCC_OPTIMIZATION_LEVEL = 0; 202 | GCC_PREPROCESSOR_DEFINITIONS = ( 203 | "DEBUG=1", 204 | "$(inherited)", 205 | ); 206 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 207 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 208 | GCC_WARN_UNDECLARED_SELECTOR = YES; 209 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 210 | GCC_WARN_UNUSED_FUNCTION = YES; 211 | GCC_WARN_UNUSED_VARIABLE = YES; 212 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 213 | MTL_ENABLE_DEBUG_INFO = YES; 214 | ONLY_ACTIVE_ARCH = YES; 215 | SDKROOT = iphoneos; 216 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 217 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 218 | }; 219 | name = Debug; 220 | }; 221 | 5C1B20831E5DC43700701C3B /* Release */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | ALWAYS_SEARCH_USER_PATHS = NO; 225 | CLANG_ANALYZER_NONNULL = YES; 226 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 227 | CLANG_CXX_LIBRARY = "libc++"; 228 | CLANG_ENABLE_MODULES = YES; 229 | CLANG_ENABLE_OBJC_ARC = YES; 230 | CLANG_WARN_BOOL_CONVERSION = YES; 231 | CLANG_WARN_CONSTANT_CONVERSION = YES; 232 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 233 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 234 | CLANG_WARN_EMPTY_BODY = YES; 235 | CLANG_WARN_ENUM_CONVERSION = YES; 236 | CLANG_WARN_INFINITE_RECURSION = YES; 237 | CLANG_WARN_INT_CONVERSION = YES; 238 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 239 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 240 | CLANG_WARN_UNREACHABLE_CODE = YES; 241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 242 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 243 | COPY_PHASE_STRIP = NO; 244 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 245 | ENABLE_NS_ASSERTIONS = NO; 246 | ENABLE_STRICT_OBJC_MSGSEND = YES; 247 | GCC_C_LANGUAGE_STANDARD = gnu99; 248 | GCC_NO_COMMON_BLOCKS = YES; 249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 251 | GCC_WARN_UNDECLARED_SELECTOR = YES; 252 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 253 | GCC_WARN_UNUSED_FUNCTION = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 256 | MTL_ENABLE_DEBUG_INFO = NO; 257 | SDKROOT = iphoneos; 258 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 259 | VALIDATE_PRODUCT = YES; 260 | }; 261 | name = Release; 262 | }; 263 | 5C1B20851E5DC43700701C3B /* Debug */ = { 264 | isa = XCBuildConfiguration; 265 | buildSettings = { 266 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 267 | INFOPLIST_FILE = "$(SRCROOT)/HADropDown/Info.plist"; 268 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 269 | PRODUCT_BUNDLE_IDENTIFIER = com.app.HADropDown; 270 | PRODUCT_NAME = "$(TARGET_NAME)"; 271 | SWIFT_VERSION = 3.0; 272 | }; 273 | name = Debug; 274 | }; 275 | 5C1B20861E5DC43700701C3B /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | INFOPLIST_FILE = "$(SRCROOT)/HADropDown/Info.plist"; 280 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 281 | PRODUCT_BUNDLE_IDENTIFIER = com.app.HADropDown; 282 | PRODUCT_NAME = "$(TARGET_NAME)"; 283 | SWIFT_VERSION = 3.0; 284 | }; 285 | name = Release; 286 | }; 287 | /* End XCBuildConfiguration section */ 288 | 289 | /* Begin XCConfigurationList section */ 290 | 5C1B206D1E5DC43600701C3B /* Build configuration list for PBXProject "HADropDown" */ = { 291 | isa = XCConfigurationList; 292 | buildConfigurations = ( 293 | 5C1B20821E5DC43700701C3B /* Debug */, 294 | 5C1B20831E5DC43700701C3B /* Release */, 295 | ); 296 | defaultConfigurationIsVisible = 0; 297 | defaultConfigurationName = Release; 298 | }; 299 | 5C1B20841E5DC43700701C3B /* Build configuration list for PBXNativeTarget "HADropDown" */ = { 300 | isa = XCConfigurationList; 301 | buildConfigurations = ( 302 | 5C1B20851E5DC43700701C3B /* Debug */, 303 | 5C1B20861E5DC43700701C3B /* Release */, 304 | ); 305 | defaultConfigurationIsVisible = 0; 306 | defaultConfigurationName = Release; 307 | }; 308 | /* End XCConfigurationList section */ 309 | }; 310 | rootObject = 5C1B206A1E5DC43600701C3B /* Project object */; 311 | } 312 | -------------------------------------------------------------------------------- /HADropDown/HADropDown.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HADropDown/HADropDown.xcodeproj/project.xcworkspace/xcuserdata/hassan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hassan-Aftab/HADropDown/90eee93458d33f9956e51512f976b4fab1a96d2e/HADropDown/HADropDown.xcodeproj/project.xcworkspace/xcuserdata/hassan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HADropDown/HADropDown.xcodeproj/xcuserdata/hassan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /HADropDown/HADropDown.xcodeproj/xcuserdata/hassan.xcuserdatad/xcschemes/MyDropDown.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /HADropDown/HADropDown.xcodeproj/xcuserdata/hassan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MyDropDown.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 5C1B20711E5DC43600701C3B 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HADropDown/HADropDown/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // MyDropDown 4 | // 5 | // Created by Hassan Aftab on 22/02/2017. 6 | // Copyright © 2017 Hassan Aftab. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // 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. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /HADropDown/HADropDown/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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /HADropDown/HADropDown/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 | -------------------------------------------------------------------------------- /HADropDown/HADropDown/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /HADropDown/HADropDown/HADropDown.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HADropDown.swift 3 | // MyDropDown 4 | // 5 | // Created by Hassan Aftab on 22/02/2017. 6 | // Copyright © 2017 Hassan Aftab. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol HADropDownDelegate: class { 12 | func didSelectItem(dropDown: HADropDown, at index: Int) 13 | func didShow(dropDown: HADropDown) 14 | func didHide(dropDown: HADropDown) 15 | 16 | } 17 | 18 | extension HADropDownDelegate { 19 | func didSelectItem(dropDown: HADropDown, at index: Int) { 20 | 21 | } 22 | func didShow(dropDown: HADropDown) { 23 | 24 | } 25 | func didHide(dropDown: HADropDown) { 26 | 27 | } 28 | } 29 | 30 | @IBDesignable 31 | class HADropDown: UIView { 32 | 33 | var delegate: HADropDownDelegate! 34 | fileprivate var label = UILabel() 35 | 36 | @IBInspectable 37 | var title : String { 38 | set { 39 | label.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) 40 | label.text = newValue 41 | } 42 | get { 43 | return label.text! 44 | } 45 | } 46 | 47 | @IBInspectable 48 | var textAllignment : NSTextAlignment { 49 | set { 50 | label.textAlignment = newValue 51 | } 52 | get { 53 | return label.textAlignment 54 | } 55 | } 56 | 57 | 58 | @IBInspectable 59 | var titleColor : UIColor { 60 | set { 61 | label.textColor = newValue 62 | } 63 | get { 64 | return label.textColor 65 | } 66 | } 67 | 68 | @IBInspectable 69 | var titleFontSize : CGFloat { 70 | set { 71 | titleFontSize1 = newValue 72 | } 73 | get { 74 | return titleFontSize1 75 | } 76 | } 77 | fileprivate var titleFontSize1 : CGFloat = 14.0 78 | 79 | 80 | @IBInspectable 81 | var itemHeight : Double { 82 | get { 83 | return itemHeight1 84 | } 85 | set { 86 | itemHeight1 = newValue 87 | } 88 | } 89 | @IBInspectable 90 | var itemBackground : UIColor { 91 | set { 92 | itemBackgroundColor = newValue 93 | } 94 | get { 95 | return itemBackgroundColor 96 | } 97 | } 98 | 99 | 100 | fileprivate var itemBackgroundColor = UIColor.white 101 | 102 | @IBInspectable 103 | var itemTextColor : UIColor { 104 | set { 105 | itemFontColor = newValue 106 | } 107 | get { 108 | return itemFontColor 109 | } 110 | } 111 | fileprivate var itemFontColor = UIColor.black 112 | 113 | fileprivate var itemHeight1 = 40.0 114 | 115 | 116 | @IBInspectable 117 | var itemFontSize : CGFloat { 118 | set { 119 | itemFontSize1 = newValue 120 | } 121 | get { 122 | return itemFontSize1 123 | } 124 | } 125 | fileprivate var itemFontSize1 : CGFloat = 14.0 126 | 127 | var itemFont = UIFont.systemFont(ofSize: 14) 128 | 129 | var font : UIFont { 130 | set { 131 | selectedFont = newValue 132 | label.font = selectedFont 133 | } 134 | get { 135 | return selectedFont 136 | } 137 | } 138 | fileprivate var selectedFont = UIFont.systemFont(ofSize: 14) 139 | 140 | var items = [String]() 141 | fileprivate var selectedIndex = -1 142 | 143 | var isCollapsed = true 144 | private var table = UITableView() 145 | 146 | var getSelectedIndex : Int { 147 | get { 148 | return selectedIndex 149 | } 150 | } 151 | 152 | private var tapGestureBackground: UITapGestureRecognizer! 153 | 154 | override func prepareForInterfaceBuilder() { 155 | label.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) 156 | font = UIFont(descriptor: font.fontDescriptor, size: titleFontSize) 157 | label.font = font 158 | self.addSubview(label) 159 | textAllignment = .center 160 | } 161 | 162 | 163 | override func layoutSubviews() { 164 | super.layoutSubviews() 165 | 166 | self.layer.cornerRadius = 4 167 | self.layer.borderColor = UIColor.gray.cgColor 168 | self.layer.borderWidth = 1 169 | 170 | label.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) 171 | self.addSubview(label) 172 | textAllignment = .center 173 | 174 | let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(gesture:))) 175 | self.addGestureRecognizer(tapGesture) 176 | table.delegate = self 177 | table.dataSource = self 178 | var rootView = self.superview 179 | 180 | // here we getting top superview to add table on that. 181 | while rootView?.superview != nil { 182 | rootView = rootView?.superview 183 | } 184 | 185 | let newFrame: CGRect = self.superview!.convert(self.frame, to: rootView) 186 | self.tableFrame = newFrame 187 | self.table.frame = CGRect(x: newFrame.origin.x, y: (newFrame.origin.y) + (newFrame.height)+5, width: (newFrame.width), height: 0) 188 | 189 | table.backgroundColor = itemBackgroundColor 190 | } 191 | // Default tableview frame 192 | var tableFrame = CGRect.zero 193 | 194 | func didTapBackground(gesture: UIGestureRecognizer) { 195 | isCollapsed = true 196 | collapseTableView() 197 | 198 | } 199 | 200 | @objc private func didTap(gesture: UIGestureRecognizer) { 201 | isCollapsed = !isCollapsed 202 | if !isCollapsed { 203 | let height : CGFloat = CGFloat(items.count > 5 ? itemHeight*5 : itemHeight*Double(items.count)) 204 | self.table.layer.zPosition = 1 205 | self.table.removeFromSuperview() 206 | self.table.layer.borderColor = UIColor.lightGray.cgColor 207 | self.table.layer.borderWidth = 1 208 | self.table.layer.cornerRadius = 4 209 | var rootView = self.superview 210 | // adding tableview to root view( we can say first view in hierarchy) 211 | while rootView?.superview != nil { 212 | rootView = rootView?.superview 213 | } 214 | 215 | rootView?.addSubview(self.table) 216 | 217 | self.table.reloadData() 218 | UIView.animate(withDuration: 0.25, animations: { 219 | self.table.frame = CGRect(x: self.tableFrame.origin.x, y: self.tableFrame.origin.y + self.frame.height+5, width: self.frame.width, height: height) 220 | 221 | }) 222 | 223 | 224 | if delegate != nil { 225 | delegate.didShow(dropDown: self) 226 | } 227 | let view = UIView(frame: UIScreen.main.bounds) 228 | view.tag = 99121 229 | rootView?.insertSubview(view, belowSubview: table) 230 | 231 | tapGestureBackground = UITapGestureRecognizer(target: self, action: #selector(didTapBackground(gesture:))) 232 | view.addGestureRecognizer(tapGestureBackground) 233 | } 234 | else { 235 | collapseTableView() 236 | } 237 | 238 | } 239 | func collapseTableView() { 240 | 241 | if isCollapsed { 242 | // removing tableview from rootview 243 | UIView.animate(withDuration: 0.25, animations: { 244 | self.table.frame = CGRect(x: self.tableFrame.origin.x, y: self.tableFrame.origin.y+self.frame.height, width: self.frame.width, height: 0) 245 | }) 246 | var rootView = self.superview 247 | 248 | while rootView?.superview != nil { 249 | rootView = rootView?.superview 250 | } 251 | 252 | rootView?.viewWithTag(99121)?.removeFromSuperview() 253 | self.superview?.viewWithTag(99121)?.removeFromSuperview() 254 | if delegate != nil { 255 | delegate.didHide(dropDown: self) 256 | } 257 | } 258 | } 259 | } 260 | extension HADropDown : UITableViewDelegate, UITableViewDataSource { 261 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 262 | return items.count 263 | } 264 | 265 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 266 | 267 | var cell = tableView.dequeueReusableCell(withIdentifier: "cell") 268 | if (cell == nil) { 269 | cell = UITableViewCell(style: .default, reuseIdentifier: "cell") 270 | } 271 | cell?.textLabel?.textAlignment = textAllignment 272 | cell?.textLabel?.text = items[indexPath.row] 273 | let font = UIFont(descriptor: itemFont.fontDescriptor, size: itemFontSize) 274 | 275 | cell?.textLabel?.font = font 276 | 277 | cell?.textLabel?.textColor = itemTextColor 278 | 279 | if indexPath.row == selectedIndex { 280 | cell?.accessoryType = .checkmark 281 | } 282 | else { 283 | cell?.accessoryType = .none 284 | } 285 | 286 | cell?.backgroundColor = itemBackgroundColor 287 | 288 | cell?.tintColor = self.tintColor 289 | 290 | return cell! 291 | } 292 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 293 | return CGFloat(itemHeight) 294 | } 295 | 296 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 297 | selectedIndex = indexPath.row 298 | label.text = items[selectedIndex] 299 | isCollapsed = true 300 | collapseTableView() 301 | if delegate != nil { 302 | delegate.didSelectItem(dropDown: self, at: selectedIndex) 303 | } 304 | } 305 | func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { 306 | return UIView() 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /HADropDown/HADropDown/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /HADropDown/HADropDown/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // MyDropDown 4 | // 5 | // Created by Hassan Aftab on 22/02/2017. 6 | // Copyright © 2017 Hassan Aftab. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | @IBOutlet weak var dropDown: HADropDown! 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | dropDown.items = ["Cat", "Mouse", "Horse", "Elephant", "Dog", "Zebra"] 17 | 18 | } 19 | 20 | override func didReceiveMemoryWarning() { 21 | super.didReceiveMemoryWarning() 22 | // Dispose of any resources that can be recreated. 23 | } 24 | 25 | 26 | } 27 | 28 | extension ViewController: HADropDownDelegate { 29 | func didSelectItem(dropDown: HADropDown, at index: Int) { 30 | print("Item selected at index \(index)") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf810 2 | {\fonttbl\f0\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;\red74\green70\blue67;\red255\green255\blue255;} 4 | {\*\expandedcolortbl;;\cssrgb\c36078\c34510\c33333;\cssrgb\c100000\c100000\c100000;} 5 | \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0 6 | \deftab720 7 | \pard\pardeftab720\partightenfactor0 8 | 9 | \f0\fs28 \cf2 \cb3 \expnd0\expndtw0\kerning0 10 | MIT License\ 11 | \ 12 | Copyright (c) 2017 Hassan Aftab\ 13 | \ 14 | Permission is hereby granted, free of charge, to any person obtaining a copy\ 15 | of this software and associated documentation files (the "Software"), to deal\ 16 | in the Software without restriction, including without limitation the rights\ 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ 18 | copies of the Software, and to permit persons to whom the Software is\ 19 | furnished to do so, subject to the following conditions:\ 20 | \ 21 | The above copyright notice and this permission notice shall be included in all\ 22 | copies or substantial portions of the Software.\ 23 | \ 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\ 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\ 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\ 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\ 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\ 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\ 30 | SOFTWARE.} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HADropDown 2 | HADropDown is a simple iOS drop down list written in Swift. It expands and collapses. It allows the user to select only one item at a time. Items are just Strings. A delegate is notified when selection occurs. HADropDown is IBDesignable and IBInspectable with customizable colors, font, and row heights. 3 | ![Alt text](https://github.com/Hassan-Aftab/HADropDown/blob/master/Simulator%20Screen%20Shot?raw=true "Demo") 4 | 5 | Simply include HADropDown.swift in your project. HADropDown requires Swift 3. 6 | # Usage 7 | 8 | Create a HADropDown in IB or in code (using UIView's init methods). Then add items and set a delegate: 9 | 10 | dropDown.items = ["hello", "goodbye", "why?"] 11 | dropDown.delegate = self 12 | You can also implement HADropDownDelegate to get notified when an item is selected: 13 | 14 | ```javascript 15 | func didSelectItem(dropDown: HADropDown, at index: Int) { 16 | print("Item selected at index \(index)") 17 | } 18 | ``` 19 | The delegate can also optionally implement the method 20 | ```javascript 21 | func didShow(dropDown: HADropDown) 22 | func didHide(dropDown: HADropDown) 23 | ``` 24 | to be notified when the collapse status of the menu changes. 25 | 26 | Items can be added or removed 27 | 28 | All properties can be manually modified. 29 | 30 | # License and Authorship 31 | 32 | Released under the MIT License. Copyright 2017-2018 Hassan Aftab. Please open issues on GitHub. 33 | -------------------------------------------------------------------------------- /Simulator Screen Shot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hassan-Aftab/HADropDown/90eee93458d33f9956e51512f976b4fab1a96d2e/Simulator Screen Shot --------------------------------------------------------------------------------