├── .gitignore
├── AccordionTableViewController.podspec
├── Classes
├── AccordionTableViewController.swift
└── SectionHeaderView.xib
├── Demo
├── AccordionExample.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
└── AccordionExample
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Contents.json
│ ├── carat-open.imageset
│ │ ├── Contents.json
│ │ └── Sort Down Filled-30-2.png
│ ├── carat.imageset
│ │ ├── Contents.json
│ │ └── Sort Right Filled-30-2.png
│ ├── facebook.imageset
│ │ ├── Contents.json
│ │ └── facebook.png
│ ├── linkedin.imageset
│ │ ├── Contents.json
│ │ └── linkedin.png
│ └── twitter.imageset
│ │ ├── Contents.json
│ │ └── twitter.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── SectionFactory.swift
│ ├── SectionViewController.swift
│ └── ViewController.swift
├── LICENSE
├── README.md
└── demo.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | # Pods/
27 |
28 | # Carthage
29 | #
30 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
31 | # Carthage/Checkouts
32 |
33 | Carthage/Build
34 |
35 | Example/.idea/.name
36 |
37 | Example/.idea/encodings.xml
38 |
39 | Example/.idea/Example.iml
40 |
41 | Example/.idea/modules.xml
42 |
43 | Example/.idea/scopes/scope_settings.xml
44 |
45 | Example/.idea/vcs.xml
46 |
47 | Example/.idea/workspace.xml
48 |
49 | Example/.idea/xcode.xml
50 |
--------------------------------------------------------------------------------
/AccordionTableViewController.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "AccordionTableViewController"
4 | s.version = "0.0.3"
5 | s.summary = "Accordion UITableViewController"
6 | s.description = <<-DESC
7 | Swift version of https://github.com/klevison/KMAccordionTableViewController
8 | DESC
9 | s.homepage = "https://github.com/klevison/AccordionTableViewController"
10 | s.screenshots = "http://dl.dropbox.com/u/378729/MBProgressHUD/1.png"
11 | s.license = { :type => 'MIT', :file => 'LICENSE' }
12 | s.author = { "Klevison Matias" => "klevison@gmail.com" }
13 | s.source = { :git => "https://github.com/klevison/AccordionTableViewController.git", :tag => s.version.to_s }
14 | s.social_media_url = 'https://twitter.com/klevison'
15 |
16 | s.platform = :ios, '8.0'
17 | s.requires_arc = true
18 |
19 | s.source_files = "Classes", "Classes/**/*.{swift}"
20 | s.resource_bundles = {
21 | 'AccordionTableViewController' => ['Classes/**/*.{xib,png,nib}']
22 | }
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/Classes/AccordionTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Accordion.swift
3 | // AccordionTableViewController
4 | //
5 | // Created by Klevison Matias on 1/6/17.
6 | // Copyright © 2017 Klevison. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | //MARK: AccordionTableViewController
12 |
13 | protocol AccordionTableViewControllerDelegate: class {
14 | func accordionTableViewControllerSectionDidOpen(section: Section)
15 | func accordionTableViewControllerSectionDidClose(section: Section)
16 | }
17 |
18 | class AccordionTableViewController: UITableViewController {
19 |
20 | var openAnimation: UITableViewRowAnimation = .fade
21 | var closeAnimation: UITableViewRowAnimation = .fade
22 | var sections = [Section]()
23 | var oneSectionAlwaysOpen = false
24 | weak var delegate: AccordionTableViewControllerDelegate?
25 | fileprivate let sectionHeaderViewIdentifier = "SectionHeaderViewIdentifier"
26 | fileprivate let sectionCellID = "CellIdentifier"
27 | var openedSection: Section? {
28 | return sections
29 | .filter { $0.open == true }
30 | .first
31 | }
32 |
33 | override func viewDidLoad() {
34 | super.viewDidLoad()
35 |
36 | setupTableView()
37 | }
38 |
39 | private func setupTableView() {
40 | let sectionHeaderNib = UINib(nibName: "SectionHeaderView", bundle: nil)
41 | tableView.register(sectionHeaderNib, forHeaderFooterViewReuseIdentifier: sectionHeaderViewIdentifier)
42 | tableView.bounces = false
43 | tableView.separatorStyle = .none
44 | }
45 |
46 | func reloadOpenedSection() {
47 | openedSection
48 | .flatMap { [IndexPath(row: 0, section: $0.sectionIndex!)] }
49 | .map { tableView.reloadRows(at: $0, with: openAnimation) }
50 | }
51 |
52 | private func indexPathsToDelete() -> [IndexPath] {
53 | if let previousOpenSection = openedSection, let previousOpenSectionIndex = previousOpenSection.sectionIndex {
54 | return [IndexPath(row: 0, section: previousOpenSectionIndex)]
55 | }
56 |
57 | return [IndexPath]()
58 | }
59 |
60 | private func updateTable(insert indexPathsToInsert: [IndexPath], delete indexPathsToDelete: [IndexPath]) {
61 | tableView.beginUpdates()
62 | tableView.insertRows(at: indexPathsToInsert, with: openAnimation)
63 | tableView.deleteRows(at: indexPathsToDelete, with: closeAnimation)
64 | tableView.endUpdates()
65 |
66 | let sectionRect = tableView.rect(forSection: indexPathsToInsert[0].section)
67 | tableView.scrollRectToVisible(sectionRect, animated: true)
68 |
69 | if let index = indexPathsToInsert.first?.section {
70 | delegate?.accordionTableViewControllerSectionDidOpen(section: sections[index])
71 | }
72 | if let index = indexPathsToDelete.first?.section {
73 | delegate?.accordionTableViewControllerSectionDidClose(section: sections[index])
74 | }
75 |
76 | }
77 |
78 | func openSection(at index: Int) {
79 | let indexPathsToInsert = [IndexPath(row: 0, section: index)]
80 | let indexPathsToDelete = self.indexPathsToDelete()
81 |
82 | if let previousOpenSection = openedSection, let previousOpenSectionIndex = previousOpenSection.sectionIndex {
83 | previousOpenSection.open = false
84 | guard let praviousSectionHeaderView = tableView.headerView(forSection: previousOpenSectionIndex) as? SectionHeaderView else {
85 | return
86 | }
87 | praviousSectionHeaderView.disclosureButton.isSelected = false
88 | delegate?.accordionTableViewControllerSectionDidClose(section: previousOpenSection)
89 | }
90 | sections[index].open = true
91 | updateTable(insert: indexPathsToInsert, delete: indexPathsToDelete)
92 | }
93 |
94 | func closeSection(at index: Int) {
95 | let currentSection = sections[index]
96 | currentSection.open = false
97 | if tableView.numberOfRows(inSection: index) > 0 {
98 | var indexPathsToDelete = [IndexPath]()
99 | indexPathsToDelete.append(IndexPath(row: 0, section: index))
100 | tableView.deleteRows(at: indexPathsToDelete, with: closeAnimation)
101 | }
102 | delegate?.accordionTableViewControllerSectionDidClose(section: currentSection)
103 | }
104 |
105 | }
106 |
107 | extension AccordionTableViewController {
108 |
109 | override func numberOfSections(in tableView: UITableView) -> Int {
110 | return sections.count
111 | }
112 |
113 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
114 | if sections[section].open {
115 | return 1
116 | }
117 |
118 | return 0
119 | }
120 |
121 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
122 | let section = sections[indexPath.section]
123 | let cellIdentifier = "\(sectionCellID)\(section.sectionIndex!)"
124 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier)
125 | let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
126 | cell.contentView.addSubview(section.view!)
127 | cell.contentView.autoresizesSubviews = false
128 | cell.contentView.frame = section.view!.frame
129 |
130 | return cell
131 | }
132 |
133 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
134 | return sections[indexPath.section].view?.frame.size.height ?? 0
135 | }
136 |
137 | override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
138 | return sections[section].appearance.headerHeight
139 | }
140 |
141 | override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
142 | return false
143 | }
144 |
145 | override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
146 | guard let sectionHeaderView = tableView.dequeueReusableHeaderFooterView(withIdentifier: sectionHeaderViewIdentifier) as? SectionHeaderView else {
147 | return nil
148 | }
149 | let currentSection = sections[section]
150 | if currentSection.backgroundColor != nil {
151 | currentSection.appearance.headerColor = currentSection.backgroundColor!
152 | }
153 |
154 | currentSection.sectionIndex = section
155 | currentSection.headerView = sectionHeaderView
156 | sectionHeaderView.headerSectionAppearence = currentSection.appearance
157 | sectionHeaderView.titleLabel.text = currentSection.title
158 | sectionHeaderView.section = section
159 | sectionHeaderView.delegate = self
160 | sectionHeaderView.disclosureButton.isSelected = currentSection.open
161 |
162 | //TODO: refact it
163 | if let overlayView = currentSection.overlayView {
164 | sectionHeaderView.addOverHeaderSubView(view: overlayView)
165 | }
166 |
167 | if oneSectionAlwaysOpen && section == 0 && openedSection == nil{
168 | openSection(at: section)
169 | sectionHeaderView.disclosureButton.isSelected = true
170 | }
171 |
172 | return sectionHeaderView
173 | }
174 |
175 | }
176 |
177 | extension AccordionTableViewController: SectionHeaderViewDelegate {
178 |
179 | func sectionHeaderView(sectionHeaderView: SectionHeaderView, selectedAtIndex index: Int) {
180 | let section = sections[index]
181 | if !section.open {
182 | openSection(at: index)
183 | sectionHeaderView.disclosureButton.isSelected = true
184 | } else if !oneSectionAlwaysOpen {
185 | closeSection(at: index)
186 | sectionHeaderView.disclosureButton.isSelected = oneSectionAlwaysOpen && openedSection?.sectionIndex == index
187 | }
188 | }
189 |
190 | }
191 |
192 | //MARK: Section
193 |
194 | final class Section {
195 |
196 | var open = false
197 | var view: UIView?
198 | var overlayView: UIView?
199 | var headerView: SectionHeaderView?
200 | var title: String?
201 | var backgroundColor: UIColor?
202 | var sectionIndex: Int?
203 | var appearance = Appearance()
204 |
205 | }
206 |
207 | //MARK: Appearance
208 |
209 | final class Appearance {
210 |
211 | var headerHeight = CGFloat(50)
212 | var headerFont = UIFont.systemFont(ofSize: 15)
213 | var headerTitleColor = UIColor.black
214 | var headerColor = UIColor.white
215 | var headerSeparatorColor = UIColor.black
216 | var headerArrowImageOpened = #imageLiteral(resourceName: "carat")
217 | var headerArrowImageClosed = #imageLiteral(resourceName: "carat-open")
218 |
219 | }
220 |
221 | //MARK: SectionHeaderView
222 |
223 | protocol SectionHeaderViewDelegate: class {
224 | func sectionHeaderView(sectionHeaderView: SectionHeaderView, selectedAtIndex index: NSInteger)
225 | }
226 |
227 | final class SectionHeaderView: UITableViewHeaderFooterView {
228 |
229 | @IBOutlet weak var titleLabel: UILabel!
230 | @IBOutlet weak var disclosureButton: UIButton!
231 | @IBOutlet weak var headerSeparatorView: UIView!
232 | @IBOutlet weak var backgroundHeaderView: UIView!
233 | @IBOutlet weak var overHeaderView: UIView!
234 |
235 | weak var delegate: SectionHeaderViewDelegate?
236 | var section: NSInteger?
237 | var headerSectionAppearence: Appearance? {
238 | didSet {
239 | headerSeparatorView.backgroundColor = headerSectionAppearence!.headerSeparatorColor
240 | backgroundHeaderView.backgroundColor = headerSectionAppearence!.headerColor
241 | titleLabel.font = headerSectionAppearence!.headerFont
242 | titleLabel.textColor = headerSectionAppearence!.headerTitleColor
243 | disclosureButton.setImage(headerSectionAppearence!.headerArrowImageOpened, for: .normal)
244 | disclosureButton.setImage(headerSectionAppearence!.headerArrowImageClosed, for: .selected)
245 | }
246 | }
247 |
248 | override func awakeFromNib() {
249 | super.awakeFromNib()
250 |
251 | let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SectionHeaderView.toggleOpen(_:)))
252 | self.addGestureRecognizer(tapGesture)
253 | }
254 |
255 | override func prepareForReuse() {
256 | super.prepareForReuse()
257 |
258 | overHeaderView.subviews.forEach { $0.removeFromSuperview() }
259 | }
260 |
261 | func addOverHeaderSubView(view: UIView) {
262 | self.overHeaderView.addSubview(view)
263 | }
264 |
265 | @IBAction func toggleOpen(_ sender: AnyObject) {
266 | delegate?.sectionHeaderView(sectionHeaderView: self, selectedAtIndex: section!)
267 | }
268 |
269 | }
270 |
--------------------------------------------------------------------------------
/Classes/SectionHeaderView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
36 |
46 |
47 |
48 |
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 |
--------------------------------------------------------------------------------
/Demo/AccordionExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | BE6AFF3E1E269FFD004C7B80 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6AFF3D1E269FFD004C7B80 /* AppDelegate.swift */; };
11 | BE6AFF401E269FFD004C7B80 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6AFF3F1E269FFD004C7B80 /* ViewController.swift */; };
12 | BE6AFF431E269FFD004C7B80 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE6AFF411E269FFD004C7B80 /* Main.storyboard */; };
13 | BE6AFF451E269FFD004C7B80 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE6AFF441E269FFD004C7B80 /* Assets.xcassets */; };
14 | BE6AFF481E269FFD004C7B80 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE6AFF461E269FFD004C7B80 /* LaunchScreen.storyboard */; };
15 | BE6AFF521E26A04B004C7B80 /* AccordionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6AFF501E26A04B004C7B80 /* AccordionTableViewController.swift */; };
16 | BE6AFF531E26A04B004C7B80 /* SectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BE6AFF511E26A04B004C7B80 /* SectionHeaderView.xib */; };
17 | BE6AFF551E26A911004C7B80 /* SectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6AFF541E26A911004C7B80 /* SectionViewController.swift */; };
18 | BE6AFF571E26A943004C7B80 /* SectionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE6AFF561E26A943004C7B80 /* SectionFactory.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | BE6AFF3A1E269FFD004C7B80 /* AccordionExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AccordionExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
23 | BE6AFF3D1E269FFD004C7B80 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
24 | BE6AFF3F1E269FFD004C7B80 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
25 | BE6AFF421E269FFD004C7B80 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
26 | BE6AFF441E269FFD004C7B80 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
27 | BE6AFF471E269FFD004C7B80 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
28 | BE6AFF491E269FFD004C7B80 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
29 | BE6AFF501E26A04B004C7B80 /* AccordionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccordionTableViewController.swift; sourceTree = ""; };
30 | BE6AFF511E26A04B004C7B80 /* SectionHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SectionHeaderView.xib; sourceTree = ""; };
31 | BE6AFF541E26A911004C7B80 /* SectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionViewController.swift; sourceTree = ""; };
32 | BE6AFF561E26A943004C7B80 /* SectionFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionFactory.swift; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | BE6AFF371E269FFD004C7B80 /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | );
41 | runOnlyForDeploymentPostprocessing = 0;
42 | };
43 | /* End PBXFrameworksBuildPhase section */
44 |
45 | /* Begin PBXGroup section */
46 | BE6AFF311E269FFD004C7B80 = {
47 | isa = PBXGroup;
48 | children = (
49 | BE6AFF3C1E269FFD004C7B80 /* AccordionExample */,
50 | BE6AFF3B1E269FFD004C7B80 /* Products */,
51 | );
52 | sourceTree = "";
53 | };
54 | BE6AFF3B1E269FFD004C7B80 /* Products */ = {
55 | isa = PBXGroup;
56 | children = (
57 | BE6AFF3A1E269FFD004C7B80 /* AccordionExample.app */,
58 | );
59 | name = Products;
60 | sourceTree = "";
61 | };
62 | BE6AFF3C1E269FFD004C7B80 /* AccordionExample */ = {
63 | isa = PBXGroup;
64 | children = (
65 | BE6AFF4F1E26A04B004C7B80 /* Classes */,
66 | BE6AFF3D1E269FFD004C7B80 /* AppDelegate.swift */,
67 | BE6AFF3F1E269FFD004C7B80 /* ViewController.swift */,
68 | BE6AFF561E26A943004C7B80 /* SectionFactory.swift */,
69 | BE6AFF541E26A911004C7B80 /* SectionViewController.swift */,
70 | BE6AFF411E269FFD004C7B80 /* Main.storyboard */,
71 | BE6AFF441E269FFD004C7B80 /* Assets.xcassets */,
72 | BE6AFF461E269FFD004C7B80 /* LaunchScreen.storyboard */,
73 | BE6AFF491E269FFD004C7B80 /* Info.plist */,
74 | );
75 | path = AccordionExample;
76 | sourceTree = "";
77 | };
78 | BE6AFF4F1E26A04B004C7B80 /* Classes */ = {
79 | isa = PBXGroup;
80 | children = (
81 | BE6AFF501E26A04B004C7B80 /* AccordionTableViewController.swift */,
82 | BE6AFF511E26A04B004C7B80 /* SectionHeaderView.xib */,
83 | );
84 | name = Classes;
85 | path = ../../Classes;
86 | sourceTree = "";
87 | };
88 | /* End PBXGroup section */
89 |
90 | /* Begin PBXNativeTarget section */
91 | BE6AFF391E269FFD004C7B80 /* AccordionExample */ = {
92 | isa = PBXNativeTarget;
93 | buildConfigurationList = BE6AFF4C1E269FFD004C7B80 /* Build configuration list for PBXNativeTarget "AccordionExample" */;
94 | buildPhases = (
95 | BE6AFF361E269FFD004C7B80 /* Sources */,
96 | BE6AFF371E269FFD004C7B80 /* Frameworks */,
97 | BE6AFF381E269FFD004C7B80 /* Resources */,
98 | );
99 | buildRules = (
100 | );
101 | dependencies = (
102 | );
103 | name = AccordionExample;
104 | productName = AccordionExample;
105 | productReference = BE6AFF3A1E269FFD004C7B80 /* AccordionExample.app */;
106 | productType = "com.apple.product-type.application";
107 | };
108 | /* End PBXNativeTarget section */
109 |
110 | /* Begin PBXProject section */
111 | BE6AFF321E269FFD004C7B80 /* Project object */ = {
112 | isa = PBXProject;
113 | attributes = {
114 | LastSwiftUpdateCheck = 0820;
115 | LastUpgradeCheck = 0820;
116 | ORGANIZATIONNAME = worQ;
117 | TargetAttributes = {
118 | BE6AFF391E269FFD004C7B80 = {
119 | CreatedOnToolsVersion = 8.2.1;
120 | DevelopmentTeam = N88S4A5QL4;
121 | ProvisioningStyle = Automatic;
122 | };
123 | };
124 | };
125 | buildConfigurationList = BE6AFF351E269FFD004C7B80 /* Build configuration list for PBXProject "AccordionExample" */;
126 | compatibilityVersion = "Xcode 3.2";
127 | developmentRegion = English;
128 | hasScannedForEncodings = 0;
129 | knownRegions = (
130 | en,
131 | Base,
132 | );
133 | mainGroup = BE6AFF311E269FFD004C7B80;
134 | productRefGroup = BE6AFF3B1E269FFD004C7B80 /* Products */;
135 | projectDirPath = "";
136 | projectRoot = "";
137 | targets = (
138 | BE6AFF391E269FFD004C7B80 /* AccordionExample */,
139 | );
140 | };
141 | /* End PBXProject section */
142 |
143 | /* Begin PBXResourcesBuildPhase section */
144 | BE6AFF381E269FFD004C7B80 /* Resources */ = {
145 | isa = PBXResourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | BE6AFF481E269FFD004C7B80 /* LaunchScreen.storyboard in Resources */,
149 | BE6AFF451E269FFD004C7B80 /* Assets.xcassets in Resources */,
150 | BE6AFF431E269FFD004C7B80 /* Main.storyboard in Resources */,
151 | BE6AFF531E26A04B004C7B80 /* SectionHeaderView.xib in Resources */,
152 | );
153 | runOnlyForDeploymentPostprocessing = 0;
154 | };
155 | /* End PBXResourcesBuildPhase section */
156 |
157 | /* Begin PBXSourcesBuildPhase section */
158 | BE6AFF361E269FFD004C7B80 /* Sources */ = {
159 | isa = PBXSourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | BE6AFF401E269FFD004C7B80 /* ViewController.swift in Sources */,
163 | BE6AFF521E26A04B004C7B80 /* AccordionTableViewController.swift in Sources */,
164 | BE6AFF551E26A911004C7B80 /* SectionViewController.swift in Sources */,
165 | BE6AFF3E1E269FFD004C7B80 /* AppDelegate.swift in Sources */,
166 | BE6AFF571E26A943004C7B80 /* SectionFactory.swift in Sources */,
167 | );
168 | runOnlyForDeploymentPostprocessing = 0;
169 | };
170 | /* End PBXSourcesBuildPhase section */
171 |
172 | /* Begin PBXVariantGroup section */
173 | BE6AFF411E269FFD004C7B80 /* Main.storyboard */ = {
174 | isa = PBXVariantGroup;
175 | children = (
176 | BE6AFF421E269FFD004C7B80 /* Base */,
177 | );
178 | name = Main.storyboard;
179 | sourceTree = "";
180 | };
181 | BE6AFF461E269FFD004C7B80 /* LaunchScreen.storyboard */ = {
182 | isa = PBXVariantGroup;
183 | children = (
184 | BE6AFF471E269FFD004C7B80 /* Base */,
185 | );
186 | name = LaunchScreen.storyboard;
187 | sourceTree = "";
188 | };
189 | /* End PBXVariantGroup section */
190 |
191 | /* Begin XCBuildConfiguration section */
192 | BE6AFF4A1E269FFD004C7B80 /* Debug */ = {
193 | isa = XCBuildConfiguration;
194 | buildSettings = {
195 | ALWAYS_SEARCH_USER_PATHS = NO;
196 | CLANG_ANALYZER_NONNULL = YES;
197 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
198 | CLANG_CXX_LIBRARY = "libc++";
199 | CLANG_ENABLE_MODULES = YES;
200 | CLANG_ENABLE_OBJC_ARC = YES;
201 | CLANG_WARN_BOOL_CONVERSION = YES;
202 | CLANG_WARN_CONSTANT_CONVERSION = YES;
203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
204 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
205 | CLANG_WARN_EMPTY_BODY = YES;
206 | CLANG_WARN_ENUM_CONVERSION = YES;
207 | CLANG_WARN_INFINITE_RECURSION = YES;
208 | CLANG_WARN_INT_CONVERSION = YES;
209 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
210 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
211 | CLANG_WARN_UNREACHABLE_CODE = YES;
212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
213 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
214 | COPY_PHASE_STRIP = NO;
215 | DEBUG_INFORMATION_FORMAT = dwarf;
216 | ENABLE_STRICT_OBJC_MSGSEND = YES;
217 | ENABLE_TESTABILITY = YES;
218 | GCC_C_LANGUAGE_STANDARD = gnu99;
219 | GCC_DYNAMIC_NO_PIC = NO;
220 | GCC_NO_COMMON_BLOCKS = YES;
221 | GCC_OPTIMIZATION_LEVEL = 0;
222 | GCC_PREPROCESSOR_DEFINITIONS = (
223 | "DEBUG=1",
224 | "$(inherited)",
225 | );
226 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
227 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
228 | GCC_WARN_UNDECLARED_SELECTOR = YES;
229 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
230 | GCC_WARN_UNUSED_FUNCTION = YES;
231 | GCC_WARN_UNUSED_VARIABLE = YES;
232 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
233 | MTL_ENABLE_DEBUG_INFO = YES;
234 | ONLY_ACTIVE_ARCH = YES;
235 | SDKROOT = iphoneos;
236 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
237 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
238 | };
239 | name = Debug;
240 | };
241 | BE6AFF4B1E269FFD004C7B80 /* Release */ = {
242 | isa = XCBuildConfiguration;
243 | buildSettings = {
244 | ALWAYS_SEARCH_USER_PATHS = NO;
245 | CLANG_ANALYZER_NONNULL = YES;
246 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
247 | CLANG_CXX_LIBRARY = "libc++";
248 | CLANG_ENABLE_MODULES = YES;
249 | CLANG_ENABLE_OBJC_ARC = YES;
250 | CLANG_WARN_BOOL_CONVERSION = YES;
251 | CLANG_WARN_CONSTANT_CONVERSION = YES;
252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
253 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
254 | CLANG_WARN_EMPTY_BODY = YES;
255 | CLANG_WARN_ENUM_CONVERSION = YES;
256 | CLANG_WARN_INFINITE_RECURSION = YES;
257 | CLANG_WARN_INT_CONVERSION = YES;
258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
259 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
260 | CLANG_WARN_UNREACHABLE_CODE = YES;
261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
265 | ENABLE_NS_ASSERTIONS = NO;
266 | ENABLE_STRICT_OBJC_MSGSEND = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_NO_COMMON_BLOCKS = YES;
269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
271 | GCC_WARN_UNDECLARED_SELECTOR = YES;
272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
273 | GCC_WARN_UNUSED_FUNCTION = YES;
274 | GCC_WARN_UNUSED_VARIABLE = YES;
275 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
276 | MTL_ENABLE_DEBUG_INFO = NO;
277 | SDKROOT = iphoneos;
278 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
279 | VALIDATE_PRODUCT = YES;
280 | };
281 | name = Release;
282 | };
283 | BE6AFF4D1E269FFD004C7B80 /* Debug */ = {
284 | isa = XCBuildConfiguration;
285 | buildSettings = {
286 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
287 | DEVELOPMENT_TEAM = N88S4A5QL4;
288 | INFOPLIST_FILE = AccordionExample/Info.plist;
289 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
290 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
291 | PRODUCT_BUNDLE_IDENTIFIER = com.worq.AccordionExample;
292 | PRODUCT_NAME = "$(TARGET_NAME)";
293 | SWIFT_VERSION = 3.0;
294 | };
295 | name = Debug;
296 | };
297 | BE6AFF4E1E269FFD004C7B80 /* Release */ = {
298 | isa = XCBuildConfiguration;
299 | buildSettings = {
300 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
301 | DEVELOPMENT_TEAM = N88S4A5QL4;
302 | INFOPLIST_FILE = AccordionExample/Info.plist;
303 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
305 | PRODUCT_BUNDLE_IDENTIFIER = com.worq.AccordionExample;
306 | PRODUCT_NAME = "$(TARGET_NAME)";
307 | SWIFT_VERSION = 3.0;
308 | };
309 | name = Release;
310 | };
311 | /* End XCBuildConfiguration section */
312 |
313 | /* Begin XCConfigurationList section */
314 | BE6AFF351E269FFD004C7B80 /* Build configuration list for PBXProject "AccordionExample" */ = {
315 | isa = XCConfigurationList;
316 | buildConfigurations = (
317 | BE6AFF4A1E269FFD004C7B80 /* Debug */,
318 | BE6AFF4B1E269FFD004C7B80 /* Release */,
319 | );
320 | defaultConfigurationIsVisible = 0;
321 | defaultConfigurationName = Release;
322 | };
323 | BE6AFF4C1E269FFD004C7B80 /* Build configuration list for PBXNativeTarget "AccordionExample" */ = {
324 | isa = XCConfigurationList;
325 | buildConfigurations = (
326 | BE6AFF4D1E269FFD004C7B80 /* Debug */,
327 | BE6AFF4E1E269FFD004C7B80 /* Release */,
328 | );
329 | defaultConfigurationIsVisible = 0;
330 | defaultConfigurationName = Release;
331 | };
332 | /* End XCConfigurationList section */
333 | };
334 | rootObject = BE6AFF321E269FFD004C7B80 /* Project object */;
335 | }
336 |
--------------------------------------------------------------------------------
/Demo/AccordionExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Demo/AccordionExample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // AccordionExample
4 | //
5 | // Created by Klevison Matias on 1/11/17.
6 | // Copyright © 2017 worQ. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/carat-open.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "Sort Down Filled-30-2.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/carat-open.imageset/Sort Down Filled-30-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klevison/AccordionTableViewController/78de224b3105fdab5203f74c43e73b329025c8a0/Demo/AccordionExample/Assets.xcassets/carat-open.imageset/Sort Down Filled-30-2.png
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/carat.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "Sort Right Filled-30-2.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/carat.imageset/Sort Right Filled-30-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klevison/AccordionTableViewController/78de224b3105fdab5203f74c43e73b329025c8a0/Demo/AccordionExample/Assets.xcassets/carat.imageset/Sort Right Filled-30-2.png
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/facebook.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "facebook.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/facebook.imageset/facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klevison/AccordionTableViewController/78de224b3105fdab5203f74c43e73b329025c8a0/Demo/AccordionExample/Assets.xcassets/facebook.imageset/facebook.png
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/linkedin.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "linkedin.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/linkedin.imageset/linkedin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klevison/AccordionTableViewController/78de224b3105fdab5203f74c43e73b329025c8a0/Demo/AccordionExample/Assets.xcassets/linkedin.imageset/linkedin.png
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/twitter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "twitter.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Demo/AccordionExample/Assets.xcassets/twitter.imageset/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klevison/AccordionTableViewController/78de224b3105fdab5203f74c43e73b329025c8a0/Demo/AccordionExample/Assets.xcassets/twitter.imageset/twitter.png
--------------------------------------------------------------------------------
/Demo/AccordionExample/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/AccordionExample/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
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 |
--------------------------------------------------------------------------------
/Demo/AccordionExample/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 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Demo/AccordionExample/SectionFactory.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionFactory.swift
3 | // AccordionExample
4 | //
5 | // Created by Klevison Matias on 1/11/17.
6 | // Copyright © 2017 worQ. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension Section {
12 |
13 | static func sectionOne(view: UIView) -> Section {
14 | let viewOfSection = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 300))
15 | viewOfSection.backgroundColor = UIColor.blue
16 | let section = Section()
17 | section.view = viewOfSection
18 | section.title = "Facebook"
19 | // individual background color for a specific section, overrides the general color if set
20 | section.backgroundColor = UIColor.red
21 | section.appearance.headerHeight = 100
22 |
23 | let overlayViewSection = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 49))
24 | overlayViewSection.backgroundColor = UIColor.white
25 | //overlayViewSection.image = UIImage(named: "facebook")
26 | overlayViewSection.contentMode = .center
27 | overlayViewSection.backgroundColor = UIColor.clear
28 | section.overlayView = overlayViewSection
29 |
30 | let button = UIButton(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50))
31 | button.setTitle("I can be any kind of UIView", for: .normal)
32 | viewOfSection.addSubview(button)
33 |
34 | return section
35 | }
36 |
37 | static func sectionTwo(view: UIView) -> Section {
38 | let viewOfSection = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 300))
39 | viewOfSection.backgroundColor = UIColor.red
40 | let section = Section()
41 | section.view = viewOfSection
42 | section.title = "Twitter"
43 | // individual background color for a specific section, overrides the general color if set
44 | section.backgroundColor = UIColor.blue
45 |
46 | let overlayViewSection = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 49))
47 | overlayViewSection.backgroundColor = UIColor.white
48 | overlayViewSection.image = UIImage(named: "twitter")
49 | overlayViewSection.contentMode = .center
50 | overlayViewSection.backgroundColor = UIColor.clear
51 | section.overlayView = overlayViewSection
52 |
53 | let button = UIButton(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50))
54 | button.setTitle("I'm another UIView", for: .normal)
55 | viewOfSection.addSubview(button)
56 |
57 | return section
58 | }
59 |
60 | static func sectionThree(vc viewController: UIViewController) -> Section {
61 | let storyboard = UIStoryboard(name: "Main", bundle: nil)
62 | let sectionViewController = storyboard.instantiateViewController(withIdentifier: "SectionViewController") as UIViewController
63 | viewController.addChildViewController(sectionViewController)
64 |
65 | let section = Section()
66 | section.view = sectionViewController.view
67 | section.title = "ViewController"
68 | // individual background color for a specific section, overrides the general color if set
69 | section.backgroundColor = UIColor.orange
70 |
71 | return section
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Demo/AccordionExample/SectionViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SectionViewController.swift
3 | // AccordionExample
4 | //
5 | // Created by Klevison Matias on 1/11/17.
6 | // Copyright © 2017 worQ. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol SectionViewControllerDelegate: class {
12 | func sectionViewControllerDidLayoutSubViews(size: CGSize)
13 | }
14 |
15 | final class SectionViewController: UIViewController {
16 |
17 | weak var delegate: SectionViewControllerDelegate?
18 |
19 | override func viewDidLayoutSubviews() {
20 | super.viewDidLayoutSubviews()
21 | delegate?.sectionViewControllerDidLayoutSubViews(size: view.bounds.size)
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/Demo/AccordionExample/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // AccordionTableViewController
4 | //
5 | // Created by Klevison Matias on 1/11/17.
6 | // Copyright © 2017 worQ. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: AccordionTableViewController, SectionViewControllerDelegate, AccordionTableViewControllerDelegate {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | oneSectionAlwaysOpen = false
17 | sections = allSetions()
18 | delegate = self
19 | openAnimation = .fade
20 | closeAnimation = .fade
21 | }
22 |
23 | private func allSetions() -> [Section] {
24 | return [Section.sectionOne(view: view), Section.sectionTwo(view: view), Section.sectionThree(vc: self)]
25 | }
26 |
27 | func sectionViewControllerDidLayoutSubViews(size: CGSize) {
28 | let section = self.sections[2]
29 | section.view!.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
30 |
31 | if openedSection?.sectionIndex == 2 {
32 | self.reloadOpenedSection()
33 | }
34 | }
35 |
36 | func accordionTableViewControllerSectionDidClose(section: Section) {
37 | print(#function)
38 | }
39 |
40 | func accordionTableViewControllerSectionDidOpen(section: Section) {
41 | print(#function)
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Klevison Matias
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AccordionTableViewController
2 |
3 | Swift version of https://github.com/klevison/KMAccordionTableViewController
4 |
5 |
6 |
7 |
8 |
9 | ## Current Version
10 |
11 | Version: 0.0.3
12 |
13 | ## Under the Hood
14 |
15 | * Supports UIViews as sections (UIViews, UIViewController's view, UITableViews, UIWebView, MKMapView, etc...)
16 | * Update content and size of a section
17 | * Custom animation, headers, sizes, etc...
18 | * Xcode 8
19 | * Swift 3
20 |
21 | ## How to install it?
22 |
23 | [CocoaPods](http://cocoapods.org) is the easiest way to install AccordionTableViewController. Run ```pod search AccordionTableViewController``` to search for the latest version. Then, copy and paste the ```pod``` line to your ```Podfile```. Your podfile should look like:
24 |
25 | ```
26 | platform :ios, '8.0'
27 | pod 'AccordionTableViewController'
28 | ```
29 |
30 | Finally, install it by running ```pod install```.
31 |
32 | If you don't use CocoaPods, import the all files from "Classes" directory to your project.
33 |
34 | ## How to use it?
35 |
36 | ### Extends from AccordionTableViewController
37 |
38 | ```swift
39 | import UIKit
40 |
41 | class ViewController: AccordionTableViewController {
42 |
43 | }
44 | ```
45 |
46 | ### Set `sections` and `delegate` variables
47 |
48 | ```swift
49 | override func viewDidLoad() {
50 | super.viewDidLoad()
51 |
52 | let viewOfSection = UIView(frame: CGRectMake(0, 0, view.frame.size.width, 300))
53 | viewOfSection.backgroundColor = UIColor.blueColor()
54 | let section = Section()
55 | section.view = viewOfSection
56 | section.title = "Section"
57 |
58 | oneSectionAlwaysOpen = true
59 | sections = [section] //how many sections you want
60 | delegate = self
61 | }
62 | ```
63 |
64 | ### Customization
65 |
66 | Each section has an `appearence` var and it can be customized
67 |
68 | ```swift
69 | var open = false
70 | var view: UIView?
71 | var overlayView: UIView?
72 | var headerView: SectionHeaderView?
73 | var title: String?
74 | var backgroundColor: UIColor?
75 | var sectionIndex: Int?
76 | var appearence = Appearence()
77 | ```
78 |
79 | ## Contact
80 |
81 | If you have any questions comments or suggestions, send me a message. If you find a bug, or want to submit a pull request, let me know.
82 |
83 | * klevison@gmail.com
84 | * http://twitter.com/klevison
85 |
86 | ## Copyright and license
87 |
88 | Copyright (c) 2015 Klevison Matias (http://twitter.com/klevison). Code released under [the MIT license](LICENSE).
89 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klevison/AccordionTableViewController/78de224b3105fdab5203f74c43e73b329025c8a0/demo.gif
--------------------------------------------------------------------------------