Permalink
Browse files

Added Example for Expanding/Collapsing TableView Sections

  • Loading branch information...
odrobnik committed Mar 12, 2013
1 parent c3de2c8 commit e09682a06de7645946789c4930ce6ea760c2cf9f

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,19 @@
+//
+// AppDelegate.h
+// ExpandableTableCells
+//
+// Created by Oliver Drobnik on 12.03.13.
+// Copyright (c) 2013 Drobnik KG. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@class UITableViewControllerWithExpandoSection;
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@property (strong, nonatomic) UITableViewControllerWithExpandoSection *viewController;
+
+@end
@@ -0,0 +1,52 @@
+//
+// AppDelegate.m
+// ExpandableTableCells
+//
+// Created by Oliver Drobnik on 12.03.13.
+// Copyright (c) 2013 Drobnik KG. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+#import "UITableViewControllerWithExpandoSection.h"
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ // Override point for customization after application launch.
+ self.viewController = [[UITableViewControllerWithExpandoSection alloc] initWithStyle:UITableViewStyleGrouped];
+ self.window.rootViewController = self.viewController;
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ // 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.
+ // 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.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ // 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.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ // 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.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ // 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.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>drobnik.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
@@ -0,0 +1,14 @@
+//
+// Prefix header for all source files of the 'ExpandableTableCells' target in the 'ExpandableTableCells' project
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_4_0
+#warning "This project uses features only available in iOS SDK 4.0 and later."
+#endif
+
+#ifdef __OBJC__
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+#endif
@@ -0,0 +1,16 @@
+//
+// UITableViewControllerWithExpandoSection.h
+// ExpandableTableCells
+//
+// Created by Oliver Drobnik on 12.03.13.
+// Copyright (c) 2013 Drobnik KG. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UITableViewControllerWithExpandoSection : UITableViewController
+{
+ NSMutableIndexSet *expandedSections;
+}
+
+@end
@@ -0,0 +1,220 @@
+//
+// UITableViewControllerWithExpandoSection.m
+// ExpandableTableCells
+//
+// Created by Oliver Drobnik on 12.03.13.
+// Copyright (c) 2013 Drobnik KG. All rights reserved.
+//
+
+#import "UITableViewControllerWithExpandoSection.h"
+#import "DTCustomColoredAccessory.h"
+
+@interface UITableViewControllerWithExpandoSection ()
+
+@end
+
+@implementation UITableViewControllerWithExpandoSection
+
+- (id)initWithStyle:(UITableViewStyle)style
+{
+ self = [super initWithStyle:style];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ if (!expandedSections)
+ {
+ expandedSections = [[NSMutableIndexSet alloc] init];
+ }
+}
+
+- (void)didReceiveMemoryWarning
+{
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+#pragma mark - Expanding
+
+- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
+{
+ if (section>0) return YES;
+
+ return NO;
+}
+
+
+#pragma mark - Table view data source
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+ return 3;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ if ([self tableView:tableView canCollapseSection:section])
+ {
+ if ([expandedSections containsIndex:section])
+ {
+ return 5; // return rows when expanded
+ }
+
+ return 1; // only top row showing
+ }
+
+ // Return the number of rows in the section.
+ return 1;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ static NSString *CellIdentifier = @"Cell";
+
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (cell == nil) {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
+ }
+
+ // Configure the cell...
+
+ if ([self tableView:tableView canCollapseSection:indexPath.section])
+ {
+ if (!indexPath.row)
+ {
+ // first row
+ cell.textLabel.text = @"Expandable"; // only top row showing
+
+ if ([expandedSections containsIndex:indexPath.section])
+ {
+ cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
+ }
+ else
+ {
+ cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown];
+ }
+ }
+ else
+ {
+ // all other rows
+ cell.textLabel.text = @"Some Detail";
+ cell.accessoryView = nil;
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+ }
+ }
+ else
+ {
+ cell.accessoryView = nil;
+ cell.textLabel.text = @"Normal Cell";
+
+ }
+
+ return cell;
+}
+
+/*
+// Override to support conditional editing of the table view.
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ // Return NO if you do not want the specified item to be editable.
+ return YES;
+}
+*/
+
+/*
+// Override to support editing the table view.
+- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ if (editingStyle == UITableViewCellEditingStyleDelete) {
+ // Delete the row from the data source
+ [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
+ }
+ else if (editingStyle == UITableViewCellEditingStyleInsert) {
+ // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
+ }
+}
+*/
+
+/*
+// Override to support rearranging the table view.
+- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
+{
+}
+*/
+
+/*
+// Override to support conditional rearranging of the table view.
+- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ // Return NO if you do not want the item to be re-orderable.
+ return YES;
+}
+*/
+
+#pragma mark - Table view delegate
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ if ([self tableView:tableView canCollapseSection:indexPath.section])
+ {
+ if (!indexPath.row)
+ {
+ [self.tableView beginUpdates];
+
+ // only first row toggles exapand/collapse
+ [tableView deselectRowAtIndexPath:indexPath animated:YES];
+
+ NSInteger section = indexPath.section;
+ BOOL currentlyExpanded = [expandedSections containsIndex:section];
+ NSInteger rows;
+
+ NSMutableArray *tmpArray = [NSMutableArray array];
+
+ if (currentlyExpanded)
+ {
+ rows = [self tableView:tableView numberOfRowsInSection:section];
+ [expandedSections removeIndex:section];
+
+ }
+ else
+ {
+ [expandedSections addIndex:section];
+ rows = [self tableView:tableView numberOfRowsInSection:section];
+ }
+
+ for (int i=1; i<rows; i++)
+ {
+ NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
+ [tmpArray addObject:tmpIndexPath];
+ }
+
+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
+
+ if (currentlyExpanded)
+ {
+ [tableView deleteRowsAtIndexPaths:tmpArray
+ withRowAnimation:UITableViewRowAnimationTop];
+
+ cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeDown];
+
+ }
+ else
+ {
+ [tableView insertRowsAtIndexPaths:tmpArray
+ withRowAnimation:UITableViewRowAnimationTop];
+ cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:DTCustomColoredAccessoryTypeUp];
+
+ }
+
+ [self.tableView endUpdates];
+ }
+ }
+}
+
+@end
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
@@ -0,0 +1,18 @@
+//
+// main.m
+// ExpandableTableCells
+//
+// Created by Oliver Drobnik on 12.03.13.
+// Copyright (c) 2013 Drobnik KG. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
View
@@ -17,6 +17,7 @@ Contents:
- [Cubed CoreAnimation Conundrum](http://bitly.com/NqcE6n)
- [Containing ViewControllers](http://j.mp/HFu8K5)
+- [Expandable TableView Sections](http://bit.ly/gSbpZp)
- [Let's Bounce](http://j.mp/JyAfw1)
- [OS X Tutorial for iOS Developers](http://bit.ly/NBVOSY)
- [Bonjour Chat](http://bit.ly/SMO5Re)

0 comments on commit e09682a

Please sign in to comment.