├── Expandable-TableViewCell-StackView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── xcuserdata │ │ ├── akashmalhotra.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── home.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── akashmalhotra.xcuserdatad │ └── xcschemes │ │ ├── Expandable-TableViewCell-StackView.xcscheme │ │ └── xcschememanagement.plist │ └── home.xcuserdatad │ └── xcschemes │ ├── Expandable-TableViewCell-StackView.xcscheme │ └── xcschememanagement.plist ├── Expandable-TableViewCell-StackView ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── down.imageset │ │ ├── Contents.json │ │ └── down.png │ └── up.imageset │ │ ├── Contents.json │ │ └── up.png ├── Base.lproj │ └── LaunchScreen.storyboard ├── Controller │ └── MainViewController.swift ├── Info.plist ├── Model │ ├── Constants.swift │ ├── Lyrics.swift │ └── LyricsGenerator.swift └── View │ ├── Custom Cells │ └── CustomTableViewCell.swift │ ├── LaunchScreen.storyboard │ └── Main.storyboard └── README.md /Expandable-TableViewCell-StackView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7AED18FA1D2FEE320022E96B /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AED18F31D2FEE320022E96B /* MainViewController.swift */; }; 11 | 7AED18FB1D2FEE320022E96B /* Lyrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AED18F51D2FEE320022E96B /* Lyrics.swift */; }; 12 | 7AED18FC1D2FEE320022E96B /* CustomTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AED18F81D2FEE320022E96B /* CustomTableViewCell.swift */; }; 13 | 7AED18FD1D2FEE320022E96B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7AED18F91D2FEE320022E96B /* Main.storyboard */; }; 14 | 7AED19011D2FEE8B0022E96B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AED19001D2FEE8B0022E96B /* AppDelegate.swift */; }; 15 | 7AED19031D2FEEC00022E96B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7AED19021D2FEEC00022E96B /* LaunchScreen.storyboard */; }; 16 | F449FE7C1D3143D500D0C60C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F449FE7B1D3143D500D0C60C /* Assets.xcassets */; }; 17 | F449FE7E1D314CE900D0C60C /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = F449FE7D1D314CE900D0C60C /* Constants.swift */; }; 18 | F449FE801D314E0000D0C60C /* LyricsGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F449FE7F1D314E0000D0C60C /* LyricsGenerator.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 7AED18F31D2FEE320022E96B /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; 23 | 7AED18F51D2FEE320022E96B /* Lyrics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lyrics.swift; sourceTree = ""; }; 24 | 7AED18F81D2FEE320022E96B /* CustomTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomTableViewCell.swift; sourceTree = ""; }; 25 | 7AED18F91D2FEE320022E96B /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 26 | 7AED18FE1D2FEE750022E96B /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "Expandable-TableViewCell-StackView/Info.plist"; sourceTree = SOURCE_ROOT; }; 27 | 7AED19001D2FEE8B0022E96B /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = "Expandable-TableViewCell-StackView/AppDelegate.swift"; sourceTree = SOURCE_ROOT; }; 28 | 7AED19021D2FEEC00022E96B /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 29 | 7AF6375B1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Expandable-TableViewCell-StackView.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | F449FE7B1D3143D500D0C60C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = "Expandable-TableViewCell-StackView/Assets.xcassets"; sourceTree = SOURCE_ROOT; }; 31 | F449FE7D1D314CE900D0C60C /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 32 | F449FE7F1D314E0000D0C60C /* LyricsGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LyricsGenerator.swift; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | 7AF637581D2F8D3700A547C1 /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | 7AED18F21D2FEE320022E96B /* Controller */ = { 47 | isa = PBXGroup; 48 | children = ( 49 | 7AED18F31D2FEE320022E96B /* MainViewController.swift */, 50 | ); 51 | name = Controller; 52 | path = "Expandable-TableViewCell-StackView/Controller"; 53 | sourceTree = SOURCE_ROOT; 54 | }; 55 | 7AED18F41D2FEE320022E96B /* Model */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 7AED18F51D2FEE320022E96B /* Lyrics.swift */, 59 | F449FE7D1D314CE900D0C60C /* Constants.swift */, 60 | F449FE7F1D314E0000D0C60C /* LyricsGenerator.swift */, 61 | ); 62 | name = Model; 63 | path = "Expandable-TableViewCell-StackView/Model"; 64 | sourceTree = SOURCE_ROOT; 65 | }; 66 | 7AED18F61D2FEE320022E96B /* View */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 7AED19021D2FEEC00022E96B /* LaunchScreen.storyboard */, 70 | 7AED18F71D2FEE320022E96B /* Custom Cells */, 71 | 7AED18F91D2FEE320022E96B /* Main.storyboard */, 72 | ); 73 | name = View; 74 | path = "Expandable-TableViewCell-StackView/View"; 75 | sourceTree = SOURCE_ROOT; 76 | }; 77 | 7AED18F71D2FEE320022E96B /* Custom Cells */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 7AED18F81D2FEE320022E96B /* CustomTableViewCell.swift */, 81 | ); 82 | path = "Custom Cells"; 83 | sourceTree = ""; 84 | }; 85 | 7AF637521D2F8D3700A547C1 = { 86 | isa = PBXGroup; 87 | children = ( 88 | 7AF6375D1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView */, 89 | 7AF6375C1D2F8D3700A547C1 /* Products */, 90 | ); 91 | sourceTree = ""; 92 | }; 93 | 7AF6375C1D2F8D3700A547C1 /* Products */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 7AF6375B1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView.app */, 97 | ); 98 | name = Products; 99 | sourceTree = ""; 100 | }; 101 | 7AF6375D1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 7AED18F21D2FEE320022E96B /* Controller */, 105 | 7AED18F41D2FEE320022E96B /* Model */, 106 | 7AED18F61D2FEE320022E96B /* View */, 107 | 7AED19001D2FEE8B0022E96B /* AppDelegate.swift */, 108 | 7AED18FE1D2FEE750022E96B /* Info.plist */, 109 | F449FE7B1D3143D500D0C60C /* Assets.xcassets */, 110 | ); 111 | name = "Expandable-TableViewCell-StackView"; 112 | path = "UIStackView-Inside-UITableViewCell"; 113 | sourceTree = ""; 114 | }; 115 | /* End PBXGroup section */ 116 | 117 | /* Begin PBXNativeTarget section */ 118 | 7AF6375A1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView */ = { 119 | isa = PBXNativeTarget; 120 | buildConfigurationList = 7AF6376D1D2F8D3700A547C1 /* Build configuration list for PBXNativeTarget "Expandable-TableViewCell-StackView" */; 121 | buildPhases = ( 122 | 7AF637571D2F8D3700A547C1 /* Sources */, 123 | 7AF637581D2F8D3700A547C1 /* Frameworks */, 124 | 7AF637591D2F8D3700A547C1 /* Resources */, 125 | ); 126 | buildRules = ( 127 | ); 128 | dependencies = ( 129 | ); 130 | name = "Expandable-TableViewCell-StackView"; 131 | productName = "UIStackView-Inside-UITableViewCell"; 132 | productReference = 7AF6375B1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView.app */; 133 | productType = "com.apple.product-type.application"; 134 | }; 135 | /* End PBXNativeTarget section */ 136 | 137 | /* Begin PBXProject section */ 138 | 7AF637531D2F8D3700A547C1 /* Project object */ = { 139 | isa = PBXProject; 140 | attributes = { 141 | LastSwiftUpdateCheck = 0710; 142 | LastUpgradeCheck = 0830; 143 | ORGANIZATIONNAME = "Akash Malhotra"; 144 | TargetAttributes = { 145 | 7AF6375A1D2F8D3700A547C1 = { 146 | CreatedOnToolsVersion = 7.1; 147 | LastSwiftMigration = 0830; 148 | }; 149 | }; 150 | }; 151 | buildConfigurationList = 7AF637561D2F8D3700A547C1 /* Build configuration list for PBXProject "Expandable-TableViewCell-StackView" */; 152 | compatibilityVersion = "Xcode 3.2"; 153 | developmentRegion = English; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | Base, 158 | ); 159 | mainGroup = 7AF637521D2F8D3700A547C1; 160 | productRefGroup = 7AF6375C1D2F8D3700A547C1 /* Products */; 161 | projectDirPath = ""; 162 | projectRoot = ""; 163 | targets = ( 164 | 7AF6375A1D2F8D3700A547C1 /* Expandable-TableViewCell-StackView */, 165 | ); 166 | }; 167 | /* End PBXProject section */ 168 | 169 | /* Begin PBXResourcesBuildPhase section */ 170 | 7AF637591D2F8D3700A547C1 /* Resources */ = { 171 | isa = PBXResourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 7AED19031D2FEEC00022E96B /* LaunchScreen.storyboard in Resources */, 175 | 7AED18FD1D2FEE320022E96B /* Main.storyboard in Resources */, 176 | F449FE7C1D3143D500D0C60C /* Assets.xcassets in Resources */, 177 | ); 178 | runOnlyForDeploymentPostprocessing = 0; 179 | }; 180 | /* End PBXResourcesBuildPhase section */ 181 | 182 | /* Begin PBXSourcesBuildPhase section */ 183 | 7AF637571D2F8D3700A547C1 /* Sources */ = { 184 | isa = PBXSourcesBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | F449FE7E1D314CE900D0C60C /* Constants.swift in Sources */, 188 | F449FE801D314E0000D0C60C /* LyricsGenerator.swift in Sources */, 189 | 7AED19011D2FEE8B0022E96B /* AppDelegate.swift in Sources */, 190 | 7AED18FB1D2FEE320022E96B /* Lyrics.swift in Sources */, 191 | 7AED18FC1D2FEE320022E96B /* CustomTableViewCell.swift in Sources */, 192 | 7AED18FA1D2FEE320022E96B /* MainViewController.swift in Sources */, 193 | ); 194 | runOnlyForDeploymentPostprocessing = 0; 195 | }; 196 | /* End PBXSourcesBuildPhase section */ 197 | 198 | /* Begin XCBuildConfiguration section */ 199 | 7AF6376B1D2F8D3700A547C1 /* Debug */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | ALWAYS_SEARCH_USER_PATHS = NO; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 204 | CLANG_CXX_LIBRARY = "libc++"; 205 | CLANG_ENABLE_MODULES = YES; 206 | CLANG_ENABLE_OBJC_ARC = YES; 207 | CLANG_WARN_BOOL_CONVERSION = YES; 208 | CLANG_WARN_CONSTANT_CONVERSION = YES; 209 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 210 | CLANG_WARN_EMPTY_BODY = YES; 211 | CLANG_WARN_ENUM_CONVERSION = YES; 212 | CLANG_WARN_INFINITE_RECURSION = YES; 213 | CLANG_WARN_INT_CONVERSION = YES; 214 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 215 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 216 | CLANG_WARN_UNREACHABLE_CODE = YES; 217 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 218 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 219 | COPY_PHASE_STRIP = NO; 220 | DEBUG_INFORMATION_FORMAT = dwarf; 221 | ENABLE_STRICT_OBJC_MSGSEND = YES; 222 | ENABLE_TESTABILITY = YES; 223 | GCC_C_LANGUAGE_STANDARD = gnu99; 224 | GCC_DYNAMIC_NO_PIC = NO; 225 | GCC_NO_COMMON_BLOCKS = YES; 226 | GCC_OPTIMIZATION_LEVEL = 0; 227 | GCC_PREPROCESSOR_DEFINITIONS = ( 228 | "DEBUG=1", 229 | "$(inherited)", 230 | ); 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 238 | MTL_ENABLE_DEBUG_INFO = YES; 239 | ONLY_ACTIVE_ARCH = YES; 240 | SDKROOT = iphoneos; 241 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 242 | }; 243 | name = Debug; 244 | }; 245 | 7AF6376C1D2F8D3700A547C1 /* Release */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 250 | CLANG_CXX_LIBRARY = "libc++"; 251 | CLANG_ENABLE_MODULES = YES; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_CONSTANT_CONVERSION = YES; 255 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 256 | CLANG_WARN_EMPTY_BODY = YES; 257 | CLANG_WARN_ENUM_CONVERSION = YES; 258 | CLANG_WARN_INFINITE_RECURSION = YES; 259 | CLANG_WARN_INT_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 262 | CLANG_WARN_UNREACHABLE_CODE = YES; 263 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 264 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 265 | COPY_PHASE_STRIP = NO; 266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 267 | ENABLE_NS_ASSERTIONS = NO; 268 | ENABLE_STRICT_OBJC_MSGSEND = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu99; 270 | GCC_NO_COMMON_BLOCKS = YES; 271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 273 | GCC_WARN_UNDECLARED_SELECTOR = YES; 274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 275 | GCC_WARN_UNUSED_FUNCTION = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 278 | MTL_ENABLE_DEBUG_INFO = NO; 279 | SDKROOT = iphoneos; 280 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 281 | VALIDATE_PRODUCT = YES; 282 | }; 283 | name = Release; 284 | }; 285 | 7AF6376E1D2F8D3700A547C1 /* Debug */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | INFOPLIST_FILE = "Expandable-TableViewCell-StackView/Info.plist"; 289 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 290 | PRODUCT_BUNDLE_IDENTIFIER = "com.akashvercetti.Expandable-TableViewCell-StackView"; 291 | PRODUCT_NAME = "Expandable-TableViewCell-StackView"; 292 | SWIFT_VERSION = 3.0; 293 | TARGETED_DEVICE_FAMILY = "1,2"; 294 | }; 295 | name = Debug; 296 | }; 297 | 7AF6376F1D2F8D3700A547C1 /* Release */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | INFOPLIST_FILE = "Expandable-TableViewCell-StackView/Info.plist"; 301 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 302 | PRODUCT_BUNDLE_IDENTIFIER = "com.akashvercetti.Expandable-TableViewCell-StackView"; 303 | PRODUCT_NAME = "Expandable-TableViewCell-StackView"; 304 | SWIFT_VERSION = 3.0; 305 | TARGETED_DEVICE_FAMILY = "1,2"; 306 | }; 307 | name = Release; 308 | }; 309 | /* End XCBuildConfiguration section */ 310 | 311 | /* Begin XCConfigurationList section */ 312 | 7AF637561D2F8D3700A547C1 /* Build configuration list for PBXProject "Expandable-TableViewCell-StackView" */ = { 313 | isa = XCConfigurationList; 314 | buildConfigurations = ( 315 | 7AF6376B1D2F8D3700A547C1 /* Debug */, 316 | 7AF6376C1D2F8D3700A547C1 /* Release */, 317 | ); 318 | defaultConfigurationIsVisible = 0; 319 | defaultConfigurationName = Release; 320 | }; 321 | 7AF6376D1D2F8D3700A547C1 /* Build configuration list for PBXNativeTarget "Expandable-TableViewCell-StackView" */ = { 322 | isa = XCConfigurationList; 323 | buildConfigurations = ( 324 | 7AF6376E1D2F8D3700A547C1 /* Debug */, 325 | 7AF6376F1D2F8D3700A547C1 /* Release */, 326 | ); 327 | defaultConfigurationIsVisible = 0; 328 | defaultConfigurationName = Release; 329 | }; 330 | /* End XCConfigurationList section */ 331 | }; 332 | rootObject = 7AF637531D2F8D3700A547C1 /* Project object */; 333 | } 334 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView.xcodeproj/project.xcworkspace/xcuserdata/akashmalhotra.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashvercetti/Expandable-UITableViewCell-UIStackView/f9d1b424a0899d8f70c6111bd7c671902ec5e34f/Expandable-TableViewCell-StackView.xcodeproj/project.xcworkspace/xcuserdata/akashmalhotra.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView.xcodeproj/project.xcworkspace/xcuserdata/home.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashvercetti/Expandable-UITableViewCell-UIStackView/f9d1b424a0899d8f70c6111bd7c671902ec5e34f/Expandable-TableViewCell-StackView.xcodeproj/project.xcworkspace/xcuserdata/home.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView.xcodeproj/xcuserdata/akashmalhotra.xcuserdatad/xcschemes/Expandable-TableViewCell-StackView.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 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView.xcodeproj/xcuserdata/akashmalhotra.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Expandable-TableViewCell-StackView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7AF6375A1D2F8D3700A547C1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView.xcodeproj/xcuserdata/home.xcuserdatad/xcschemes/Expandable-TableViewCell-StackView.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 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView.xcodeproj/xcuserdata/home.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Expandable-TableViewCell-StackView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 7AF6375A1D2F8D3700A547C1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Expandable-TableViewCell-StackView 4 | // 5 | // Created by Akash Malhotra on 7/8/16. 6 | // Copyright © 2016 Akash Malhotra. 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/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 | } -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Assets.xcassets/down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "down.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 | } -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Assets.xcassets/down.imageset/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashvercetti/Expandable-UITableViewCell-UIStackView/f9d1b424a0899d8f70c6111bd7c671902ec5e34f/Expandable-TableViewCell-StackView/Assets.xcassets/down.imageset/down.png -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Assets.xcassets/up.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "up.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 | } -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Assets.xcassets/up.imageset/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akashvercetti/Expandable-UITableViewCell-UIStackView/f9d1b424a0899d8f70c6111bd7c671902ec5e34f/Expandable-TableViewCell-StackView/Assets.xcassets/up.imageset/up.png -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/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 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Controller/MainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.swift 3 | // Expandable-TableViewCell-StackView 4 | // 5 | // Created by Akash Malhotra on 7/8/16. 6 | // Copyright © 2016 Akash Malhotra. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 12 | 13 | @IBOutlet weak var tableView: UITableView! 14 | 15 | var dataSource = LyricsGenerator.getLyrics() 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | setupUI() 20 | } 21 | 22 | override func didReceiveMemoryWarning() { 23 | super.didReceiveMemoryWarning() 24 | } 25 | 26 | //MARK: UI 27 | func setupUI() { 28 | tableView.estimatedRowHeight = 100 29 | tableView.rowHeight = UITableViewAutomaticDimension 30 | } 31 | 32 | //MARK: UITableViewDataSource 33 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 34 | return dataSource.count; 35 | } 36 | 37 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 38 | let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTableViewCell 39 | cell.setValues(dataSource[indexPath.row]) 40 | 41 | return cell 42 | } 43 | 44 | //MARK: UITableViewDelegate 45 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 46 | 47 | let lyrics = dataSource[indexPath.row] 48 | let lyricsShown = dataSource[indexPath.row].lyricsShown 49 | lyrics.lyricsShown = !lyricsShown 50 | 51 | tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.automatic) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIcons 10 | 11 | CFBundleIcons~ipad 12 | 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Model/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.swift 3 | // Expandable-TableViewCell-StackView 4 | // 5 | // Created by Home on 09/07/16. 6 | // Copyright © 2016 Akash Malhotra. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum LyricsSamples : String { 12 | case DIVIDE = "Crawling underneath our feet\na river running black and green\nfrom the heart of the gallows tree\nwhere the future and our fate\nwill bleed into the world below." 13 | 14 | case HEAVEN = "Before the story begins, is it such a sin\nFor me to take what's mine until the end of time\nWe were more than friends, before the story ends\nAnd I will take what's mine, create what God would never design\nOur love had been so strong for far too long\nI was weak with fear that something would go wrong\nBefore the possibilities came true\nI took all possibility from you" 15 | 16 | case MOST_LIKELY = "You say you love me\nAnd you’re thinkin’ of me\nBut you know you could be wrong\nYou say you told me\nThat you wanna hold me\nBut you know you’re not that strong\nI just can’t do what I done before\nI just can’t beg you anymore\nI’m gonna case you pass\nAnd I’ll go last\nThen time will tell just who fell\nAnd who’s been left behind\nWhen you go your way and I go mine" 17 | 18 | case IN_THE_END = "I tried so hard\nAnd got so far\nBut in the end\nIt doesn't even matter\nI had to fall\nTo lose it all\nBut in the end\nIt doesn't even matter\nOne thing, I don’t know why\nIt doesn’t even matter how hard you try\nKeep that in mind, I designed this rhyme\nTo remind myself how\nI tried so hard" 19 | 20 | case BAD_COMPANY = "A company\nAlways on the run\nA destiny\nOh it's the rising sun\nI was born\nA shotgun in my hands\nBehind the gun\nI'll make my final stand, yeah!\nAnd that's why they call me\nBad Company\nI can't deny\nBad Bad Company till the day I die\nUntil the day I die\nUntil the day I die" 21 | } 22 | 23 | enum Artists : String { 24 | case LINKIN_PARK = "Linkin Park" 25 | case FIVE_FINGER_DEATH_PUNCH = "Five Finger Death Punch" 26 | case BOB_DYLAN = "Bob Dylan" 27 | case AVENGED_SEVENFOLD = "Avenged Sevenfold" 28 | case THE_BIRTHDAY_MASSACRE = "The Birthday Massacre" 29 | } 30 | 31 | enum Songs : String { 32 | case DIVIDE = "Divide" 33 | case HEAVEN = "A Little Piece Of Heaven" 34 | case MOST_LIKELY = "Most Likely You Go Your Way and I'll go mine" 35 | case IN_THE_END = "In The End" 36 | case BAD_COMPANY = "Bad Company" 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Model/Lyrics.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Lyrics.swift 3 | // Expandable-TableViewCell-StackView 4 | // 5 | // Created by Akash Malhotra on 7/8/16. 6 | // Copyright © 2016 Akash Malhotra. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Lyrics { 12 | 13 | var artist: String? 14 | var song: String? 15 | var lyricsSample: String? 16 | var lyricsShown = false 17 | 18 | init(artist: String, song: String, lyricsSample: String) { 19 | self.artist = artist 20 | self.song = song 21 | self.lyricsSample = lyricsSample 22 | } 23 | } -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/Model/LyricsGenerator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LyricsGenerator.swift 3 | // Expandable-TableViewCell-StackView 4 | // 5 | // Created by Home on 09/07/16. 6 | // Copyright © 2016 Akash Malhotra. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class LyricsGenerator { 12 | 13 | static func getLyrics() -> [Lyrics] { 14 | var allLyrics = [Lyrics]() 15 | 16 | allLyrics.append(Lyrics(artist: Artists.THE_BIRTHDAY_MASSACRE.rawValue, song: Songs.DIVIDE.rawValue, lyricsSample: LyricsSamples.DIVIDE.rawValue)) 17 | allLyrics.append(Lyrics(artist: Artists.LINKIN_PARK.rawValue, song: Songs.IN_THE_END.rawValue, lyricsSample: LyricsSamples.IN_THE_END.rawValue)) 18 | allLyrics.append(Lyrics(artist: Artists.AVENGED_SEVENFOLD.rawValue, song: Songs.HEAVEN.rawValue, lyricsSample: LyricsSamples.HEAVEN.rawValue)) 19 | allLyrics.append(Lyrics(artist: Artists.FIVE_FINGER_DEATH_PUNCH.rawValue, song: Songs.BAD_COMPANY.rawValue, lyricsSample: LyricsSamples.BAD_COMPANY.rawValue)) 20 | allLyrics.append(Lyrics(artist: Artists.BOB_DYLAN.rawValue, song: Songs.MOST_LIKELY.rawValue, lyricsSample: LyricsSamples.MOST_LIKELY.rawValue)) 21 | 22 | return allLyrics 23 | } 24 | } -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/View/Custom Cells/CustomTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTableViewCell.swift 3 | // Expandable-TableViewCell-StackView 4 | // 5 | // Created by Akash Malhotra on 7/8/16. 6 | // Copyright © 2016 Akash Malhotra. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CustomTableViewCell: UITableViewCell { 12 | 13 | @IBOutlet weak var titleLabel : UILabel! 14 | @IBOutlet weak var subtitleLabel : UILabel! 15 | @IBOutlet weak var descriptionLabel : UILabel! 16 | @IBOutlet weak var icon : UIImageView! 17 | 18 | override func awakeFromNib() { 19 | super.awakeFromNib() 20 | // Initialization code 21 | } 22 | 23 | override func setSelected(_ selected: Bool, animated: Bool) { 24 | super.setSelected(selected, animated: animated) 25 | 26 | // Configure the view for the selected state 27 | } 28 | 29 | func setValues(_ lyrics: Lyrics) { 30 | self.titleLabel.text = lyrics.song 31 | self.subtitleLabel.text = lyrics.artist 32 | 33 | self.descriptionLabel.text = lyrics.lyricsSample 34 | let lyricsShown = lyrics.lyricsShown 35 | self.descriptionLabel.isHidden = !lyricsShown 36 | 37 | self.icon.image = lyricsShown ? UIImage(named: "up") : UIImage(named: "down") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/View/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Expandable-TableViewCell-StackView/View/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 | 46 | 53 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Expandable-UITableViewCell-UIStackView 2 | ====================================== 3 | 4 | **An expandable UITableView with dynamic cell heights using UIStackView.** 5 | 6 | ![An expandable UITableView with dynamic cell heights using UIStackView.](http://i.imgur.com/vgrWILg.gif) 7 | 8 | The UIStackView was introduced in iOS 9. It acts as a container for views, laid out horizontally or vertically. It removes the need for AutoLayout constraints in most(not all) cases. :) 9 | 10 | If you need to familiarize yourself with UIStackViews, here's Ray Wenderlich's post: 11 | https://www.raywenderlich.com/114552/uistackview-tutorial-introducing-stack-views 12 | 13 | 14 | ---------- 15 | 16 | Summary 17 | ------- 18 | **First, add a UITableView, a prototype cell, add labels, imageviews etc. inside the cell and add them to a vertical stack via the stack button at the bottom right of the storyboard like so...** 19 | 20 | ![add a UITableView, a prototype cell, add labels, imageviews etc. inside the cell and add them to a vertical stack via the stack button at the bottom right ](http://i.imgur.com/Hcv8gHe.png) 21 | 22 | 23 | ---------- 24 | 25 | **IMPORTANT: Make sure you add constraints to the UIStackView with respect to the cell's contentView, or else the dynamic height for cells won't work!** 26 | 27 | **Next, populate the cells via** `cellForRowAtIndexPath` 28 | 29 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 30 | let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! CustomTableViewCell 31 | cell.setValues(dataSource[indexPath.row]) 32 | 33 | return cell 34 | } 35 | func setValues(lyrics: Lyrics) { 36 | self.titleLabel.text = lyrics.song 37 | self.subtitleLabel.text = lyrics.artist 38 | 39 | self.descriptionLabel.text = lyrics.lyricsSample 40 | let lyricsShown = lyrics.lyricsShown 41 | self.descriptionLabel.hidden = !lyricsShown 42 | 43 | self.icon.image = lyricsShown ? UIImage(named: "up") : UIImage(named: "down") 44 | } 45 | 46 | 47 | ---------- 48 | 49 | 50 | **^^^Notice the part inside `setValues()`where the description label is hidden based on a Boolean flag, that's where the magic happens. Now implement the cell press like so...** 51 | 52 | func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 53 | 54 | let lyrics = dataSource[indexPath.row] 55 | let lyricsShown = dataSource[indexPath.row].lyricsShown 56 | lyrics.lyricsShown = !lyricsShown 57 | 58 | tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) 59 | } 60 | 61 | 62 | ---------- 63 | 64 | **^^^The Boolean flag which hides/shows the description label is inversed on a cell tap, followed by the table reloading the concerned row. The stackview automatically adjusts its height based on the visibility of its subviews. Speaking of heights...** 65 | **Make sure you add these two bad boys inside `viewDidLoad`** 66 | 67 | //Any non zero value works 68 | tableView.estimatedRowHeight = 100 tableView.rowHeight = UITableViewAutomaticDimension 69 | 70 | **^^^This will take care of the dynamic cell height.** 71 | 72 | --------------------------------------------------------------------------------