Latest 1.1.0
Homepage https://github.com/rob-nash/CollapsibleTable
License MIT
Platforms ios 8.0, requires ARC
Authors

Carthage compatible
[Cocoapods compatible]()
[Platform]()
[Language]()
Build Status

The collapsing mechanism can be installed in just a few minutes. But the creative design and styling of the UI, is at the mercy of the implementing developer.

demo

Take a look at the demo App by running the XCode scheme ‘CollapsibleTableDemo’

Installation

CocoaPods:

Add the line pod "CollapsibleTable" to your Podfile

Carthage:

Add the line github "rob-nash/CollapsibleTable" to your Cartfile

Usage

First subclass UITableViewHeaderFooterView

import UIKit

class ArrowSectionHeaderView: UITableViewHeaderFooterView
{
    @IBOutlet fileprivate weak var mainTitleLabel: UILabel!

    @IBOutlet fileprivate weak var arrowImageView: UIImageView?

    fileprivate var isRotating = false
}

Then conform to the HeaderFooterViewCollapsible protocol

import CollapsibleTable

extension ArrowSectionHeaderView: HeaderFooterViewCollapsible
{
    func updateTitle(with value: String) {
        mainTitleLabel.text = value
    }

    func open(animated: Bool) {
        if animated == true && isRotating == false {
            isRotating = true
            UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear,.allowUserInteraction], animations: {
                self.arrowImageView?.transform = .identity
            }, completion: { _ in
                self.isRotating = false
            })
        } else {
            layer.removeAllAnimations()
            arrowImageView?.transform = .identity
            isRotating = false
        }
    }

    func close(animated: Bool) {
        let angle = radians(degrees: 90)
        let transform = CGAffineTransform(rotationAngle: angle)
        if animated == true && isRotating == false {
            isRotating = true
            UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear,.allowUserInteraction], animations: {
                self.arrowImageView?.transform = transform
            }, completion: { _ in
                self.isRotating = false
            })
        } else {
            layer.removeAllAnimations()
            arrowImageView?.transform = transform
            isRotating = false
        }
    }

    private func radians(degrees: CGFloat) -> CGFloat {
        return .pi * degrees / 180
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        guard let t = touches.first else { return }
        let point = t.location(in: self)
        respondToTouchAtPoint(point)
    }
}

Create a collection of instances that represent each section of your table view.

import Foundation

class Food
{
    /// The section title
    fileprivate let title: String

    /// The rows
    fileprivate var items: [Item]

    /// Are rows hidden
    fileprivate var isHidden = false

    init(title: String, items: [Item], isHidden: Bool) {
        self.title = title
        self.items = items
        self.isHidden = isHidden
    }
}

class Item
{
    let title: String
    var isSelected: Bool

    init(title: String, isSelected: Bool = false) {
        self.title = title
        self.isSelected = isSelected
    }
}

Each model instance representing your table view sections, must conform to CollapsibleTableSectionDatasource.

extension Food: CollapsibleTableSectionDatasource
{
    typealias TableRow = Item

    var rows: [Item] {
        get {
            return items
        }
        set(newValue) {
            items = newValue
        }
    }

    var state: RowVisibility {
        get {
            return isHidden ? .collapsed : .expanded
        }
        set(newValue) {
            switch newValue {
            case .collapsed:
                isHidden = true
            case .expanded:
                isHidden = false
            }
        }
    }

    var sectionTitle: String {
        return title
    }

    var sectionHeaderNibName: String {
        return "ArrowSectionHeaderView"
    }

    var sectionHeaderViewIdentifier: String {
        return "ArrowSectionHeaderViewID"
    }

    var sectionHeaderNibBundle: Bundle {
        return .main
    }
}

Create a UITableView subclass that conforms to TableCollapsible.

import UIKit
import CollapsibleTable

class FoodShoppingTableView: UITableView, TableCollapsible
{
    typealias TableSection = Food

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        separatorStyle = .none
        let nib = UINib(nibName: "ArrowSectionHeaderView", bundle: nil)
        register(nib, forHeaderFooterViewReuseIdentifier: "ArrowSectionHeaderViewID")
        observeSectionHeaders()
    }

    deinit {
        stopObservingSectionHeaders()
    }
}

Create a datasource by subclassing CollapsibleTableDatasource

import UIKit
import CollapsibleTable

class FoodShoppingTableViewDatasource: CollapsibleTableDatasource<Food>
{
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CustomCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
        let section: Food = sections[indexPath.section]
        let item: Item = section.rows[indexPath.row]
        cell.mainTitleLabel?.text = item.title
        return cell
    }
}

Then connect it all up

import UIKit
import CollapsibleTable

class ViewController: UIViewController
{
    @IBOutlet private weak var tableView: FoodShoppingTableView! {
        didSet {
            let appDelegate = UIApplication.shared.delegate as? AppDelegate
            tableView.dataSource = appDelegate?.foodShoppingTableViewDatasource
        }
    }
}

Donations.

If you like this and you want to buy me a drink, use bitcoin.

Bitcoin Image

Bitcoin Address: 15Gj4DBTzSujnJrfRZ6ivrR9kDnWXNPvNQ

Latest podspec

{
    "name": "CollapsibleTable",
    "version": "1.1.0",
    "summary": "A collapsible table view mechanism.",
    "description": "A table view of collapsing table view sections",
    "homepage": "https://github.com/rob-nash/CollapsibleTable",
    "screenshots": "https://i.imgur.com/HjznyIf.gif",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Robert Nash": "[email protected]"
    },
    "social_media_url": "http://twitter.com/rob__nash",
    "platforms": {
        "ios": "8.0"
    },
    "source": {
        "git": "https://github.com/rob-nash/CollapsibleTable.git",
        "tag": "1.1.0"
    },
    "source_files": "CollapsibleTable/*.{swift}",
    "requires_arc": true,
    "pushed_with_swift_version": "3.2"
}

Pin It on Pinterest

Share This