├── .gitignore ├── Demo └── STCollapseTableViewDemo │ ├── STCollapseTableViewDemo.xcodeproj │ └── project.pbxproj │ └── STCollapseTableViewDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Default-568h@2x.png │ ├── Default.png │ ├── Default@2x.png │ ├── STCollapseTableViewDemo-Info.plist │ ├── STCollapseTableViewDemo-Prefix.pch │ ├── ViewController.h │ ├── ViewController.m │ ├── en.lproj │ ├── InfoPlist.strings │ └── ViewController.xib │ └── main.m ├── LICENSE ├── README.md └── STCollapseTableView ├── STCollapseTableView.h └── STCollapseTableView.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9A519E7C17B5006A00B5C3AD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A519E7B17B5006A00B5C3AD /* UIKit.framework */; }; 11 | 9A519E7E17B5006A00B5C3AD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A519E7D17B5006A00B5C3AD /* Foundation.framework */; }; 12 | 9A519E8017B5006A00B5C3AD /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A519E7F17B5006A00B5C3AD /* CoreGraphics.framework */; }; 13 | 9A519E8617B5006A00B5C3AD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9A519E8417B5006A00B5C3AD /* InfoPlist.strings */; }; 14 | 9A519E8817B5006A00B5C3AD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A519E8717B5006A00B5C3AD /* main.m */; }; 15 | 9A519E8C17B5006A00B5C3AD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A519E8B17B5006A00B5C3AD /* AppDelegate.m */; }; 16 | 9A519E8E17B5006A00B5C3AD /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A519E8D17B5006A00B5C3AD /* Default.png */; }; 17 | 9A519E9017B5006A00B5C3AD /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A519E8F17B5006A00B5C3AD /* Default@2x.png */; }; 18 | 9A519E9217B5006A00B5C3AD /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9A519E9117B5006A00B5C3AD /* Default-568h@2x.png */; }; 19 | 9A519E9517B5006A00B5C3AD /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A519E9417B5006A00B5C3AD /* ViewController.m */; }; 20 | 9A519E9817B5006A00B5C3AD /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9A519E9617B5006A00B5C3AD /* ViewController.xib */; }; 21 | 9A519EA117B5008500B5C3AD /* STCollapseTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A519EA017B5008500B5C3AD /* STCollapseTableView.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | 9A519E7817B5006A00B5C3AD /* STCollapseTableViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STCollapseTableViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 9A519E7B17B5006A00B5C3AD /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 27 | 9A519E7D17B5006A00B5C3AD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | 9A519E7F17B5006A00B5C3AD /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29 | 9A519E8317B5006A00B5C3AD /* STCollapseTableViewDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "STCollapseTableViewDemo-Info.plist"; sourceTree = ""; }; 30 | 9A519E8517B5006A00B5C3AD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 31 | 9A519E8717B5006A00B5C3AD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | 9A519E8917B5006A00B5C3AD /* STCollapseTableViewDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "STCollapseTableViewDemo-Prefix.pch"; sourceTree = ""; }; 33 | 9A519E8A17B5006A00B5C3AD /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 34 | 9A519E8B17B5006A00B5C3AD /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 35 | 9A519E8D17B5006A00B5C3AD /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 36 | 9A519E8F17B5006A00B5C3AD /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 37 | 9A519E9117B5006A00B5C3AD /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 38 | 9A519E9317B5006A00B5C3AD /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 39 | 9A519E9417B5006A00B5C3AD /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 40 | 9A519E9717B5006A00B5C3AD /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 41 | 9A519E9F17B5008500B5C3AD /* STCollapseTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STCollapseTableView.h; sourceTree = ""; }; 42 | 9A519EA017B5008500B5C3AD /* STCollapseTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STCollapseTableView.m; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | 9A519E7517B5006A00B5C3AD /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | 9A519E7C17B5006A00B5C3AD /* UIKit.framework in Frameworks */, 51 | 9A519E7E17B5006A00B5C3AD /* Foundation.framework in Frameworks */, 52 | 9A519E8017B5006A00B5C3AD /* CoreGraphics.framework in Frameworks */, 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | 9A519E6F17B5006A00B5C3AD = { 60 | isa = PBXGroup; 61 | children = ( 62 | 9A519E9E17B5008500B5C3AD /* STCollapseTableView */, 63 | 9A519E8117B5006A00B5C3AD /* STCollapseTableViewDemo */, 64 | 9A519E7A17B5006A00B5C3AD /* Frameworks */, 65 | 9A519E7917B5006A00B5C3AD /* Products */, 66 | ); 67 | sourceTree = ""; 68 | }; 69 | 9A519E7917B5006A00B5C3AD /* Products */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9A519E7817B5006A00B5C3AD /* STCollapseTableViewDemo.app */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 9A519E7A17B5006A00B5C3AD /* Frameworks */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 9A519E7B17B5006A00B5C3AD /* UIKit.framework */, 81 | 9A519E7D17B5006A00B5C3AD /* Foundation.framework */, 82 | 9A519E7F17B5006A00B5C3AD /* CoreGraphics.framework */, 83 | ); 84 | name = Frameworks; 85 | sourceTree = ""; 86 | }; 87 | 9A519E8117B5006A00B5C3AD /* STCollapseTableViewDemo */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 9A519E8A17B5006A00B5C3AD /* AppDelegate.h */, 91 | 9A519E8B17B5006A00B5C3AD /* AppDelegate.m */, 92 | 9A519E9317B5006A00B5C3AD /* ViewController.h */, 93 | 9A519E9417B5006A00B5C3AD /* ViewController.m */, 94 | 9A519E9617B5006A00B5C3AD /* ViewController.xib */, 95 | 9A519E8217B5006A00B5C3AD /* Supporting Files */, 96 | ); 97 | path = STCollapseTableViewDemo; 98 | sourceTree = ""; 99 | }; 100 | 9A519E8217B5006A00B5C3AD /* Supporting Files */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 9A519E8317B5006A00B5C3AD /* STCollapseTableViewDemo-Info.plist */, 104 | 9A519E8417B5006A00B5C3AD /* InfoPlist.strings */, 105 | 9A519E8717B5006A00B5C3AD /* main.m */, 106 | 9A519E8917B5006A00B5C3AD /* STCollapseTableViewDemo-Prefix.pch */, 107 | 9A519E8D17B5006A00B5C3AD /* Default.png */, 108 | 9A519E8F17B5006A00B5C3AD /* Default@2x.png */, 109 | 9A519E9117B5006A00B5C3AD /* Default-568h@2x.png */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | 9A519E9E17B5008500B5C3AD /* STCollapseTableView */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 9A519E9F17B5008500B5C3AD /* STCollapseTableView.h */, 118 | 9A519EA017B5008500B5C3AD /* STCollapseTableView.m */, 119 | ); 120 | name = STCollapseTableView; 121 | path = ../../STCollapseTableView; 122 | sourceTree = ""; 123 | }; 124 | /* End PBXGroup section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 9A519E7717B5006A00B5C3AD /* STCollapseTableViewDemo */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 9A519E9B17B5006A00B5C3AD /* Build configuration list for PBXNativeTarget "STCollapseTableViewDemo" */; 130 | buildPhases = ( 131 | 9A519E7417B5006A00B5C3AD /* Sources */, 132 | 9A519E7517B5006A00B5C3AD /* Frameworks */, 133 | 9A519E7617B5006A00B5C3AD /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | ); 139 | name = STCollapseTableViewDemo; 140 | productName = STCollapseTableViewDemo; 141 | productReference = 9A519E7817B5006A00B5C3AD /* STCollapseTableViewDemo.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 9A519E7017B5006A00B5C3AD /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastUpgradeCheck = 0460; 151 | ORGANIZATIONNAME = iSofTom; 152 | }; 153 | buildConfigurationList = 9A519E7317B5006A00B5C3AD /* Build configuration list for PBXProject "STCollapseTableViewDemo" */; 154 | compatibilityVersion = "Xcode 3.2"; 155 | developmentRegion = English; 156 | hasScannedForEncodings = 0; 157 | knownRegions = ( 158 | en, 159 | ); 160 | mainGroup = 9A519E6F17B5006A00B5C3AD; 161 | productRefGroup = 9A519E7917B5006A00B5C3AD /* Products */; 162 | projectDirPath = ""; 163 | projectRoot = ""; 164 | targets = ( 165 | 9A519E7717B5006A00B5C3AD /* STCollapseTableViewDemo */, 166 | ); 167 | }; 168 | /* End PBXProject section */ 169 | 170 | /* Begin PBXResourcesBuildPhase section */ 171 | 9A519E7617B5006A00B5C3AD /* Resources */ = { 172 | isa = PBXResourcesBuildPhase; 173 | buildActionMask = 2147483647; 174 | files = ( 175 | 9A519E8617B5006A00B5C3AD /* InfoPlist.strings in Resources */, 176 | 9A519E8E17B5006A00B5C3AD /* Default.png in Resources */, 177 | 9A519E9017B5006A00B5C3AD /* Default@2x.png in Resources */, 178 | 9A519E9217B5006A00B5C3AD /* Default-568h@2x.png in Resources */, 179 | 9A519E9817B5006A00B5C3AD /* ViewController.xib in Resources */, 180 | ); 181 | runOnlyForDeploymentPostprocessing = 0; 182 | }; 183 | /* End PBXResourcesBuildPhase section */ 184 | 185 | /* Begin PBXSourcesBuildPhase section */ 186 | 9A519E7417B5006A00B5C3AD /* Sources */ = { 187 | isa = PBXSourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 9A519E8817B5006A00B5C3AD /* main.m in Sources */, 191 | 9A519E8C17B5006A00B5C3AD /* AppDelegate.m in Sources */, 192 | 9A519E9517B5006A00B5C3AD /* ViewController.m in Sources */, 193 | 9A519EA117B5008500B5C3AD /* STCollapseTableView.m in Sources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXSourcesBuildPhase section */ 198 | 199 | /* Begin PBXVariantGroup section */ 200 | 9A519E8417B5006A00B5C3AD /* InfoPlist.strings */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 9A519E8517B5006A00B5C3AD /* en */, 204 | ); 205 | name = InfoPlist.strings; 206 | sourceTree = ""; 207 | }; 208 | 9A519E9617B5006A00B5C3AD /* ViewController.xib */ = { 209 | isa = PBXVariantGroup; 210 | children = ( 211 | 9A519E9717B5006A00B5C3AD /* en */, 212 | ); 213 | name = ViewController.xib; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXVariantGroup section */ 217 | 218 | /* Begin XCBuildConfiguration section */ 219 | 9A519E9917B5006A00B5C3AD /* Debug */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | ALWAYS_SEARCH_USER_PATHS = NO; 223 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 224 | CLANG_CXX_LIBRARY = "libc++"; 225 | CLANG_ENABLE_OBJC_ARC = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_EMPTY_BODY = YES; 228 | CLANG_WARN_ENUM_CONVERSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 232 | COPY_PHASE_STRIP = NO; 233 | GCC_C_LANGUAGE_STANDARD = gnu99; 234 | GCC_DYNAMIC_NO_PIC = NO; 235 | GCC_OPTIMIZATION_LEVEL = 0; 236 | GCC_PREPROCESSOR_DEFINITIONS = ( 237 | "DEBUG=1", 238 | "$(inherited)", 239 | ); 240 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 243 | GCC_WARN_UNUSED_VARIABLE = YES; 244 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 245 | ONLY_ACTIVE_ARCH = YES; 246 | SDKROOT = iphoneos; 247 | }; 248 | name = Debug; 249 | }; 250 | 9A519E9A17B5006A00B5C3AD /* Release */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_CONSTANT_CONVERSION = YES; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INT_CONVERSION = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 267 | GCC_WARN_UNUSED_VARIABLE = YES; 268 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 269 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 270 | SDKROOT = iphoneos; 271 | VALIDATE_PRODUCT = YES; 272 | }; 273 | name = Release; 274 | }; 275 | 9A519E9C17B5006A00B5C3AD /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 279 | GCC_PREFIX_HEADER = "STCollapseTableViewDemo/STCollapseTableViewDemo-Prefix.pch"; 280 | INFOPLIST_FILE = "STCollapseTableViewDemo/STCollapseTableViewDemo-Info.plist"; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | WRAPPER_EXTENSION = app; 283 | }; 284 | name = Debug; 285 | }; 286 | 9A519E9D17B5006A00B5C3AD /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 290 | GCC_PREFIX_HEADER = "STCollapseTableViewDemo/STCollapseTableViewDemo-Prefix.pch"; 291 | INFOPLIST_FILE = "STCollapseTableViewDemo/STCollapseTableViewDemo-Info.plist"; 292 | PRODUCT_NAME = "$(TARGET_NAME)"; 293 | WRAPPER_EXTENSION = app; 294 | }; 295 | name = Release; 296 | }; 297 | /* End XCBuildConfiguration section */ 298 | 299 | /* Begin XCConfigurationList section */ 300 | 9A519E7317B5006A00B5C3AD /* Build configuration list for PBXProject "STCollapseTableViewDemo" */ = { 301 | isa = XCConfigurationList; 302 | buildConfigurations = ( 303 | 9A519E9917B5006A00B5C3AD /* Debug */, 304 | 9A519E9A17B5006A00B5C3AD /* Release */, 305 | ); 306 | defaultConfigurationIsVisible = 0; 307 | defaultConfigurationName = Release; 308 | }; 309 | 9A519E9B17B5006A00B5C3AD /* Build configuration list for PBXNativeTarget "STCollapseTableViewDemo" */ = { 310 | isa = XCConfigurationList; 311 | buildConfigurations = ( 312 | 9A519E9C17B5006A00B5C3AD /* Debug */, 313 | 9A519E9D17B5006A00B5C3AD /* Release */, 314 | ); 315 | defaultConfigurationIsVisible = 0; 316 | defaultConfigurationName = Release; 317 | }; 318 | /* End XCConfigurationList section */ 319 | }; 320 | rootObject = 9A519E7017B5006A00B5C3AD /* Project object */; 321 | } 322 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // STCollapseTableViewDemo 4 | // 5 | // Created by Thomas Dupont on 09/08/13. 6 | // Copyright (c) 2013 iSofTom. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // STCollapseTableViewDemo 4 | // 5 | // Created by Thomas Dupont on 09/08/13. 6 | // Copyright (c) 2013 iSofTom. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @implementation AppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | // Override point for customization after application launch. 19 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 20 | self.window.rootViewController = self.viewController; 21 | [self.window makeKeyAndVisible]; 22 | return YES; 23 | } 24 | 25 | - (void)applicationWillResignActive:(UIApplication *)application 26 | { 27 | // 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. 28 | // 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. 29 | } 30 | 31 | - (void)applicationDidEnterBackground:(UIApplication *)application 32 | { 33 | // 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. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | - (void)applicationWillEnterForeground:(UIApplication *)application 38 | { 39 | // 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. 40 | } 41 | 42 | - (void)applicationDidBecomeActive:(UIApplication *)application 43 | { 44 | // 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. 45 | } 46 | 47 | - (void)applicationWillTerminate:(UIApplication *)application 48 | { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSofTom/STCollapseTableView/4a077f893c44ee9e63fdda8ae6f4de73b81e40ae/Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/Default-568h@2x.png -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSofTom/STCollapseTableView/4a077f893c44ee9e63fdda8ae6f4de73b81e40ae/Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/Default.png -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iSofTom/STCollapseTableView/4a077f893c44ee9e63fdda8ae6f4de73b81e40ae/Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/Default@2x.png -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/STCollapseTableViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.isoftom.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/STCollapseTableViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'STCollapseTableViewDemo' target in the 'STCollapseTableViewDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // STCollapseTableViewDemo 4 | // 5 | // Created by Thomas Dupont on 09/08/13. 6 | // Copyright (c) 2013 iSofTom. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // STCollapseTableViewDemo 4 | // 5 | // Created by Thomas Dupont on 09/08/13. 6 | // Copyright (c) 2013 iSofTom. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "STCollapseTableView.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet STCollapseTableView *tableView; 16 | 17 | @property (nonatomic, strong) NSMutableArray* data; 18 | @property (nonatomic, strong) NSMutableArray* headers; 19 | 20 | @end 21 | 22 | @implementation ViewController 23 | 24 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 25 | { 26 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 27 | if (self) 28 | { 29 | [self setupViewController]; 30 | } 31 | return self; 32 | } 33 | 34 | - (id)initWithCoder:(NSCoder *)aDecoder 35 | { 36 | self = [super initWithCoder:aDecoder]; 37 | if (self) 38 | { 39 | [self setupViewController]; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)setupViewController 45 | { 46 | NSArray* colors = @[[UIColor redColor], 47 | [UIColor orangeColor], 48 | [UIColor yellowColor], 49 | [UIColor greenColor], 50 | [UIColor blueColor], 51 | [UIColor purpleColor]]; 52 | 53 | self.data = [[NSMutableArray alloc] init]; 54 | for (int i = 0 ; i < [colors count] ; i++) 55 | { 56 | NSMutableArray* section = [[NSMutableArray alloc] init]; 57 | for (int j = 0 ; j < 3 ; j++) 58 | { 59 | [section addObject:[NSString stringWithFormat:@"Cell n°%i", j]]; 60 | } 61 | [self.data addObject:section]; 62 | } 63 | 64 | self.headers = [[NSMutableArray alloc] init]; 65 | for (int i = 0 ; i < [colors count] ; i++) 66 | { 67 | UIView* header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 40)]; 68 | [header setBackgroundColor:[colors objectAtIndex:i]]; 69 | [self.headers addObject:header]; 70 | } 71 | } 72 | 73 | - (void)viewDidLoad 74 | { 75 | [super viewDidLoad]; 76 | 77 | [self.tableView reloadData]; 78 | [self.tableView openSection:0 animated:NO]; 79 | } 80 | 81 | - (IBAction)handleExclusiveButtonTap:(UIButton*)button 82 | { 83 | [self.tableView setExclusiveSections:!self.tableView.exclusiveSections]; 84 | 85 | [button setTitle:self.tableView.exclusiveSections?@"exclusive":@"!exclusive" forState:UIControlStateNormal]; 86 | } 87 | 88 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 89 | { 90 | return [self.data count]; 91 | } 92 | 93 | - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 94 | { 95 | static NSString* cellIdentifier = @"cell"; 96 | 97 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 98 | 99 | if (!cell) 100 | { 101 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; 102 | } 103 | 104 | NSString* text = [[self.data objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]; 105 | cell.textLabel.text = text; 106 | 107 | return cell; 108 | } 109 | 110 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 111 | { 112 | return [[self.data objectAtIndex:section] count]; 113 | } 114 | 115 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 116 | { 117 | return 40; 118 | } 119 | 120 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 121 | { 122 | return [self.headers objectAtIndex:section]; 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/en.lproj/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12E55 6 | 3084 7 | 1187.39 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUIButton 17 | IBUITableView 18 | IBUIView 19 | 20 | 21 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 22 | 23 | 24 | PluginDependencyRecalculationVersion 25 | 26 | 27 | 28 | 29 | IBFilesOwner 30 | IBCocoaTouchFramework 31 | 32 | 33 | IBFirstResponder 34 | IBCocoaTouchFramework 35 | 36 | 37 | 38 | 274 39 | 40 | 41 | 42 | 274 43 | {320, 474} 44 | 45 | 46 | _NS:9 47 | 48 | 3 49 | MQA 50 | 51 | YES 52 | IBCocoaTouchFramework 53 | YES 54 | 1 55 | 0 56 | YES 57 | 44 58 | 22 59 | 22 60 | 61 | 62 | 63 | 292 64 | {{20, 490}, {280, 44}} 65 | 66 | 67 | _NS:9 68 | NO 69 | IBCocoaTouchFramework 70 | 0 71 | 0 72 | 1 73 | exclusive 74 | 75 | 76 | 1 77 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 78 | 79 | 80 | 3 81 | MC41AA 82 | 83 | 84 | 2 85 | 15 86 | 87 | 88 | Helvetica-Bold 89 | 15 90 | 16 91 | 92 | 93 | 94 | {{0, 20}, {320, 548}} 95 | 96 | 97 | 98 | 99 | 3 100 | MC43NQA 101 | 102 | 2 103 | 104 | 105 | NO 106 | 107 | 108 | IBUIScreenMetrics 109 | 110 | YES 111 | 112 | 113 | 114 | 115 | 116 | {320, 568} 117 | {568, 320} 118 | 119 | 120 | IBCocoaTouchFramework 121 | Retina 4 Full Screen 122 | 2 123 | 124 | IBCocoaTouchFramework 125 | 126 | 127 | 128 | 129 | 130 | 131 | view 132 | 133 | 134 | 135 | 7 136 | 137 | 138 | 139 | tableView 140 | 141 | 142 | 143 | 33 144 | 145 | 146 | 147 | dataSource 148 | 149 | 150 | 151 | 34 152 | 153 | 154 | 155 | delegate 156 | 157 | 158 | 159 | 35 160 | 161 | 162 | 163 | handleExclusiveButtonTap: 164 | 165 | 166 | 7 167 | 168 | 29 169 | 170 | 171 | 172 | 173 | 174 | 0 175 | 176 | 177 | 178 | 179 | 180 | -1 181 | 182 | 183 | File's Owner 184 | 185 | 186 | -2 187 | 188 | 189 | 190 | 191 | 6 192 | 193 | 194 | 195 | 196 | 197 | 6 198 | 0 199 | 200 | 6 201 | 1 202 | 203 | 20 204 | 205 | 1000 206 | 207 | 8 208 | 29 209 | 3 210 | 211 | 212 | 213 | 4 214 | 0 215 | 216 | 4 217 | 1 218 | 219 | 15 220 | 221 | 1000 222 | 223 | 3 224 | 9 225 | 3 226 | 227 | 228 | 229 | 5 230 | 0 231 | 232 | 5 233 | 1 234 | 235 | 20 236 | 237 | 1000 238 | 239 | 8 240 | 29 241 | 3 242 | 243 | 244 | 245 | 4 246 | 0 247 | 248 | 4 249 | 1 250 | 251 | 74 252 | 253 | 1000 254 | 255 | 9 256 | 40 257 | 3 258 | 259 | 260 | 261 | 5 262 | 0 263 | 264 | 5 265 | 1 266 | 267 | 0.0 268 | 269 | 1000 270 | 271 | 8 272 | 29 273 | 3 274 | 275 | 276 | 277 | 3 278 | 0 279 | 280 | 3 281 | 1 282 | 283 | 0.0 284 | 285 | 1000 286 | 287 | 9 288 | 40 289 | 3 290 | 291 | 292 | 293 | 6 294 | 0 295 | 296 | 6 297 | 1 298 | 299 | 0.0 300 | 301 | 1000 302 | 303 | 8 304 | 29 305 | 3 306 | 307 | 308 | 309 | 310 | 311 | 312 | 8 313 | 314 | 315 | 316 | 317 | 318 | 9 319 | 320 | 321 | 322 | 323 | 10 324 | 325 | 326 | 327 | 328 | 11 329 | 330 | 331 | 332 | 333 | 14 334 | 335 | 336 | 337 | 338 | 17 339 | 340 | 341 | 342 | 343 | 24 344 | 345 | 346 | 347 | 348 | 32 349 | 350 | 351 | 352 | 353 | 36 354 | 355 | 356 | 357 | 358 | 359 | 360 | ViewController 361 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 362 | UIResponder 363 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 364 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 365 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 366 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 367 | 368 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 369 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 370 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 371 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 372 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | STCollapseTableView 383 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 384 | 385 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 386 | 387 | 388 | 389 | 390 | 391 | 36 392 | 393 | 394 | 395 | 396 | NSLayoutConstraint 397 | NSObject 398 | 399 | IBProjectSource 400 | ./Classes/NSLayoutConstraint.h 401 | 402 | 403 | 404 | STCollapseTableView 405 | UITableView 406 | 407 | IBProjectSource 408 | ./Classes/STCollapseTableView.h 409 | 410 | 411 | 412 | ViewController 413 | UIViewController 414 | 415 | handleExclusiveButtonTap: 416 | UIButton 417 | 418 | 419 | handleExclusiveButtonTap: 420 | 421 | handleExclusiveButtonTap: 422 | UIButton 423 | 424 | 425 | 426 | UISwitch 427 | STCollapseTableView 428 | 429 | 430 | 431 | animatedSwitch 432 | UISwitch 433 | 434 | 435 | tableView 436 | STCollapseTableView 437 | 438 | 439 | 440 | IBProjectSource 441 | ./Classes/ViewController.h 442 | 443 | 444 | 445 | 446 | 0 447 | IBCocoaTouchFramework 448 | YES 449 | 3 450 | YES 451 | 2083 452 | 453 | 454 | -------------------------------------------------------------------------------- /Demo/STCollapseTableViewDemo/STCollapseTableViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // STCollapseTableViewDemo 4 | // 5 | // Created by Thomas Dupont on 09/08/13. 6 | // Copyright (c) 2013 iSofTom. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 iSofTom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | STCollapseTableView 2 | =============== 3 | 4 | A UITableView subclass that automatically collapse and/or expand your sections. 5 | 6 | You just have to fill your datasource like for a classic UITableView and the magic will happen. 7 | 8 | ## How to use it ? 9 | 10 | By default all the sections are closed, so no rows will be displayed ! 11 | But you have now access to several new table view methods: 12 | 13 | ``` 14 | - (void)openSection:(NSUInteger)sectionIndex animated:(BOOL)animated; 15 | - (void)closeSection:(NSUInteger)sectionIndex animated:(BOOL)animated; 16 | - (void)toggleSection:(NSUInteger)sectionIndex animated:(BOOL)animated; 17 | - (BOOL)isOpenSection:(NSUInteger)sectionIndex; 18 | ``` 19 | As their names suggests, those methods allows to open or close a section and can be animated or not. The last one returns a boolean to know if a section is currently open. 20 | 21 | so if you want the first section to be open after your view is loaded, you could write: 22 | 23 | ``` 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | 28 | [self.tableView reloadData]; 29 | [self.tableView openSection:0 animated:NO]; 30 | } 31 | ``` 32 | 33 | By default if you open a section, any other that is open will automatically be closed. 34 | This can be prevented by setting this property to NO: 35 | 36 | ``` 37 | @property (nonatomic, assign) BOOL exclusiveSections; 38 | ``` 39 | 40 | As you might have seen, your headers automatically toggle theirs section on a tap ! 41 | This is automatically done for you in three conditions: 42 | * Your datasource implements the `tableView:heightForHeaderInSection:` method 43 | * The returned views haven't any UITapGestureRecognizer. 44 | * the STCollapseTableView property `shouldHandleHeadersTap` is YES (which is the default value). 45 | 46 | ## Installation 47 | 48 | To include this component in your project, I recommend you to use [Cocoapods](http://cocoapods.org): 49 | * Add `pod "STCollapseTableView"` to your Podfile. 50 | 51 | ## How does it work ? 52 | 53 | Here is an article about how this component works : [Forwarding Mechanism](http://www.isoftom.com/2013/08/forwarding-mechanism.html). 54 | -------------------------------------------------------------------------------- /STCollapseTableView/STCollapseTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // STCollapseTableView.h 3 | // STCollapseTableView 4 | // 5 | // Created by Thomas Dupont on 07/08/13. 6 | 7 | /*********************************************************************************** 8 | * 9 | * Copyright (c) 2013 Thomas Dupont 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | * 29 | ***********************************************************************************/ 30 | 31 | #import 32 | 33 | /** 34 | * STCollapseTableView is a UITableView subclass that automatically collapse and/or expand your sections. 35 | * 36 | * Just fill your datasource like for any table view and the magic will happen. 37 | * By default all the sections are closed. 38 | */ 39 | @interface STCollapseTableView : UITableView 40 | 41 | /** 42 | * This property allow to enable/disable the exclusivity. 43 | * If YES, only one section is allowed to be open. 44 | * Default value is YES. 45 | */ 46 | @property (nonatomic, assign) BOOL exclusiveSections; 47 | 48 | /** 49 | * This property allows STCollapseTableView to automatically handle tap on headers in order to collapse or expand sections. 50 | * If NO, you'll have to manually call the open or close methods if you want any content to be displayed. 51 | * Default value is YES. 52 | */ 53 | @property (nonatomic, assign) BOOL shouldHandleHeadersTap; 54 | 55 | /** 56 | * This method will display the section whose index is in parameters 57 | * If exclusiveSections boolean is YES, this method will close any open section. 58 | * 59 | * @param sectionIndex The section you want to show. 60 | * @param animated YES if you want the opening to be animated. 61 | */ 62 | - (void)openSection:(NSUInteger)sectionIndex animated:(BOOL)animated; 63 | 64 | /** 65 | * This method will close the section whose index is in parameters. 66 | * 67 | * @param sectionIndex The section you want to close. 68 | * @param animated YES if you want the closing to be animated. 69 | */ 70 | - (void)closeSection:(NSUInteger)sectionIndex animated:(BOOL)animated; 71 | 72 | /** 73 | * The will open or close the section whose index is in parameters regarding of its current state. 74 | * 75 | * @param sectionIndex The section you want to toggle the visibility. 76 | * @param animated YES if you want the toggle to be animated. 77 | */ 78 | - (void)toggleSection:(NSUInteger)sectionIndex animated:(BOOL)animated; 79 | 80 | /** 81 | * This methods will return YES if the section whose index is in parameters is open. 82 | * 83 | * @param sectionIndex The section you want to knwo its visibility. 84 | * 85 | * @return YES if the section is open. 86 | */ 87 | - (BOOL)isOpenSection:(NSUInteger)sectionIndex; 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /STCollapseTableView/STCollapseTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // STCollapseTableView.m 3 | // STCollapseTableView 4 | // 5 | // Created by Thomas Dupont on 07/08/13. 6 | 7 | /*********************************************************************************** 8 | * 9 | * Copyright (c) 2013 Thomas Dupont 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | * 29 | ***********************************************************************************/ 30 | 31 | #import "STCollapseTableView.h" 32 | 33 | #import 34 | 35 | @interface STCollapseTableView () 36 | 37 | @property (nonatomic, assign) id collapseDataSource; 38 | @property (nonatomic, assign) id collapseDelegate; 39 | @property (nonatomic, strong) NSMutableArray* sectionsStates; 40 | 41 | @end 42 | 43 | @implementation STCollapseTableView 44 | 45 | - (id)initWithCoder:(NSCoder *)aDecoder 46 | { 47 | self = [super initWithCoder:aDecoder]; 48 | if (self) 49 | { 50 | [self setupCollapseTableView]; 51 | } 52 | return self; 53 | } 54 | 55 | - (id)initWithFrame:(CGRect)frame 56 | { 57 | self = [super initWithFrame:frame]; 58 | if (self) 59 | { 60 | [self setupCollapseTableView]; 61 | } 62 | return self; 63 | } 64 | 65 | - (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style 66 | { 67 | self = [super initWithFrame:frame style:style]; 68 | if (self) 69 | { 70 | [self setupCollapseTableView]; 71 | } 72 | return self; 73 | } 74 | 75 | - (void)setupCollapseTableView 76 | { 77 | self.exclusiveSections = YES; 78 | self.shouldHandleHeadersTap = YES; 79 | self.sectionsStates = [[NSMutableArray alloc] init]; 80 | } 81 | 82 | - (void)setDataSource:(id )newDataSource 83 | { 84 | if (newDataSource != self.collapseDataSource) 85 | { 86 | self.collapseDataSource = newDataSource; 87 | [self.sectionsStates removeAllObjects]; 88 | [super setDataSource:self.collapseDataSource?self:nil]; 89 | } 90 | } 91 | 92 | - (void)setDelegate:(id)newDelegate 93 | { 94 | if (newDelegate != self.collapseDelegate) 95 | { 96 | self.collapseDelegate = newDelegate; 97 | [super setDelegate:self.collapseDelegate?self:nil]; 98 | } 99 | } 100 | 101 | - (id)forwardingTargetForSelector:(SEL)aSelector 102 | { 103 | if ([self.collapseDataSource respondsToSelector:aSelector]) 104 | { 105 | return self.collapseDataSource; 106 | } 107 | if ([self.collapseDelegate respondsToSelector:aSelector]) 108 | { 109 | return self.collapseDelegate; 110 | } 111 | return nil; 112 | } 113 | 114 | - (BOOL)respondsToSelector:(SEL)aSelector 115 | { 116 | if (sel_isEqual(aSelector, @selector(tableView:viewForHeaderInSection:))) 117 | { 118 | return [self.collapseDelegate respondsToSelector:aSelector]; 119 | } 120 | 121 | return [super respondsToSelector:aSelector] || [self.collapseDataSource respondsToSelector:aSelector] || [self.collapseDelegate respondsToSelector:aSelector]; 122 | } 123 | 124 | - (void)openSection:(NSUInteger)sectionIndex animated:(BOOL)animated 125 | { 126 | if (sectionIndex >= [self.sectionsStates count]) 127 | { 128 | return; 129 | } 130 | 131 | if ([[self.sectionsStates objectAtIndex:sectionIndex] boolValue]) 132 | { 133 | return; 134 | } 135 | 136 | if (self.exclusiveSections) 137 | { 138 | NSUInteger openedSection = [self openedSection]; 139 | 140 | [self setSectionAtIndex:sectionIndex open:YES]; 141 | [self setSectionAtIndex:openedSection open:NO]; 142 | 143 | if(animated) 144 | { 145 | NSArray* indexPathsToInsert = [self indexPathsForRowsInSectionAtIndex:sectionIndex]; 146 | NSArray* indexPathsToDelete = [self indexPathsForRowsInSectionAtIndex:openedSection]; 147 | 148 | UITableViewRowAnimation insertAnimation; 149 | UITableViewRowAnimation deleteAnimation; 150 | 151 | if (openedSection == NSNotFound || sectionIndex < openedSection) 152 | { 153 | insertAnimation = UITableViewRowAnimationTop; 154 | deleteAnimation = UITableViewRowAnimationBottom; 155 | } 156 | else 157 | { 158 | insertAnimation = UITableViewRowAnimationBottom; 159 | deleteAnimation = UITableViewRowAnimationTop; 160 | } 161 | 162 | [self beginUpdates]; 163 | [self insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:insertAnimation]; 164 | [self deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation]; 165 | [self endUpdates]; 166 | } 167 | else 168 | { 169 | [self reloadData]; 170 | } 171 | } 172 | else 173 | { 174 | [self setSectionAtIndex:sectionIndex open:YES]; 175 | 176 | if (animated) 177 | { 178 | NSArray* indexPathsToInsert = [self indexPathsForRowsInSectionAtIndex:sectionIndex]; 179 | [self insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationTop]; 180 | } 181 | else 182 | { 183 | [self reloadData]; 184 | } 185 | } 186 | } 187 | 188 | - (void)closeSection:(NSUInteger)sectionIndex animated:(BOOL)animated 189 | { 190 | [self setSectionAtIndex:sectionIndex open:NO]; 191 | 192 | if (animated) 193 | { 194 | NSArray* indexPathsToDelete = [self indexPathsForRowsInSectionAtIndex:sectionIndex]; 195 | [self deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationTop]; 196 | } 197 | else 198 | { 199 | [self reloadData]; 200 | } 201 | } 202 | 203 | - (void)toggleSection:(NSUInteger)sectionIndex animated:(BOOL)animated 204 | { 205 | if (sectionIndex >= [self.sectionsStates count]) 206 | { 207 | return; 208 | } 209 | 210 | BOOL sectionIsOpen = [[self.sectionsStates objectAtIndex:sectionIndex] boolValue]; 211 | 212 | if (sectionIsOpen) 213 | { 214 | [self closeSection:sectionIndex animated:animated]; 215 | } 216 | else 217 | { 218 | [self openSection:sectionIndex animated:animated]; 219 | } 220 | } 221 | 222 | - (BOOL)isOpenSection:(NSUInteger)sectionIndex 223 | { 224 | if (sectionIndex >= [self.sectionsStates count]) 225 | { 226 | return NO; 227 | } 228 | return [[self.sectionsStates objectAtIndex:sectionIndex] boolValue]; 229 | } 230 | 231 | - (void)setExclusiveSections:(BOOL)exclusiveSections 232 | { 233 | _exclusiveSections = exclusiveSections; 234 | 235 | if (self.exclusiveSections) 236 | { 237 | NSInteger firstSection = NSNotFound; 238 | 239 | for (NSUInteger index = 0 ; index < [self.sectionsStates count] ; index++) 240 | { 241 | if ([[self.sectionsStates objectAtIndex:index] boolValue]) 242 | { 243 | if (firstSection == NSNotFound) 244 | { 245 | firstSection = index; 246 | } 247 | else 248 | { 249 | [self closeSection:index animated:YES]; 250 | } 251 | } 252 | } 253 | } 254 | } 255 | 256 | #pragma mark - DataSource 257 | 258 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 259 | { 260 | return [self.collapseDataSource tableView:tableView cellForRowAtIndexPath:indexPath]; 261 | } 262 | 263 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 264 | { 265 | if ([[self.sectionsStates objectAtIndex:section] boolValue]) 266 | { 267 | return [self.collapseDataSource tableView:tableView numberOfRowsInSection:section]; 268 | } 269 | return 0; 270 | } 271 | 272 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 273 | { 274 | int nbSection = [self.collapseDataSource numberOfSectionsInTableView:tableView]; 275 | 276 | while (nbSection < [self.sectionsStates count]) 277 | { 278 | [self.sectionsStates removeLastObject]; 279 | } 280 | 281 | while (nbSection > [self.sectionsStates count]) 282 | { 283 | [self.sectionsStates addObject:@NO]; 284 | } 285 | 286 | return nbSection; 287 | } 288 | 289 | #pragma mark - Delegate 290 | 291 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 292 | { 293 | UIView* view = [self.collapseDelegate tableView:tableView viewForHeaderInSection:section]; 294 | 295 | if (self.shouldHandleHeadersTap) 296 | { 297 | NSArray* gestures = view.gestureRecognizers; 298 | BOOL tapGestureFound = NO; 299 | for (UIGestureRecognizer* gesture in gestures) 300 | { 301 | if ([gesture isKindOfClass:[UITapGestureRecognizer class]]) 302 | { 303 | tapGestureFound = YES; 304 | break; 305 | } 306 | } 307 | 308 | if (!tapGestureFound) 309 | { 310 | [view setTag:section]; 311 | [view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]]; 312 | } 313 | } 314 | 315 | return view; 316 | } 317 | 318 | #pragma mark - Private methods 319 | 320 | - (void)handleTapGesture:(UITapGestureRecognizer*)tap 321 | { 322 | NSInteger index = tap.view.tag; 323 | if (index >= 0) 324 | { 325 | [self toggleSection:(NSUInteger)index animated:YES]; 326 | } 327 | } 328 | 329 | - (NSArray*)indexPathsForRowsInSectionAtIndex:(NSUInteger)sectionIndex 330 | { 331 | if (sectionIndex >= [self.sectionsStates count]) 332 | { 333 | return nil; 334 | } 335 | 336 | NSInteger numberOfRows = [self.collapseDataSource tableView:self numberOfRowsInSection:sectionIndex]; 337 | 338 | NSMutableArray* array = [[NSMutableArray alloc] init]; 339 | 340 | for (int i = 0 ; i < numberOfRows ; i++) 341 | { 342 | [array addObject:[NSIndexPath indexPathForRow:i inSection:sectionIndex]]; 343 | } 344 | 345 | return array; 346 | } 347 | 348 | - (void)setSectionAtIndex:(NSUInteger)sectionIndex open:(BOOL)open 349 | { 350 | if (sectionIndex >= [self.sectionsStates count]) 351 | { 352 | return; 353 | } 354 | 355 | [self.sectionsStates replaceObjectAtIndex:sectionIndex withObject:@(open)]; 356 | } 357 | 358 | - (NSUInteger)openedSection 359 | { 360 | if (!self.exclusiveSections) 361 | { 362 | return NSNotFound; 363 | } 364 | 365 | for (NSUInteger index = 0 ; index < [self.sectionsStates count] ; index++) 366 | { 367 | if ([[self.sectionsStates objectAtIndex:index] boolValue]) 368 | { 369 | return index; 370 | } 371 | } 372 | 373 | return NSNotFound; 374 | } 375 | 376 | @end 377 | --------------------------------------------------------------------------------