Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#import "STCollapseTableView.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@interface ViewController () <UITableViewDataSource, UITableViewDelegate, STCollapseTableViewDelegate>

@property (weak, nonatomic) IBOutlet STCollapseTableView *tableView;

Expand Down Expand Up @@ -74,6 +74,7 @@ - (void)viewDidLoad
{
[super viewDidLoad];

self.tableView.headerViewTapDelegate = self;
[self.tableView reloadData];
[self.tableView openSection:0 animated:NO];
}
Expand Down Expand Up @@ -122,4 +123,14 @@ - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger
return [self.headers objectAtIndex:section];
}

- (void)STCollapseTableView:(STCollapseTableView *)STCollapseTableView didSelectHeaderViewAtSection:(NSInteger)section
{
[[[UIAlertView alloc] initWithTitle:@""
message:[NSString stringWithFormat:@"headerView %ld tapped",section]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil]
show];
}

@end
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@ As you might have seen, your headers automatically toggle theirs section on a ta
This is automatically done for you in three conditions:
* Your datasource implements the `tableView:heightForHeaderInSection:` method
* The returned views haven't any UITapGestureRecognizer.
* the STCollapseTableView property `shouldHandleHeadersTap` is YES (which is the default value).
* the STCollapseTableView property `shouldHandleHeadersTap` is YES (which is the default value).

----
```
@property (nonatomic, weak) id<STCollapseTableViewDelegate> headerViewTapDelegate;
```
Just as the name, the herderViewTapDelegate is designed to handle hederViews tapping events, you can do things in the delegate method when a specified headerView tapped:

```
- (void)STCollapseTableView:(STCollapseTableView *)STCollapseTableView didSelectHeaderViewAtSection:(NSInteger)section;
```
## Installation

To include this component in your project, I recommend you to use [Cocoapods](http://cocoapods.org):
Expand Down
11 changes: 11 additions & 0 deletions STCollapseTableView/STCollapseTableView.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@
***********************************************************************************/

#import <UIKit/UIKit.h>
@class STCollapseTableView;

@protocol STCollapseTableViewDelegate <NSObject>

@optional

- (void)STCollapseTableView:(STCollapseTableView *)STCollapseTableView didSelectHeaderViewAtSection:(NSInteger)section;

@end

/**
* STCollapseTableView is a UITableView subclass that automatically collapse and/or expand your sections.
Expand Down Expand Up @@ -86,4 +95,6 @@
*/
- (BOOL)isOpenSection:(NSUInteger)sectionIndex;

@property (nonatomic, weak) id<STCollapseTableViewDelegate> headerViewTapDelegate;

@end
153 changes: 79 additions & 74 deletions STCollapseTableView/STCollapseTableView.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,64 +34,64 @@

@interface STCollapseTableView () <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, assign) id<UITableViewDataSource> collapseDataSource;
@property (nonatomic, assign) id<UITableViewDelegate> collapseDelegate;
@property (nonatomic, strong) NSMutableArray* sectionsStates;
@property (nonatomic, weak) id<UITableViewDataSource> collapseDataSource;
@property (nonatomic, weak) id<UITableViewDelegate> collapseDelegate;
@property (nonatomic, strong) NSMutableArray *sectionsStates;

@end

@implementation STCollapseTableView

- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
self = [super initWithCoder:aDecoder];
if (self)
{
[self setupCollapseTableView];
}
return self;
[self setupCollapseTableView];
}
return self;
}

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
self = [super initWithFrame:frame];
if (self)
{
[self setupCollapseTableView];
}
return self;
[self setupCollapseTableView];
}
return self;
}

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
{
self = [super initWithFrame:frame style:style];
if (self)
self = [super initWithFrame:frame style:style];
if (self)
{
[self setupCollapseTableView];
}
return self;
[self setupCollapseTableView];
}
return self;
}

- (void)setupCollapseTableView
{
self.exclusiveSections = YES;
self.exclusiveSections = YES;
self.shouldHandleHeadersTap = YES;
self.sectionsStates = [[NSMutableArray alloc] init];
self.sectionsStates = [[NSMutableArray alloc] init];
}

- (void)setDataSource:(id <UITableViewDataSource>)newDataSource
{
if (newDataSource != self.collapseDataSource)
if (newDataSource && newDataSource != self.collapseDataSource)
{
self.collapseDataSource = newDataSource;
[self.sectionsStates removeAllObjects];
[super setDataSource:self.collapseDataSource?self:nil];
}
self.collapseDataSource = newDataSource;
[self.sectionsStates removeAllObjects];
[super setDataSource:self.collapseDataSource?self:nil];
}
}

- (void)setDelegate:(id<UITableViewDelegate>)newDelegate
{
if (newDelegate != self.collapseDelegate)
if (newDelegate && newDelegate != self.collapseDelegate)
{
self.collapseDelegate = newDelegate;
[super setDelegate:self.collapseDelegate?self:nil];
Expand All @@ -100,15 +100,15 @@ - (void)setDelegate:(id<UITableViewDelegate>)newDelegate

- (id)forwardingTargetForSelector:(SEL)aSelector
{
if ([self.collapseDataSource respondsToSelector:aSelector])
if ([self.collapseDataSource respondsToSelector:aSelector])
{
return self.collapseDataSource;
}
return self.collapseDataSource;
}
if ([self.collapseDelegate respondsToSelector:aSelector])
{
return self.collapseDelegate;
}
return nil;
return nil;
}

- (BOOL)respondsToSelector:(SEL)aSelector
Expand All @@ -118,7 +118,7 @@ - (BOOL)respondsToSelector:(SEL)aSelector
return [self.collapseDelegate respondsToSelector:aSelector];
}

return [super respondsToSelector:aSelector] || [self.collapseDataSource respondsToSelector:aSelector] || [self.collapseDelegate respondsToSelector:aSelector];
return [super respondsToSelector:aSelector] || [self.collapseDataSource respondsToSelector:aSelector] || [self.collapseDelegate respondsToSelector:aSelector];
}

- (void)openSection:(NSUInteger)sectionIndex animated:(BOOL)animated
Expand All @@ -132,16 +132,16 @@ - (void)openSection:(NSUInteger)sectionIndex animated:(BOOL)animated
{
return;
}
if (self.exclusiveSections)
if (self.exclusiveSections)
{
NSUInteger openedSection = [self openedSection];

[self setSectionAtIndex:sectionIndex open:YES];
[self setSectionAtIndex:openedSection open:NO];
[self setSectionAtIndex:sectionIndex open:YES];
[self setSectionAtIndex:openedSection open:NO];

if(animated)
{
{
NSArray* indexPathsToInsert = [self indexPathsForRowsInSectionAtIndex:sectionIndex];
NSArray* indexPathsToDelete = [self indexPathsForRowsInSectionAtIndex:openedSection];

Expand All @@ -168,31 +168,31 @@ - (void)openSection:(NSUInteger)sectionIndex animated:(BOOL)animated
{
[self reloadData];
}
}
}
else
{
[self setSectionAtIndex:sectionIndex open:YES];
if (animated)
[self setSectionAtIndex:sectionIndex open:YES];
if (animated)
{
NSArray* indexPathsToInsert = [self indexPathsForRowsInSectionAtIndex:sectionIndex];
[self insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationTop];
[self insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationFade];
}
else
{
[self reloadData];
}
}
}
}

- (void)closeSection:(NSUInteger)sectionIndex animated:(BOOL)animated
{
[self setSectionAtIndex:sectionIndex open:NO];
if (animated)
if (animated)
{
NSArray* indexPathsToDelete = [self indexPathsForRowsInSectionAtIndex:sectionIndex];
[self deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationTop];
[self deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:NO];
}
else
{
Expand All @@ -204,28 +204,28 @@ - (void)toggleSection:(NSUInteger)sectionIndex animated:(BOOL)animated
{
if (sectionIndex >= [self.sectionsStates count])
{
return;
}
BOOL sectionIsOpen = [[self.sectionsStates objectAtIndex:sectionIndex] boolValue];
if (sectionIsOpen)
return;
}
BOOL sectionIsOpen = [[self.sectionsStates objectAtIndex:sectionIndex] boolValue];
if (sectionIsOpen)
{
[self closeSection:sectionIndex animated:animated];
}
[self closeSection:sectionIndex animated:animated];
}
else
{
[self openSection:sectionIndex animated:animated];
}
[self openSection:sectionIndex animated:animated];
}
}

- (BOOL)isOpenSection:(NSUInteger)sectionIndex
{
if (sectionIndex >= [self.sectionsStates count])
{
return NO;
}
return [[self.sectionsStates objectAtIndex:sectionIndex] boolValue];
return NO;
}
return [[self.sectionsStates objectAtIndex:sectionIndex] boolValue];
}

- (void)setExclusiveSections:(BOOL)exclusiveSections
Expand Down Expand Up @@ -262,41 +262,41 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([[self.sectionsStates objectAtIndex:section] boolValue])
if ([[self.sectionsStates objectAtIndex:section] boolValue])
{
return [self.collapseDataSource tableView:tableView numberOfRowsInSection:section];
}
return 0;
return [self.collapseDataSource tableView:tableView numberOfRowsInSection:section];
}
return 0;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
int nbSection = [self.collapseDataSource numberOfSectionsInTableView:tableView];
int nbSection = (int)[self.collapseDataSource numberOfSectionsInTableView:tableView];

while (nbSection < [self.sectionsStates count])
while (nbSection < [self.sectionsStates count])
{
[self.sectionsStates removeLastObject];
}
[self.sectionsStates removeLastObject];
}

while (nbSection > [self.sectionsStates count])
while (nbSection > [self.sectionsStates count])
{
[self.sectionsStates addObject:@NO];
}
[self.sectionsStates addObject:@NO];
}

return nbSection;
return nbSection;
}

#pragma mark - Delegate

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView* view = [self.collapseDelegate tableView:tableView viewForHeaderInSection:section];
UIView *view = [self.collapseDelegate tableView:tableView viewForHeaderInSection:section];

if (self.shouldHandleHeadersTap)
{
NSArray* gestures = view.gestureRecognizers;
NSArray *gestures = view.gestureRecognizers;
BOOL tapGestureFound = NO;
for (UIGestureRecognizer* gesture in gestures)
for (UIGestureRecognizer *gesture in gestures)
{
if ([gesture isKindOfClass:[UITapGestureRecognizer class]])
{
Expand All @@ -307,9 +307,9 @@ - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger

if (!tapGestureFound)
{
[view setTag:section];
[view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]];
}
[view setTag:section];
}

return view;
Expand All @@ -322,6 +322,11 @@ - (void)handleTapGesture:(UITapGestureRecognizer*)tap
NSInteger index = tap.view.tag;
if (index >= 0)
{
if([self.headerViewTapDelegate respondsToSelector:@selector(STCollapseTableView:didSelectHeaderViewAtSection:)])
{
[self.headerViewTapDelegate STCollapseTableView:self didSelectHeaderViewAtSection:index];
}

[self toggleSection:(NSUInteger)index animated:YES];
}
}
Expand Down