├── .travis.yml
├── .DS_Store
├── Screenshots
├── Screenshots1.png
├── Screenshots2.png
├── Screenshots3.png
└── Screenshots4.png
├── FTFoldingTableView
├── Arrowhead.png
├── FTFoldingTableView.h
└── FTFoldingTableView.m
├── Demo
├── FTFoldingTableView.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
├── FTFoldingTableView
│ ├── ViewController.h
│ ├── AppDelegate.h
│ ├── main.m
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Info.plist
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── AppDelegate.m
│ ├── ViewController.m
│ └── Main.storyboard
└── FTFoldingTableViewUITests
│ ├── Info.plist
│ └── FTFoldingTableViewUITests.m
├── ChangeLog.md
├── LICENSE
├── FTFoldingTableView.podspec
├── .gitignore
└── README.md
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liufengting/FTFoldingTableView/HEAD/.DS_Store
--------------------------------------------------------------------------------
/Screenshots/Screenshots1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liufengting/FTFoldingTableView/HEAD/Screenshots/Screenshots1.png
--------------------------------------------------------------------------------
/Screenshots/Screenshots2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liufengting/FTFoldingTableView/HEAD/Screenshots/Screenshots2.png
--------------------------------------------------------------------------------
/Screenshots/Screenshots3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liufengting/FTFoldingTableView/HEAD/Screenshots/Screenshots3.png
--------------------------------------------------------------------------------
/Screenshots/Screenshots4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liufengting/FTFoldingTableView/HEAD/Screenshots/Screenshots4.png
--------------------------------------------------------------------------------
/FTFoldingTableView/Arrowhead.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liufengting/FTFoldingTableView/HEAD/FTFoldingTableView/Arrowhead.png
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 | @end
14 |
15 |
--------------------------------------------------------------------------------
/ChangeLog.md:
--------------------------------------------------------------------------------
1 | # FTFoldingTableView ChangeLog
2 |
3 | * 1.0.0 (2016.06.28) upload to Cocoapods
4 | * 1.0.5 (2016.08.01) supports portrait and landscrape
5 | * 1.0.6 (2017.02.03) add will fold/open delegate
6 | * 1.0.8 (2018.01.11) add didDeselectRowAtIndexPath delegate
7 | * 1.0.9 (2018.01.15) add delegate methods and public methods
8 | * 1.1.0 (2019.03.09) just made some small changes
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/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 | }
--------------------------------------------------------------------------------
/Demo/FTFoldingTableViewUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 刘锋婷
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/FTFoldingTableView.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "FTFoldingTableView"
4 | s.version = "1.1.0"
5 | s.summary = "Folding cells with simple delegates, and change UI looks in a few lines of code."
6 | s.description = <<-DESC
7 | FTFoldingTableView.Folding cells with simple delegates, and change UI looks in a few lines of code. I recently developed this for future use.
8 | DESC
9 | s.homepage = "https://github.com/liufengting/FTFoldingTableView"
10 | s.screenshots = "https://raw.githubusercontent.com/liufengting/FTFoldingTableView/master/Screenshots/Screenshots1.png","https://raw.githubusercontent.com/liufengting/FTFoldingTableView/master/Screenshots/Screenshots2.png","https://raw.githubusercontent.com/liufengting/FTFoldingTableView/master/Screenshots/Screenshots3.png","https://raw.githubusercontent.com/liufengting/FTFoldingTableView/master/Screenshots/Screenshots4.png"
11 | s.license = { :type => "MIT", :file => "LICENSE" }
12 | s.author = { "liufengting" => "wo157121900@me.com" }
13 | s.social_media_url = "https://twitter.com/liufengting"
14 | s.platform = :ios
15 | s.source = { :git => "https://github.com/liufengting/FTFoldingTableView.git", :tag => "#{s.version}" }
16 | s.source_files = "FTFoldingTableView/*.{h,m}"
17 | s.resources = "FTFoldingTableView/*.{png}"
18 |
19 | end
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableViewUITests/FTFoldingTableViewUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // FTFoldingTableViewUITests.m
3 | // FTFoldingTableViewUITests
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface FTFoldingTableViewUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation FTFoldingTableViewUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 | .DS_Store
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xcuserstate
23 |
24 | ## Obj-C/Swift specific
25 | *.hmap
26 | *.ipa
27 | *.dSYM.zip
28 | *.dSYM
29 |
30 | # CocoaPods
31 | #
32 | # We recommend against adding the Pods directory to your .gitignore. However
33 | # you should judge for yourself, the pros and cons are mentioned at:
34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
35 | #
36 | # Pods/
37 |
38 | # Carthage
39 | #
40 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
41 | # Carthage/Checkouts
42 |
43 | Carthage/Build
44 |
45 | # fastlane
46 | #
47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
48 | # screenshots whenever they are needed.
49 | # For more information about the recommended setup visit:
50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
51 |
52 | fastlane/report.xml
53 | fastlane/screenshots
54 |
55 | #Code Injection
56 | #
57 | # After new code Injection tools there's a generated folder /iOSInjectionProject
58 | # https://github.com/johnno1962/injectionforxcode
59 |
60 | iOSInjectionProject/
61 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/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 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // 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.
25 | // 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.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // 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.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // 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.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // 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.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "FTFoldingTableView.h"
11 |
12 | static NSString * const SectionHeaderViewIdentifier = @"SectionHeaderViewIdentifier";
13 | static NSString * const DemoTableViewIdentifier = @"DemoTableViewIdentifier";
14 |
15 | @interface ViewController ()
16 |
17 | @property (weak, nonatomic) IBOutlet FTFoldingTableView *ft_tableView;
18 | @property (nonatomic, assign) FTFoldingSectionHeaderArrowPosition arrowPosition;
19 |
20 | @end
21 |
22 | @implementation ViewController
23 |
24 | - (void)viewDidLoad {
25 | [super viewDidLoad];
26 |
27 | self.automaticallyAdjustsScrollViewInsets = NO;
28 |
29 | self.arrowPosition = FTFoldingSectionHeaderArrowPositionLeft;
30 |
31 | self.ft_tableView.foldingDelegate = self;
32 | }
33 |
34 | - (IBAction)changeStyle:(UIBarButtonItem *)sender
35 | {
36 | self.arrowPosition = [NSNumber numberWithBool:(![NSNumber numberWithInteger:self.arrowPosition].boolValue)].integerValue;
37 | [self.ft_tableView reloadData];
38 |
39 |
40 | // foldAllSections
41 | // [self.ft_tableView foldAllSections];
42 |
43 | // expandAllSections
44 | // [self.ft_tableView expandAllSections];
45 |
46 | // test one section
47 | // NSInteger section = 0;
48 | // FTFoldingSectionState state = [self.ft_tableView foldingStateForSection:section];
49 | // if (state == FTFoldingSectionStateFold) {
50 | // [self.ft_tableView expandSection:section];
51 | // }else{
52 | // [self.ft_tableView foldSection:section];
53 | // }
54 | }
55 |
56 | #pragma mark - FTFoldingTableViewDelegate / required
57 |
58 | - (FTFoldingSectionHeaderArrowPosition)perferedArrowPositionForFTFoldingTableView:(FTFoldingTableView *)ftTableView
59 | {
60 | return self.arrowPosition;
61 | }
62 | - (NSInteger)numberOfSectionForFTFoldingTableView:(FTFoldingTableView *)ftTableView
63 | {
64 | return 5;
65 | }
66 | - (NSInteger)ftFoldingTableView:(FTFoldingTableView *)ftTableView numberOfRowsInSection:(NSInteger)section
67 | {
68 | return 3;
69 | }
70 | - (CGFloat)ftFoldingTableView:(FTFoldingTableView *)ftTableView heightForHeaderInSection:(NSInteger)section
71 | {
72 | return 60.f;
73 | }
74 | - (CGFloat)ftFoldingTableView:(FTFoldingTableView *)ftTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
75 | {
76 | return 50.f;
77 | }
78 | - (NSString *)ftFoldingTableView:(FTFoldingTableView *)ftTableView titleForHeaderInSection:(NSInteger)section
79 | {
80 | return [NSString stringWithFormat:@"Section %ld",section];
81 | }
82 | - (UITableViewCell *)ftFoldingTableView:(FTFoldingTableView *)ftTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
83 | {
84 | UITableViewCell *cell = [self.ft_tableView dequeueReusableCellWithIdentifier:DemoTableViewIdentifier forIndexPath:indexPath];
85 |
86 |
87 | return cell;
88 | }
89 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
90 | {
91 | [ftTableView deselectRowAtIndexPath:indexPath animated:YES];
92 | }
93 |
94 | #pragma mark - FTFoldingTableViewDelegate / optional delegates, change almost everything using delegate
95 |
96 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView willChangeToSectionState:(FTFoldingSectionState)sectionState section:(NSInteger)section
97 | {
98 | NSLog(@"section: %ld is about to %@", section, sectionState == FTFoldingSectionStateFold ? @"close" : @"open");
99 | }
100 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView didChangeToSectionState:(FTFoldingSectionState)sectionState section:(NSInteger)section
101 | {
102 | NSLog(@"section: %ld is now %@", section, sectionState == FTFoldingSectionStateFold ? @"closed" : @"opened");
103 | }
104 |
105 | - (NSString *)ftFoldingTableView:(FTFoldingTableView *)ftTableView descriptionForHeaderInSection:(NSInteger)section
106 | {
107 | return @"description";
108 | }
109 |
110 | //- (UIImage *)ftFoldingTableView:(FTFoldingTableView *)ftTableView arrowImageForSection:(NSInteger)section
111 | //{
112 | // return [UIImage imageNamed:@"Arrowhead"];
113 | //}
114 | //- (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView backgroundColorForHeaderInSection:(NSInteger)section
115 | //{
116 | // return [UIColor grayColor];
117 | //}
118 | //- (UIFont *)ftFoldingTableView:(FTFoldingTableView *)ftTableView fontForTitleInSection:(NSInteger)section
119 | //{
120 | // return [UIFont boldSystemFontOfSize:16];
121 | //}
122 | //- (UIFont *)ftFoldingTableView:(FTFoldingTableView *)ftTableView fontForDescriptionInSection:(NSInteger)section
123 | //{
124 | // return [UIFont systemFontOfSize:13];
125 | //}
126 | //- (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView textColorForTitleInSection:(NSInteger)section
127 | //{
128 | // return [UIColor whiteColor];
129 | //}
130 | //- (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView textColorForDescriptionInSection:(NSInteger)section
131 | //{
132 | // return [UIColor whiteColor];
133 | //}
134 |
135 | @end
136 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FTFoldingTableView
2 |
3 | [](http://twitter.com/liufengting)
4 | [](https://raw.githubusercontent.com/liufengting/FTFoldingTableView/master/LICENSE)
5 | [](http://cocoapods.org/pods/FTFoldingTableView)
6 | [](http://cocoapods.org/pods/FTFoldingTableView)
7 | [](http://cocoapods.org/pods/FTFoldingTableView)
8 | [](https://travis-ci.org/liufengting/FTFoldingTableView)
9 | [](https://github.com/liufengting/FTFoldingTableView/stargazers)
10 |
11 | FTFoldingTableView. Folding cells with simple delegates, and change UI looks in a few lines of code.
12 |
13 |
14 | # ScreenShots
15 |
16 | | Style | Left | Right |
17 | |:-------------|:-------------:|:-------------:|
18 | | fold |
|
|
19 | | show |
|
|
20 |
21 | # Usage
22 |
23 | ## Required Methods
24 |
25 | * preferred ArrowPosition
26 |
27 | ```objective-c
28 | - (FTFoldingSectionHeaderArrowPosition)perferedArrowPositionForFTFoldingTableView:(FTFoldingTableView *)ftTableView
29 | {
30 | return self.arrowPosition;
31 | }
32 | ```
33 | * numberOfSectionForFTFoldingTableView
34 |
35 | ```objective-c
36 | - (NSInteger )numberOfSectionForFTFoldingTableView:(FTFoldingTableView *)ftTableView
37 | {
38 | return 5;
39 | }
40 |
41 | ```
42 | * numberOfRowsInSection
43 |
44 | ```objective-c
45 | - (NSInteger )ftFoldingTableView:(FTFoldingTableView *)ftTableView numberOfRowsInSection:(NSInteger )section
46 | {
47 | return 3;
48 | }
49 | ```
50 | * heightForHeaderInSection
51 |
52 | ```objective-c
53 | - (CGFloat )ftFoldingTableView:(FTFoldingTableView *)ftTableView heightForHeaderInSection:(NSInteger )section
54 | {
55 | return 60;
56 | }
57 | ```
58 | * heightForRowAtIndexPath
59 |
60 | ```objective-c
61 | - (CGFloat )ftFoldingTableView:(FTFoldingTableView *)ftTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
62 | {
63 | return 50;
64 | }
65 | ```
66 | * titleForHeaderInSection
67 |
68 | ```objective-c
69 | - (NSString *)ftFoldingTableView:(FTFoldingTableView *)ftTableView titleForHeaderInSection:(NSInteger)section
70 | {
71 | return [NSString stringWithFormat:@"Section %ld",section];
72 | }
73 | ```
74 | * cellForRowAtIndexPath
75 |
76 | ```objective-c
77 | - (UITableViewCell *)ftFoldingTableView:(FTFoldingTableView *)ftTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
78 | {
79 | UITableViewCell *cell = [ft_tableView dequeueReusableCellWithIdentifier:DemoTableViewIdentifier forIndexPath:indexPath];
80 |
81 |
82 | return cell;
83 | }
84 | ```
85 | * didSelectRowAtIndexPath
86 |
87 | ```objective-c
88 | - (void )ftFoldingTableView:(FTFoldingTableView *)ftTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
89 | {
90 | [ftTableView deselectRowAtIndexPath:indexPath animated:YES];
91 |
92 |
93 | }
94 | ```
95 | ## Optional Methods
96 |
97 | * descriptionForHeaderInSection
98 |
99 | ```objective-c
100 | - (NSString *)ftFoldingTableView:(FTFoldingTableView *)ftTableView descriptionForHeaderInSection:(NSInteger )section
101 | {
102 | return @"description";
103 | }
104 | ```
105 | * arrowImageForSection
106 |
107 | ```objective-c
108 | - (UIImage *)ftFoldingTableView:(FTFoldingTableView *)ftTableView arrowImageForSection:(NSInteger )section
109 | {
110 | return [UIImage imageNamed:@"Arrowhead"];
111 | }
112 | ```
113 | * backgroundColorForHeaderInSection
114 |
115 | ```objective-c
116 | - (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView backgroundColorForHeaderInSection:(NSInteger )section
117 | {
118 | return [UIColor grayColor];
119 | }
120 | ```
121 | * fontForTitleInSection
122 |
123 | ```objective-c
124 | - (UIFont *)ftFoldingTableView:(FTFoldingTableView *)ftTableView fontForTitleInSection:(NSInteger )section
125 | {
126 | return [UIFont boldSystemFontOfSize:16];
127 | }
128 | ```
129 | * fontForDescriptionInSection
130 |
131 | ```objective-c
132 | - (UIFont *)ftFoldingTableView:(FTFoldingTableView *)ftTableView fontForDescriptionInSection:(NSInteger )section
133 | {
134 | return [UIFont systemFontOfSize:13];
135 | }
136 | ```
137 | * textColorForTitleInSection
138 |
139 | ```objective-c
140 | - (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView textColorForTitleInSection:(NSInteger )section
141 | {
142 | return [UIColor whiteColor];
143 | }
144 | ```
145 | * textColorForDescriptionInSection
146 |
147 | ```objective-c
148 | - (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView textColorForDescriptionInSection:(NSInteger )section
149 | {
150 | return [UIColor whiteColor];
151 | }
152 | ```
153 |
154 | # Installation
155 |
156 | ## Manually
157 |
158 | * clone this repo.
159 | * Simply drop the '/FTFoldingTableViewLib' folder into your project.
160 | * Enjoy!
161 |
162 | ## Cocoapods
163 |
164 | FTFoldingTableView is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:
165 |
166 | ```ruby
167 | pod 'FTFoldingTableView'
168 | ```
169 |
170 |
171 |
172 | # Need to know
173 |
174 | * I used two days to finish this project, and then uploaded it to Cocoapods, so I didn't have enough time to test it;if you have any questions, please let me know. I'll fill this README in the near future.
175 |
176 |
177 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView/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 |
42 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
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 |
--------------------------------------------------------------------------------
/FTFoldingTableView/FTFoldingTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // FTFoldingTableView.h
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #pragma mark - ENUM FTFoldingSectionState
12 | /**
13 | FTFoldingSectionState
14 | */
15 | typedef NS_ENUM(NSUInteger, FTFoldingSectionState) {
16 | /**
17 | section state fold
18 | */
19 | FTFoldingSectionStateFold,
20 | /**
21 | section state show
22 | */
23 | FTFoldingSectionStateExpand,
24 | };
25 |
26 | #pragma mark - ENUM FTFoldingSectionHeaderArrowPosition
27 | /**
28 | FTFoldingSectionHeaderArrowPosition
29 | */
30 | typedef NS_ENUM(NSUInteger, FTFoldingSectionHeaderArrowPosition) {
31 | /**
32 | arrow position left
33 | */
34 | FTFoldingSectionHeaderArrowPositionLeft,
35 | /**
36 | arrow position right
37 | */
38 | FTFoldingSectionHeaderArrowPositionRight,
39 | };
40 |
41 |
42 | #pragma mark - FTFoldingTableViewDelegate
43 |
44 | @class FTFoldingTableView;
45 | /**
46 | * FTFoldingTableViewDelegate
47 | */
48 | @protocol FTFoldingTableViewDelegate
49 |
50 | @required
51 | /**
52 | perferedArrowPositionForFTFoldingTableView
53 |
54 | @param ftTableView FTFoldingTableView
55 | @return FTFoldingSectionHeaderArrowPosition
56 | */
57 | - (FTFoldingSectionHeaderArrowPosition)perferedArrowPositionForFTFoldingTableView:(FTFoldingTableView *)ftTableView;
58 | /**
59 | numberOfSectionForFTFoldingTableView
60 |
61 | @param ftTableView FTFoldingTableView
62 | @return NSInteger
63 | */
64 | - (NSInteger)numberOfSectionForFTFoldingTableView:(FTFoldingTableView *)ftTableView;
65 | /**
66 | numberOfRowsInSection
67 |
68 | @param ftTableView FTFoldingTableView
69 | @param section NSInteger
70 | @return NSInteger
71 | */
72 | - (NSInteger)ftFoldingTableView:(FTFoldingTableView *)ftTableView numberOfRowsInSection:(NSInteger)section;
73 | /**
74 | heightForHeaderInSection
75 |
76 | @param ftTableView FTFoldingTableView
77 | @param section NSInteger
78 | @return CGFloat
79 | */
80 | - (CGFloat)ftFoldingTableView:(FTFoldingTableView *)ftTableView heightForHeaderInSection:(NSInteger)section;
81 | /**
82 | heightForRowAtIndexPath
83 |
84 | @param ftTableView FTFoldingTableView
85 | @param indexPath NSIndexPath
86 | @return CGFloat
87 | */
88 | - (CGFloat)ftFoldingTableView:(FTFoldingTableView *)ftTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
89 | /**
90 | titleForHeaderInSection
91 |
92 | @param ftTableView FTFoldingTableView
93 | @param section NSInteger
94 | @return NSString
95 | */
96 | - (NSString *)ftFoldingTableView:(FTFoldingTableView *)ftTableView titleForHeaderInSection:(NSInteger)section;
97 | /**
98 | cellForRowAtIndexPath
99 |
100 | @param ftTableView FTFoldingTableView
101 | @param indexPath NSIndexPath
102 | @return UITableViewCell
103 | */
104 | - (UITableViewCell *)ftFoldingTableView:(FTFoldingTableView *)ftTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
105 | /**
106 | didSelectRowAtIndexPath
107 |
108 | @param ftTableView FTFoldingTableView
109 | @param indexPath NSIndexPath
110 | */
111 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
112 |
113 | @optional
114 |
115 | /**
116 | didChangeSectionState
117 |
118 | @param ftTableView FTFoldingTableView
119 | @param sectionState FTFoldingSectionState
120 | @param section section
121 | */
122 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView willChangeToSectionState:(FTFoldingSectionState)sectionState section:(NSInteger)section;
123 | /**
124 | didChangeToSectionState
125 |
126 | @param ftTableView FTFoldingTableView
127 | @param sectionState FTFoldingSectionState
128 | @param section section
129 | */
130 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView didChangeToSectionState:(FTFoldingSectionState)sectionState section:(NSInteger)section;
131 | /**
132 | arrowImageForSection
133 |
134 | @param ftTableView FTFoldingTableView
135 | @param section NSInteger
136 | @return UIImage
137 | */
138 | - (UIImage *)ftFoldingTableView:(FTFoldingTableView *)ftTableView arrowImageForSection:(NSInteger)section;
139 | /**
140 | descriptionForHeaderInSection
141 |
142 | @param ftTableView FTFoldingTableView
143 | @param section NSInteger
144 | @return NSString
145 | */
146 | - (NSString *)ftFoldingTableView:(FTFoldingTableView *)ftTableView descriptionForHeaderInSection:(NSInteger)section;
147 | /**
148 | backgroundColorForHeaderInSection
149 |
150 | @param ftTableView FTFoldingTableView
151 | @param section NSInteger
152 | @return UIColor
153 | */
154 | - (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView backgroundColorForHeaderInSection:(NSInteger)section;
155 | /**
156 | fontForTitleInSection
157 |
158 | @param ftTableView FTFoldingTableView
159 | @param section NSInteger
160 | @return UIFont
161 | */
162 | - (UIFont *)ftFoldingTableView:(FTFoldingTableView *)ftTableView fontForTitleInSection:(NSInteger)section;
163 | /**
164 | fontForDescriptionInSection
165 |
166 | @param ftTableView FTFoldingTableView
167 | @param section NSInteger
168 | @return UIFont
169 | */
170 | - (UIFont *)ftFoldingTableView:(FTFoldingTableView *)ftTableView fontForDescriptionInSection:(NSInteger)section;
171 | /**
172 | textColorForTitleInSection
173 |
174 | @param ftTableView FTFoldingTableView
175 | @param section NSInteger
176 | @return UIColor
177 | */
178 | - (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView textColorForTitleInSection:(NSInteger)section;
179 | /**
180 | textColorForDescriptionInSection
181 |
182 | @param ftTableView FTFoldingTableView
183 | @param section NSInteger
184 | @return UIColor
185 | */
186 | - (UIColor *)ftFoldingTableView:(FTFoldingTableView *)ftTableView textColorForDescriptionInSection:(NSInteger)section;
187 | /**
188 | didDeselectRowAtIndexPath
189 |
190 | @param ftTableView FTFoldingTableView
191 | @param indexPath NSIndexPath
192 | */
193 | - (void)ftFoldingTableView:(FTFoldingTableView *)ftTableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath;
194 |
195 | @end
196 |
197 | #pragma mark - FTFoldingSectionHeaderDelegate
198 | /**
199 | FTFoldingSectionHeaderDelegate
200 | */
201 | @protocol FTFoldingSectionHeaderDelegate
202 | /**
203 | ftFoldingSectionHeaderTappedAtIndex
204 |
205 | @param index NSInteger
206 | */
207 | - (void)ftFoldingSectionHeaderTappedAtIndex:(NSInteger)index;
208 |
209 | @end
210 |
211 | #pragma mark - FTFoldingTableView
212 | /**
213 | FTFoldingTableView
214 | */
215 | @interface FTFoldingTableView : UITableView
216 | /**
217 | FTFoldingTableViewDelegate foldingDelegate
218 | */
219 | @property (nonatomic, weak) id foldingDelegate;
220 |
221 | /**
222 | foldingStateForSection
223 |
224 | @param section NSInteger
225 | @return FTFoldingSectionState
226 | */
227 | - (FTFoldingSectionState)foldingStateForSection:(NSInteger)section;
228 |
229 | /**
230 | expandSection
231 |
232 | @param section NSInteger
233 | */
234 | - (void)expandSection:(NSInteger)section;
235 |
236 | /**
237 | foldSection
238 |
239 | @param section NSInteger
240 | */
241 | - (void)foldSection:(NSInteger)section;
242 |
243 | /**
244 | expandAllSections
245 | */
246 | - (void)expandAllSections;
247 |
248 | /**
249 | foldAllSections
250 | */
251 | - (void)foldAllSections;
252 |
253 | @end
254 |
255 | #pragma mark - FTFoldingSectionHeader
256 |
257 | /**
258 | FTFoldingSectionHeader
259 | */
260 | @interface FTFoldingSectionHeader : UIView
261 |
262 | @property (nonatomic, weak) id tapDelegate;
263 | /**
264 | initWithFrame
265 |
266 | @param frame CGRect
267 | @param tag NSInteger
268 | @return instancetype
269 | */
270 | - (instancetype)initWithFrame:(CGRect)frame withTag:(NSInteger)tag;
271 | /**
272 | setup
273 |
274 | @param backgroundColor UIColor
275 | @param titleString NSString
276 | @param titleColor UIColor
277 | @param titleFont UIFont
278 | @param descriptionString NSString
279 | @param descriptionColor UIColor
280 | @param descriptionFont UIFont
281 | @param arrowImage UIImage
282 | @param arrowPosition FTFoldingSectionHeaderArrowPosition
283 | @param sectionState FTFoldingSectionState
284 | */
285 | - (void)setupWithBackgroundColor:(UIColor *)backgroundColor
286 | titleString:(NSString *)titleString
287 | titleColor:(UIColor *)titleColor
288 | titleFont:(UIFont *)titleFont
289 | descriptionString:(NSString *)descriptionString
290 | descriptionColor:(UIColor *)descriptionColor
291 | descriptionFont:(UIFont *)descriptionFont
292 | arrowImage:(UIImage *)arrowImage
293 | arrowPosition:(FTFoldingSectionHeaderArrowPosition)arrowPosition
294 | sectionState:(FTFoldingSectionState)sectionState;
295 |
296 | @end
297 |
--------------------------------------------------------------------------------
/Demo/FTFoldingTableView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 2ABD2C521E44520F00EBB748 /* Arrowhead.png in Resources */ = {isa = PBXBuildFile; fileRef = 2ABD2C4F1E44520F00EBB748 /* Arrowhead.png */; };
11 | 2ABD2C531E44520F00EBB748 /* FTFoldingTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 2ABD2C511E44520F00EBB748 /* FTFoldingTableView.m */; };
12 | 5A4B4FB41D4F3D3200134E33 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5A4B4FB31D4F3D3200134E33 /* Main.storyboard */; };
13 | 5AB106C81D178925003E69E4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AB106C71D178925003E69E4 /* main.m */; };
14 | 5AB106CB1D178925003E69E4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AB106CA1D178925003E69E4 /* AppDelegate.m */; };
15 | 5AB106CE1D178925003E69E4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AB106CD1D178925003E69E4 /* ViewController.m */; };
16 | 5AB106D31D178925003E69E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5AB106D21D178925003E69E4 /* Assets.xcassets */; };
17 | 5AB106D61D178925003E69E4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5AB106D41D178925003E69E4 /* LaunchScreen.storyboard */; };
18 | 5AB106E11D178926003E69E4 /* FTFoldingTableViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AB106E01D178926003E69E4 /* FTFoldingTableViewUITests.m */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXContainerItemProxy section */
22 | 5AB106DD1D178926003E69E4 /* PBXContainerItemProxy */ = {
23 | isa = PBXContainerItemProxy;
24 | containerPortal = 5AB106BB1D178925003E69E4 /* Project object */;
25 | proxyType = 1;
26 | remoteGlobalIDString = 5AB106C21D178925003E69E4;
27 | remoteInfo = FTFoldingTableView;
28 | };
29 | /* End PBXContainerItemProxy section */
30 |
31 | /* Begin PBXFileReference section */
32 | 2ABD2C4F1E44520F00EBB748 /* Arrowhead.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Arrowhead.png; sourceTree = ""; };
33 | 2ABD2C501E44520F00EBB748 /* FTFoldingTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FTFoldingTableView.h; sourceTree = ""; };
34 | 2ABD2C511E44520F00EBB748 /* FTFoldingTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FTFoldingTableView.m; sourceTree = ""; };
35 | 5A4B4FB31D4F3D3200134E33 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
36 | 5AB106C31D178925003E69E4 /* FTFoldingTableView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FTFoldingTableView.app; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 5AB106C71D178925003E69E4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
38 | 5AB106C91D178925003E69E4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
39 | 5AB106CA1D178925003E69E4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
40 | 5AB106CC1D178925003E69E4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
41 | 5AB106CD1D178925003E69E4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
42 | 5AB106D21D178925003E69E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 5AB106D51D178925003E69E4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 5AB106D71D178925003E69E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | 5AB106DC1D178926003E69E4 /* FTFoldingTableViewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FTFoldingTableViewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 5AB106E01D178926003E69E4 /* FTFoldingTableViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FTFoldingTableViewUITests.m; sourceTree = ""; };
47 | 5AB106E21D178926003E69E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
48 | /* End PBXFileReference section */
49 |
50 | /* Begin PBXFrameworksBuildPhase section */
51 | 5AB106C01D178925003E69E4 /* Frameworks */ = {
52 | isa = PBXFrameworksBuildPhase;
53 | buildActionMask = 2147483647;
54 | files = (
55 | );
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | 5AB106D91D178926003E69E4 /* Frameworks */ = {
59 | isa = PBXFrameworksBuildPhase;
60 | buildActionMask = 2147483647;
61 | files = (
62 | );
63 | runOnlyForDeploymentPostprocessing = 0;
64 | };
65 | /* End PBXFrameworksBuildPhase section */
66 |
67 | /* Begin PBXGroup section */
68 | 2ABD2C4E1E44520F00EBB748 /* FTFoldingTableView */ = {
69 | isa = PBXGroup;
70 | children = (
71 | 2ABD2C4F1E44520F00EBB748 /* Arrowhead.png */,
72 | 2ABD2C501E44520F00EBB748 /* FTFoldingTableView.h */,
73 | 2ABD2C511E44520F00EBB748 /* FTFoldingTableView.m */,
74 | );
75 | name = FTFoldingTableView;
76 | path = ../../FTFoldingTableView;
77 | sourceTree = "";
78 | };
79 | 5AB106BA1D178925003E69E4 = {
80 | isa = PBXGroup;
81 | children = (
82 | 5AB106C51D178925003E69E4 /* FTFoldingTableView */,
83 | 5AB106DF1D178926003E69E4 /* FTFoldingTableViewUITests */,
84 | 5AB106C41D178925003E69E4 /* Products */,
85 | );
86 | sourceTree = "";
87 | };
88 | 5AB106C41D178925003E69E4 /* Products */ = {
89 | isa = PBXGroup;
90 | children = (
91 | 5AB106C31D178925003E69E4 /* FTFoldingTableView.app */,
92 | 5AB106DC1D178926003E69E4 /* FTFoldingTableViewUITests.xctest */,
93 | );
94 | name = Products;
95 | sourceTree = "";
96 | };
97 | 5AB106C51D178925003E69E4 /* FTFoldingTableView */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 2ABD2C4E1E44520F00EBB748 /* FTFoldingTableView */,
101 | 5AB106C91D178925003E69E4 /* AppDelegate.h */,
102 | 5AB106CA1D178925003E69E4 /* AppDelegate.m */,
103 | 5AB106CC1D178925003E69E4 /* ViewController.h */,
104 | 5AB106CD1D178925003E69E4 /* ViewController.m */,
105 | 5A4B4FB31D4F3D3200134E33 /* Main.storyboard */,
106 | 5AB106D21D178925003E69E4 /* Assets.xcassets */,
107 | 5AB106D41D178925003E69E4 /* LaunchScreen.storyboard */,
108 | 5AB106D71D178925003E69E4 /* Info.plist */,
109 | 5AB106C61D178925003E69E4 /* Supporting Files */,
110 | );
111 | path = FTFoldingTableView;
112 | sourceTree = "";
113 | };
114 | 5AB106C61D178925003E69E4 /* Supporting Files */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 5AB106C71D178925003E69E4 /* main.m */,
118 | );
119 | name = "Supporting Files";
120 | sourceTree = "";
121 | };
122 | 5AB106DF1D178926003E69E4 /* FTFoldingTableViewUITests */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 5AB106E01D178926003E69E4 /* FTFoldingTableViewUITests.m */,
126 | 5AB106E21D178926003E69E4 /* Info.plist */,
127 | );
128 | path = FTFoldingTableViewUITests;
129 | sourceTree = "";
130 | };
131 | /* End PBXGroup section */
132 |
133 | /* Begin PBXNativeTarget section */
134 | 5AB106C21D178925003E69E4 /* FTFoldingTableView */ = {
135 | isa = PBXNativeTarget;
136 | buildConfigurationList = 5AB106E51D178926003E69E4 /* Build configuration list for PBXNativeTarget "FTFoldingTableView" */;
137 | buildPhases = (
138 | 5AB106BF1D178925003E69E4 /* Sources */,
139 | 5AB106C01D178925003E69E4 /* Frameworks */,
140 | 5AB106C11D178925003E69E4 /* Resources */,
141 | );
142 | buildRules = (
143 | );
144 | dependencies = (
145 | );
146 | name = FTFoldingTableView;
147 | productName = FTFoldingTableView;
148 | productReference = 5AB106C31D178925003E69E4 /* FTFoldingTableView.app */;
149 | productType = "com.apple.product-type.application";
150 | };
151 | 5AB106DB1D178926003E69E4 /* FTFoldingTableViewUITests */ = {
152 | isa = PBXNativeTarget;
153 | buildConfigurationList = 5AB106E81D178926003E69E4 /* Build configuration list for PBXNativeTarget "FTFoldingTableViewUITests" */;
154 | buildPhases = (
155 | 5AB106D81D178926003E69E4 /* Sources */,
156 | 5AB106D91D178926003E69E4 /* Frameworks */,
157 | 5AB106DA1D178926003E69E4 /* Resources */,
158 | );
159 | buildRules = (
160 | );
161 | dependencies = (
162 | 5AB106DE1D178926003E69E4 /* PBXTargetDependency */,
163 | );
164 | name = FTFoldingTableViewUITests;
165 | productName = FTFoldingTableViewUITests;
166 | productReference = 5AB106DC1D178926003E69E4 /* FTFoldingTableViewUITests.xctest */;
167 | productType = "com.apple.product-type.bundle.ui-testing";
168 | };
169 | /* End PBXNativeTarget section */
170 |
171 | /* Begin PBXProject section */
172 | 5AB106BB1D178925003E69E4 /* Project object */ = {
173 | isa = PBXProject;
174 | attributes = {
175 | LastUpgradeCheck = 1010;
176 | ORGANIZATIONNAME = liufengting;
177 | TargetAttributes = {
178 | 5AB106C21D178925003E69E4 = {
179 | CreatedOnToolsVersion = 7.3.1;
180 | DevelopmentTeam = E83AC9WR2F;
181 | DevelopmentTeamName = "锋婷 刘 (Personal Team)";
182 | ProvisioningStyle = Automatic;
183 | };
184 | 5AB106DB1D178926003E69E4 = {
185 | CreatedOnToolsVersion = 7.3.1;
186 | TestTargetID = 5AB106C21D178925003E69E4;
187 | };
188 | };
189 | };
190 | buildConfigurationList = 5AB106BE1D178925003E69E4 /* Build configuration list for PBXProject "FTFoldingTableView" */;
191 | compatibilityVersion = "Xcode 3.2";
192 | developmentRegion = English;
193 | hasScannedForEncodings = 0;
194 | knownRegions = (
195 | en,
196 | Base,
197 | );
198 | mainGroup = 5AB106BA1D178925003E69E4;
199 | productRefGroup = 5AB106C41D178925003E69E4 /* Products */;
200 | projectDirPath = "";
201 | projectRoot = "";
202 | targets = (
203 | 5AB106C21D178925003E69E4 /* FTFoldingTableView */,
204 | 5AB106DB1D178926003E69E4 /* FTFoldingTableViewUITests */,
205 | );
206 | };
207 | /* End PBXProject section */
208 |
209 | /* Begin PBXResourcesBuildPhase section */
210 | 5AB106C11D178925003E69E4 /* Resources */ = {
211 | isa = PBXResourcesBuildPhase;
212 | buildActionMask = 2147483647;
213 | files = (
214 | 5AB106D61D178925003E69E4 /* LaunchScreen.storyboard in Resources */,
215 | 2ABD2C521E44520F00EBB748 /* Arrowhead.png in Resources */,
216 | 5AB106D31D178925003E69E4 /* Assets.xcassets in Resources */,
217 | 5A4B4FB41D4F3D3200134E33 /* Main.storyboard in Resources */,
218 | );
219 | runOnlyForDeploymentPostprocessing = 0;
220 | };
221 | 5AB106DA1D178926003E69E4 /* Resources */ = {
222 | isa = PBXResourcesBuildPhase;
223 | buildActionMask = 2147483647;
224 | files = (
225 | );
226 | runOnlyForDeploymentPostprocessing = 0;
227 | };
228 | /* End PBXResourcesBuildPhase section */
229 |
230 | /* Begin PBXSourcesBuildPhase section */
231 | 5AB106BF1D178925003E69E4 /* Sources */ = {
232 | isa = PBXSourcesBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | 5AB106CE1D178925003E69E4 /* ViewController.m in Sources */,
236 | 5AB106CB1D178925003E69E4 /* AppDelegate.m in Sources */,
237 | 5AB106C81D178925003E69E4 /* main.m in Sources */,
238 | 2ABD2C531E44520F00EBB748 /* FTFoldingTableView.m in Sources */,
239 | );
240 | runOnlyForDeploymentPostprocessing = 0;
241 | };
242 | 5AB106D81D178926003E69E4 /* Sources */ = {
243 | isa = PBXSourcesBuildPhase;
244 | buildActionMask = 2147483647;
245 | files = (
246 | 5AB106E11D178926003E69E4 /* FTFoldingTableViewUITests.m in Sources */,
247 | );
248 | runOnlyForDeploymentPostprocessing = 0;
249 | };
250 | /* End PBXSourcesBuildPhase section */
251 |
252 | /* Begin PBXTargetDependency section */
253 | 5AB106DE1D178926003E69E4 /* PBXTargetDependency */ = {
254 | isa = PBXTargetDependency;
255 | target = 5AB106C21D178925003E69E4 /* FTFoldingTableView */;
256 | targetProxy = 5AB106DD1D178926003E69E4 /* PBXContainerItemProxy */;
257 | };
258 | /* End PBXTargetDependency section */
259 |
260 | /* Begin PBXVariantGroup section */
261 | 5AB106D41D178925003E69E4 /* LaunchScreen.storyboard */ = {
262 | isa = PBXVariantGroup;
263 | children = (
264 | 5AB106D51D178925003E69E4 /* Base */,
265 | );
266 | name = LaunchScreen.storyboard;
267 | sourceTree = "";
268 | };
269 | /* End PBXVariantGroup section */
270 |
271 | /* Begin XCBuildConfiguration section */
272 | 5AB106E31D178926003E69E4 /* Debug */ = {
273 | isa = XCBuildConfiguration;
274 | buildSettings = {
275 | ALWAYS_SEARCH_USER_PATHS = NO;
276 | CLANG_ANALYZER_NONNULL = YES;
277 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
278 | CLANG_CXX_LIBRARY = "libc++";
279 | CLANG_ENABLE_MODULES = YES;
280 | CLANG_ENABLE_OBJC_ARC = YES;
281 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
282 | CLANG_WARN_BOOL_CONVERSION = YES;
283 | CLANG_WARN_COMMA = YES;
284 | CLANG_WARN_CONSTANT_CONVERSION = YES;
285 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
286 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
287 | CLANG_WARN_EMPTY_BODY = YES;
288 | CLANG_WARN_ENUM_CONVERSION = YES;
289 | CLANG_WARN_INFINITE_RECURSION = YES;
290 | CLANG_WARN_INT_CONVERSION = YES;
291 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
292 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
293 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
294 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
295 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
296 | CLANG_WARN_STRICT_PROTOTYPES = YES;
297 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
298 | CLANG_WARN_UNREACHABLE_CODE = YES;
299 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
300 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
301 | COPY_PHASE_STRIP = NO;
302 | DEBUG_INFORMATION_FORMAT = dwarf;
303 | ENABLE_STRICT_OBJC_MSGSEND = YES;
304 | ENABLE_TESTABILITY = YES;
305 | GCC_C_LANGUAGE_STANDARD = gnu99;
306 | GCC_DYNAMIC_NO_PIC = NO;
307 | GCC_NO_COMMON_BLOCKS = YES;
308 | GCC_OPTIMIZATION_LEVEL = 0;
309 | GCC_PREPROCESSOR_DEFINITIONS = (
310 | "DEBUG=1",
311 | "$(inherited)",
312 | );
313 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
314 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
315 | GCC_WARN_UNDECLARED_SELECTOR = YES;
316 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
317 | GCC_WARN_UNUSED_FUNCTION = YES;
318 | GCC_WARN_UNUSED_VARIABLE = YES;
319 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
320 | MTL_ENABLE_DEBUG_INFO = YES;
321 | ONLY_ACTIVE_ARCH = YES;
322 | SDKROOT = iphoneos;
323 | };
324 | name = Debug;
325 | };
326 | 5AB106E41D178926003E69E4 /* Release */ = {
327 | isa = XCBuildConfiguration;
328 | buildSettings = {
329 | ALWAYS_SEARCH_USER_PATHS = NO;
330 | CLANG_ANALYZER_NONNULL = YES;
331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
332 | CLANG_CXX_LIBRARY = "libc++";
333 | CLANG_ENABLE_MODULES = YES;
334 | CLANG_ENABLE_OBJC_ARC = YES;
335 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
336 | CLANG_WARN_BOOL_CONVERSION = YES;
337 | CLANG_WARN_COMMA = YES;
338 | CLANG_WARN_CONSTANT_CONVERSION = YES;
339 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
340 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
341 | CLANG_WARN_EMPTY_BODY = YES;
342 | CLANG_WARN_ENUM_CONVERSION = YES;
343 | CLANG_WARN_INFINITE_RECURSION = YES;
344 | CLANG_WARN_INT_CONVERSION = YES;
345 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
346 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
347 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
348 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
349 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
350 | CLANG_WARN_STRICT_PROTOTYPES = YES;
351 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
352 | CLANG_WARN_UNREACHABLE_CODE = YES;
353 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
354 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
355 | COPY_PHASE_STRIP = NO;
356 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
357 | ENABLE_NS_ASSERTIONS = NO;
358 | ENABLE_STRICT_OBJC_MSGSEND = YES;
359 | GCC_C_LANGUAGE_STANDARD = gnu99;
360 | GCC_NO_COMMON_BLOCKS = YES;
361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
363 | GCC_WARN_UNDECLARED_SELECTOR = YES;
364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
365 | GCC_WARN_UNUSED_FUNCTION = YES;
366 | GCC_WARN_UNUSED_VARIABLE = YES;
367 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
368 | MTL_ENABLE_DEBUG_INFO = NO;
369 | SDKROOT = iphoneos;
370 | VALIDATE_PRODUCT = YES;
371 | };
372 | name = Release;
373 | };
374 | 5AB106E61D178926003E69E4 /* Debug */ = {
375 | isa = XCBuildConfiguration;
376 | buildSettings = {
377 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
378 | CODE_SIGN_IDENTITY = "iPhone Developer";
379 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
380 | DEVELOPMENT_TEAM = E83AC9WR2F;
381 | INFOPLIST_FILE = FTFoldingTableView/Info.plist;
382 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
383 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
384 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.FTPageController;
385 | PRODUCT_NAME = "$(TARGET_NAME)";
386 | };
387 | name = Debug;
388 | };
389 | 5AB106E71D178926003E69E4 /* Release */ = {
390 | isa = XCBuildConfiguration;
391 | buildSettings = {
392 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
393 | CODE_SIGN_IDENTITY = "iPhone Developer";
394 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
395 | DEVELOPMENT_TEAM = E83AC9WR2F;
396 | INFOPLIST_FILE = FTFoldingTableView/Info.plist;
397 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
398 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
399 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.FTPageController;
400 | PRODUCT_NAME = "$(TARGET_NAME)";
401 | };
402 | name = Release;
403 | };
404 | 5AB106E91D178926003E69E4 /* Debug */ = {
405 | isa = XCBuildConfiguration;
406 | buildSettings = {
407 | INFOPLIST_FILE = FTFoldingTableViewUITests/Info.plist;
408 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
409 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.FTFoldingTableViewUITests;
410 | PRODUCT_NAME = "$(TARGET_NAME)";
411 | TEST_TARGET_NAME = FTFoldingTableView;
412 | };
413 | name = Debug;
414 | };
415 | 5AB106EA1D178926003E69E4 /* Release */ = {
416 | isa = XCBuildConfiguration;
417 | buildSettings = {
418 | INFOPLIST_FILE = FTFoldingTableViewUITests/Info.plist;
419 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
420 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.FTFoldingTableViewUITests;
421 | PRODUCT_NAME = "$(TARGET_NAME)";
422 | TEST_TARGET_NAME = FTFoldingTableView;
423 | };
424 | name = Release;
425 | };
426 | /* End XCBuildConfiguration section */
427 |
428 | /* Begin XCConfigurationList section */
429 | 5AB106BE1D178925003E69E4 /* Build configuration list for PBXProject "FTFoldingTableView" */ = {
430 | isa = XCConfigurationList;
431 | buildConfigurations = (
432 | 5AB106E31D178926003E69E4 /* Debug */,
433 | 5AB106E41D178926003E69E4 /* Release */,
434 | );
435 | defaultConfigurationIsVisible = 0;
436 | defaultConfigurationName = Release;
437 | };
438 | 5AB106E51D178926003E69E4 /* Build configuration list for PBXNativeTarget "FTFoldingTableView" */ = {
439 | isa = XCConfigurationList;
440 | buildConfigurations = (
441 | 5AB106E61D178926003E69E4 /* Debug */,
442 | 5AB106E71D178926003E69E4 /* Release */,
443 | );
444 | defaultConfigurationIsVisible = 0;
445 | defaultConfigurationName = Release;
446 | };
447 | 5AB106E81D178926003E69E4 /* Build configuration list for PBXNativeTarget "FTFoldingTableViewUITests" */ = {
448 | isa = XCConfigurationList;
449 | buildConfigurations = (
450 | 5AB106E91D178926003E69E4 /* Debug */,
451 | 5AB106EA1D178926003E69E4 /* Release */,
452 | );
453 | defaultConfigurationIsVisible = 0;
454 | defaultConfigurationName = Release;
455 | };
456 | /* End XCConfigurationList section */
457 | };
458 | rootObject = 5AB106BB1D178925003E69E4 /* Project object */;
459 | }
460 |
--------------------------------------------------------------------------------
/FTFoldingTableView/FTFoldingTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // FTFoldingTableView.m
3 | // FTFoldingTableView
4 | //
5 | // Created by liufengting on 16/6/20.
6 | // Copyright © 2016 LiuFengting . All rights reserved.
7 | //
8 |
9 | #import "FTFoldingTableView.h"
10 |
11 | #pragma mark - Constants
12 | /**
13 | * Constants
14 | */
15 | #define FTFoldingDefaultMargin 8.0f
16 | #define FTFoldingDefaultIconSize 24.0f
17 | #define FTFoldingDefaultSepertorLineWidth 0.3f
18 |
19 | #pragma mark - FTFoldingTableView
20 | /**
21 | * FTFoldingTableView
22 | */
23 | @interface FTFoldingTableView ()
24 |
25 | @property (nonatomic, strong) NSMutableArray *statusArray;
26 |
27 | @end
28 |
29 | @implementation FTFoldingTableView
30 |
31 | #pragma mark - Initial Methods
32 |
33 | - (instancetype)init {
34 | self = [super init];
35 | if (self) {
36 | [self setupDelegateAndDataSource];
37 | }
38 | return self;
39 | }
40 |
41 | - (instancetype)initWithFrame:(CGRect)frame {
42 | self = [super initWithFrame:frame];
43 | if (self) {
44 | [self setupDelegateAndDataSource];
45 | }
46 | return self;
47 | }
48 |
49 | - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
50 | self = [super initWithFrame:frame style:style];
51 | if (self) {
52 | [self setupDelegateAndDataSource];
53 | }
54 | return self;
55 | }
56 |
57 | - (instancetype)initWithCoder:(NSCoder *)aDecoder {
58 | self = [super initWithCoder:aDecoder];
59 | if (self) {
60 | [self setupDelegateAndDataSource];
61 | }
62 | return self;
63 | }
64 |
65 | #pragma mark - Setup Methods
66 |
67 | - (void)setupDelegateAndDataSource {
68 | self.delegate = self;
69 | self.dataSource = self;
70 | if (self.style == UITableViewStylePlain) {
71 | self.tableFooterView = [[UIView alloc] init];
72 | }
73 | [[NSNotificationCenter defaultCenter] addObserver:self
74 | selector:@selector(onChangeStatusBarOrientationNotification:)
75 | name:UIApplicationDidChangeStatusBarOrientationNotification
76 | object:nil];
77 | }
78 |
79 | - (NSMutableArray *)statusArray {
80 | if (!_statusArray) {
81 | _statusArray = [NSMutableArray array];
82 | }
83 | if (_statusArray.count) {
84 | if (_statusArray.count > self.numberOfSections) {
85 | [_statusArray removeObjectsInRange:NSMakeRange(self.numberOfSections - 1, _statusArray.count - self.numberOfSections)];
86 | }else if (_statusArray.count < self.numberOfSections) {
87 | for (NSInteger i = self.numberOfSections - _statusArray.count; i < self.numberOfSections; i++) {
88 | [_statusArray addObject:[NSNumber numberWithInteger:FTFoldingSectionStateFold]];
89 | }
90 | }
91 | }else{
92 | for (NSInteger i = 0; i < self.numberOfSections; i++) {
93 | [_statusArray addObject:[NSNumber numberWithInteger:FTFoldingSectionStateFold]];
94 | }
95 | }
96 | return _statusArray;
97 | }
98 |
99 | - (void)onChangeStatusBarOrientationNotification:(NSNotification *)notification {
100 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
101 | [self reloadData];
102 | });
103 | }
104 |
105 | #pragma mark - UI Configration
106 |
107 | - (FTFoldingSectionHeaderArrowPosition )perferedArrowPosition {
108 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(perferedArrowPositionForFTFoldingTableView:)]) {
109 | return [_foldingDelegate perferedArrowPositionForFTFoldingTableView:self];
110 | }
111 | return FTFoldingSectionHeaderArrowPositionRight;
112 | }
113 |
114 | - (UIColor *)backgroundColorForSection:(NSInteger )section {
115 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:backgroundColorForHeaderInSection:)]) {
116 | return [_foldingDelegate ftFoldingTableView:self backgroundColorForHeaderInSection:section];
117 | }
118 | return [UIColor colorWithRed:102/255.f green:102/255.f blue:255/255.f alpha:1.f];
119 | }
120 |
121 | - (NSString *)titleForSection:(NSInteger )section {
122 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:titleForHeaderInSection:)]) {
123 | return [_foldingDelegate ftFoldingTableView:self titleForHeaderInSection:section];
124 | }
125 | return [NSString string];
126 | }
127 |
128 | - (UIFont *)titleFontForSection:(NSInteger )section {
129 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:fontForTitleInSection:)]) {
130 | return [_foldingDelegate ftFoldingTableView:self fontForTitleInSection:section];
131 | }
132 | return [UIFont boldSystemFontOfSize:16];
133 | }
134 |
135 | - (UIColor *)titleColorForSection:(NSInteger )section {
136 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:textColorForTitleInSection:)]) {
137 | return [_foldingDelegate ftFoldingTableView:self textColorForTitleInSection:section];
138 | }
139 | return [UIColor whiteColor];
140 | }
141 |
142 | - (NSString *)descriptionForSection:(NSInteger )section {
143 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:descriptionForHeaderInSection:)]) {
144 | return [_foldingDelegate ftFoldingTableView:self descriptionForHeaderInSection:section];
145 | }
146 | return [NSString string];
147 | }
148 |
149 | - (UIFont *)descriptionFontForSection:(NSInteger )section {
150 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:fontForDescriptionInSection:)]) {
151 | return [_foldingDelegate ftFoldingTableView:self fontForDescriptionInSection:section];
152 | }
153 | return [UIFont systemFontOfSize:13];
154 | }
155 |
156 | - (UIColor *)descriptionColorForSection:(NSInteger )section {
157 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:textColorForDescriptionInSection:)]) {
158 | return [_foldingDelegate ftFoldingTableView:self textColorForDescriptionInSection:section];
159 | }
160 | return [UIColor whiteColor];
161 | }
162 |
163 | - (UIImage *)arrowImageForSection:(NSInteger )section {
164 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:arrowImageForSection:)]) {
165 | return [_foldingDelegate ftFoldingTableView:self arrowImageForSection:section];
166 | }
167 | return [UIImage imageNamed:@"Arrowhead"];
168 | }
169 |
170 | #pragma mark - UITableViewDelegate,UITableViewDataSource
171 |
172 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
173 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(numberOfSectionForFTFoldingTableView:)]) {
174 | return [_foldingDelegate numberOfSectionForFTFoldingTableView:self];
175 | }else{
176 | return self.numberOfSections;
177 | }
178 | }
179 |
180 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
181 | if (((NSNumber *)self.statusArray[section]).integerValue == FTFoldingSectionStateExpand) {
182 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:numberOfRowsInSection:)]) {
183 | return [_foldingDelegate ftFoldingTableView:self numberOfRowsInSection:section];
184 | }
185 | }
186 | return 0;
187 | }
188 |
189 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
190 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:heightForHeaderInSection:)]) {
191 | return [_foldingDelegate ftFoldingTableView:self heightForHeaderInSection:section];
192 | }else{
193 | return self.sectionHeaderHeight;
194 | }
195 | }
196 |
197 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
198 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:heightForRowAtIndexPath:)]) {
199 | return [_foldingDelegate ftFoldingTableView:self heightForRowAtIndexPath:indexPath];
200 | }else{
201 | return self.rowHeight;
202 | }
203 | }
204 |
205 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
206 | if (self.style == UITableViewStylePlain) {
207 | return 0;
208 | }else{
209 | return 0.01;
210 | }
211 | }
212 |
213 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
214 | FTFoldingSectionHeader *sectionHeaderView = [[FTFoldingSectionHeader alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, [self tableView:self heightForHeaderInSection:section])
215 | withTag:section];
216 |
217 | [sectionHeaderView setupWithBackgroundColor:[self backgroundColorForSection:section]
218 | titleString:[self titleForSection:section]
219 | titleColor:[self titleColorForSection:section]
220 | titleFont:[self titleFontForSection:section]
221 | descriptionString:[self descriptionForSection:section]
222 | descriptionColor:[self descriptionColorForSection:section]
223 | descriptionFont:[self descriptionFontForSection:section]
224 | arrowImage:[self arrowImageForSection:section]
225 | arrowPosition:[self perferedArrowPosition]
226 | sectionState:((NSNumber *)self.statusArray[section]).integerValue];
227 |
228 | sectionHeaderView.tapDelegate = self;
229 |
230 | return sectionHeaderView;
231 | }
232 |
233 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
234 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:cellForRowAtIndexPath:)]) {
235 | return [_foldingDelegate ftFoldingTableView:self cellForRowAtIndexPath:indexPath];
236 | }
237 | return [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"DefaultCellIndentifier"];
238 | }
239 |
240 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
241 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:didSelectRowAtIndexPath:)]) {
242 | [_foldingDelegate ftFoldingTableView:self didSelectRowAtIndexPath:indexPath];
243 | }
244 | }
245 |
246 | - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
247 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:didDeselectRowAtIndexPath:)]) {
248 | [_foldingDelegate ftFoldingTableView:self didDeselectRowAtIndexPath:indexPath];
249 | }
250 | }
251 |
252 | #pragma mark - FTFoldingSectionHeaderDelegate
253 |
254 | - (void)ftFoldingSectionHeaderTappedAtIndex:(NSInteger)index {
255 | BOOL currentIsOpen = ((NSNumber *)self.statusArray[index]).boolValue;
256 |
257 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:willChangeToSectionState:section:)]) {
258 | [_foldingDelegate ftFoldingTableView:self
259 | willChangeToSectionState:(currentIsOpen == YES) ? FTFoldingSectionStateFold : FTFoldingSectionStateExpand
260 | section:index];
261 | }
262 |
263 | [self.statusArray replaceObjectAtIndex:index withObject:[NSNumber numberWithBool:!currentIsOpen]];
264 |
265 | NSInteger numberOfRow = [_foldingDelegate ftFoldingTableView:self numberOfRowsInSection:index];
266 | NSMutableArray *rowArray = [NSMutableArray array];
267 | if (numberOfRow) {
268 | for (NSInteger i = 0; i < numberOfRow; i++) {
269 | [rowArray addObject:[NSIndexPath indexPathForRow:i inSection:index]];
270 | }
271 | }
272 | if (rowArray.count) {
273 | if (currentIsOpen) {
274 | [self deleteRowsAtIndexPaths:[NSArray arrayWithArray:rowArray] withRowAnimation:UITableViewRowAnimationTop];
275 | }else{
276 | [self insertRowsAtIndexPaths:[NSArray arrayWithArray:rowArray] withRowAnimation:UITableViewRowAnimationTop];
277 | }
278 | }
279 | if (_foldingDelegate && [_foldingDelegate respondsToSelector:@selector(ftFoldingTableView:didChangeToSectionState:section:)]) {
280 | [_foldingDelegate ftFoldingTableView:self
281 | didChangeToSectionState:(currentIsOpen == YES) ? FTFoldingSectionStateFold : FTFoldingSectionStateExpand
282 | section:index];
283 | }
284 | }
285 |
286 | - (FTFoldingSectionState)foldingStateForSection:(NSInteger)section {
287 | if (section <= self.statusArray.count - 1) {
288 | return ((NSNumber *)self.statusArray[section]).integerValue;
289 | }
290 | return FTFoldingSectionStateFold;
291 | }
292 |
293 | - (void)expandSection:(NSInteger)section {
294 | if ([self foldingStateForSection:section] == FTFoldingSectionStateFold) {
295 | [self ftFoldingSectionHeaderTappedAtIndex:section];
296 | }
297 | }
298 |
299 | - (void)foldSection:(NSInteger)section {
300 | if ([self foldingStateForSection:section] == FTFoldingSectionStateExpand) {
301 | [self ftFoldingSectionHeaderTappedAtIndex:section];
302 | }
303 | }
304 |
305 | - (void)expandAllSections {
306 | [self.statusArray enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
307 | if (obj.integerValue == FTFoldingSectionStateFold) {
308 | [self ftFoldingSectionHeaderTappedAtIndex:idx];
309 | }
310 | }];
311 | }
312 |
313 | - (void)foldAllSections {
314 | [self.statusArray enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
315 | if (obj.boolValue == FTFoldingSectionStateExpand) {
316 | [self ftFoldingSectionHeaderTappedAtIndex:idx];
317 | }
318 | }];
319 | }
320 |
321 | @end
322 |
323 | #pragma mark - FTFoldingSectionHeader
324 | /**
325 | * FTFoldingSectionHeader
326 | */
327 | @interface FTFoldingSectionHeader ()
328 |
329 | @property (nonatomic, strong)UILabel *titleLabel;
330 | @property (nonatomic, strong)UILabel *descriptionLabel;
331 | @property (nonatomic, strong)UIImageView *arrowImageView;
332 | @property (nonatomic, strong)UIView *sepertorLine;
333 | @property (nonatomic, assign)FTFoldingSectionHeaderArrowPosition arrowPosition;
334 | @property (nonatomic, assign)FTFoldingSectionState sectionState;
335 | @property (nonatomic, strong)UITapGestureRecognizer *tapGesture;
336 |
337 | @end
338 |
339 | @implementation FTFoldingSectionHeader
340 |
341 | - (instancetype)initWithFrame:(CGRect)frame withTag:(NSInteger)tag {
342 | self = [super initWithFrame:frame];
343 | if (self) {
344 | self.tag = tag;
345 | [self setupSubviewsWithArrowPosition:FTFoldingSectionHeaderArrowPositionRight];
346 | }
347 | return self;
348 | }
349 |
350 | - (void)awakeFromNib {
351 | [super awakeFromNib];
352 | [self setupSubviewsWithArrowPosition:FTFoldingSectionHeaderArrowPositionRight];
353 |
354 | }
355 |
356 | - (UILabel *)titleLabel {
357 | if (!_titleLabel) {
358 | _titleLabel = [[UILabel alloc]initWithFrame:CGRectZero];
359 | _titleLabel.backgroundColor = [UIColor clearColor];
360 | _titleLabel.textAlignment = NSTextAlignmentLeft;
361 | }
362 | return _titleLabel;
363 | }
364 |
365 | - (UILabel *)descriptionLabel {
366 | if (!_descriptionLabel) {
367 | _descriptionLabel = [[UILabel alloc]initWithFrame:CGRectZero];
368 | _descriptionLabel.backgroundColor = [UIColor clearColor];
369 | _descriptionLabel.textAlignment = NSTextAlignmentRight;
370 | }
371 | return _descriptionLabel;
372 | }
373 |
374 | - (UIImageView *)arrowImageView {
375 | if (!_arrowImageView) {
376 | _arrowImageView = [[UIImageView alloc]initWithFrame:CGRectZero];
377 | _arrowImageView.backgroundColor = [UIColor clearColor];
378 | _arrowImageView.contentMode = UIViewContentModeScaleAspectFit;
379 | }
380 | return _arrowImageView;
381 | }
382 |
383 | - (UIView *)sepertorLine {
384 | if (!_sepertorLine) {
385 | _sepertorLine = [[UIView alloc]initWithFrame:CGRectZero];
386 | _sepertorLine.backgroundColor = [UIColor whiteColor];
387 | }
388 | return _sepertorLine;
389 | }
390 |
391 | - (UITapGestureRecognizer *)tapGesture {
392 | if (!_tapGesture) {
393 | _tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(onTapped:)];
394 | }
395 | return _tapGesture;
396 | }
397 |
398 | - (void)setupWithBackgroundColor:(UIColor *)backgroundColor
399 | titleString:(NSString *)titleString
400 | titleColor:(UIColor *)titleColor
401 | titleFont:(UIFont *)titleFont
402 | descriptionString:(NSString *)descriptionString
403 | descriptionColor:(UIColor *)descriptionColor
404 | descriptionFont:(UIFont *)descriptionFont
405 | arrowImage:(UIImage *)arrowImage
406 | arrowPosition:(FTFoldingSectionHeaderArrowPosition)arrowPosition
407 | sectionState:(FTFoldingSectionState)sectionState {
408 | [self setBackgroundColor:backgroundColor];
409 |
410 | [self setupSubviewsWithArrowPosition:arrowPosition];
411 |
412 | self.titleLabel.text = titleString;
413 | self.titleLabel.textColor = titleColor;
414 | self.titleLabel.font = titleFont;
415 |
416 | self.descriptionLabel.text = descriptionString;
417 | self.descriptionLabel.textColor = descriptionColor;
418 | self.descriptionLabel.font = descriptionFont;
419 |
420 | self.arrowImageView.image = arrowImage;
421 | self.arrowPosition = arrowPosition;
422 | self.sectionState = sectionState;
423 |
424 | if (sectionState == FTFoldingSectionStateExpand) {
425 | if (self.arrowPosition == FTFoldingSectionHeaderArrowPositionRight) {
426 | self.arrowImageView.transform = CGAffineTransformMakeRotation(-M_PI/2);
427 | }else{
428 | self.arrowImageView.transform = CGAffineTransformMakeRotation(M_PI/2);
429 | }
430 | } else {
431 | if (self.arrowPosition == FTFoldingSectionHeaderArrowPositionRight) {
432 | _arrowImageView.transform = CGAffineTransformMakeRotation(M_PI/2);
433 | }else{
434 | self.arrowImageView.transform = CGAffineTransformMakeRotation(0);
435 | }
436 | }
437 |
438 | }
439 |
440 | - (void)setupSubviewsWithArrowPosition:(FTFoldingSectionHeaderArrowPosition)arrowPosition {
441 | CGFloat labelWidth = (self.frame.size.width - FTFoldingDefaultMargin*2 - FTFoldingDefaultIconSize)/2;
442 | CGFloat labelHeight = self.frame.size.height;
443 | CGRect arrowRect = CGRectMake(0, (self.frame.size.height - FTFoldingDefaultIconSize)/2, FTFoldingDefaultIconSize, FTFoldingDefaultIconSize);
444 | CGRect titleRect = CGRectMake(FTFoldingDefaultMargin + FTFoldingDefaultIconSize, 0, labelWidth, labelHeight);
445 | CGRect descriptionRect = CGRectMake(FTFoldingDefaultMargin + FTFoldingDefaultIconSize + labelWidth, 0, labelWidth, labelHeight);
446 | CGRect lineRect = CGRectMake(0, self.bounds.size.height - FTFoldingDefaultSepertorLineWidth, self.bounds.size.width, FTFoldingDefaultSepertorLineWidth);
447 | if (arrowPosition == FTFoldingSectionHeaderArrowPositionRight) {
448 | arrowRect.origin.x = FTFoldingDefaultMargin*2 + labelWidth*2;
449 | titleRect.origin.x = FTFoldingDefaultMargin;
450 | descriptionRect.origin.x = FTFoldingDefaultMargin + labelWidth;
451 | }
452 |
453 | [self.titleLabel setFrame:titleRect];
454 | [self.descriptionLabel setFrame:descriptionRect];
455 | [self.arrowImageView setFrame:arrowRect];
456 | [self.sepertorLine setFrame:lineRect];
457 |
458 |
459 | [self addSubview:self.titleLabel];
460 | [self addSubview:self.descriptionLabel];
461 | [self addSubview:self.arrowImageView];
462 | [self addGestureRecognizer:self.tapGesture];
463 | [self addSubview:self.sepertorLine];
464 |
465 | }
466 |
467 | - (void)shouldExpand:(BOOL)shouldExpand {
468 |
469 | [UIView animateWithDuration:0.2
470 | animations:^{
471 | if (shouldExpand) {
472 | if (self.arrowPosition == FTFoldingSectionHeaderArrowPositionRight) {
473 | self.arrowImageView.transform = CGAffineTransformMakeRotation(-M_PI/2);
474 | }else{
475 | self.arrowImageView.transform = CGAffineTransformMakeRotation(M_PI/2);
476 | }
477 | } else {
478 | if (self.arrowPosition == FTFoldingSectionHeaderArrowPositionRight) {
479 | self.arrowImageView.transform = CGAffineTransformMakeRotation(M_PI/2);
480 | }else{
481 | self.arrowImageView.transform = CGAffineTransformMakeRotation(0);
482 | }
483 | }
484 | } completion:^(BOOL finished) {
485 | if (finished == YES) {
486 | self.sepertorLine.hidden = shouldExpand;
487 | }
488 | }];
489 | }
490 |
491 | - (void)onTapped:(UITapGestureRecognizer *)gesture {
492 | [self shouldExpand:![NSNumber numberWithInteger:self.sectionState].boolValue];
493 | if (_tapDelegate && [_tapDelegate respondsToSelector:@selector(ftFoldingSectionHeaderTappedAtIndex:)]) {
494 | self.sectionState = [NSNumber numberWithInteger:(![NSNumber numberWithInteger:self.sectionState].boolValue)].integerValue;
495 | [_tapDelegate ftFoldingSectionHeaderTappedAtIndex:self.tag];
496 | }
497 | }
498 |
499 | @end
500 |
501 |
--------------------------------------------------------------------------------