Savory is swift accrodion view implementation

Overview

Savory Carthage compatible GitHub license

Savory is a swift accordion view implementation.

screencast

Requirements

  • Xcode 8.0
  • Swift 3.0
  • iOS 8

Installation

  • Using CocoaPods:

    pod 'Savory', :git => 'https://github.com/Nandiin/Savory.git'
  • Using Carthage:

    github "Nandiin/Savory"
    

    then proceed with official steps stated in Carthage readme

  • Manually:

    Add the files in Savory folder to your project.

Usage

import UIKit
import Savory

class ViewController: UIViewController, SavoryViewDelegate {

    var savoryView: SavoryView!

    override func viewDidLoad() {
        super.viewDidLoad()

        /* 1. Initiate SavoryView */
        savoryView = SavoryView(frame: view.frame)
        // offset for status bar
        savoryView.frame.origin.y = 20
        savoryView.frame.size.height -= 20 

        /* 2. Provide a implementation of SavoryStateProtivder protocol */
        // Savory providers a simple implementation - SimpleStateProvider
        savoryView.stateProvider = SimpleStateProvider([.expanded, .collapsed, .collapsed])

        /* 3. Set the reuse identifiers for header and body cells */
        savoryView.headerIdentifier = "header"
        savoryView.bodyIdentifier = "body"

        /* 4. register the reuse identifiers */
        savoryView.register(UITableViewCell.self, forCellReuseIdentifier: "header")
        savoryView.register(UITableViewCell.self, forCellReuseIdentifier: "body")

        /* 5. set the savoryDelegate */
        savoryView.savoryDelegate = self

        /* 6. add subview */
        view.addSubview(savoryView)
    }

    func headerCell(forPanelAt index: SavoryPanelIndex, in savoryView: SavoryView) -> SavoryHeaderCell {

        /* Dequeues a reusable cell */
        // SavoryView provides a method to dequeue reusable header cell for certain index
        // SavoryView internally dequeues a cell using its headerIdentifier as reuse identifier
        let cell = savoryView.dequeueReusableHeaderCell(forPanelAt: index)

        /* customize the cell */
        cell.selectionStyle = .none
        cell.textLabel?.text = "Header \(index)"
        cell.backgroundColor = UIColor.lightGray

        return cell
    }

    func bodyCell(forPanelAt index: SavoryPanelIndex, in savoryView: SavoryView) -> SavoryBodyCell {

        // almost same as headerCell(forPanelAt:in:)
        let cell = savoryView.dequeueReusableBodyCell(forPanelAt: index)
        cell.textLabel?.numberOfLines = 0
        cell.textLabel?.text = [String](repeating: "Body \(index)", count: index + 1).joined(separator: "\n")
        return cell
    }
}

Savory also can be used along with Interface Builder:

  • Set Class filed of a Table View to SavoryView in the Identity Inspector.

  • Set Identifier fileds of two Table View Cells respectively in the Attributes Inspector.

  • Connect Table View to a view controller as outlet.

  • Set the headerIdentifier, bodyIdentifier properties of the outlet, you should use the values set for Table View Cells above.

  • Set stateProvider and savoryDelegate properties of the outlet.

Reference

Glossary

  • Header: The upper title bar of a accordion panel that consumes user selection event and then toggles the visibility of the Body.

  • Body: The lower view of a accordion panel that typically carrys detail information and would collapse or expand when user taps the corresponding Header.

SavoryView

Accordion effect view developed on UITableView.

  • savoryDelegate: Delegate that provides header and body cells for the view. It also receives event like willCollapse, willExpand, didCollapse, didExpand and didSelect.

  • stateProvider: Another delegate that provides the state of the accordion view. SavoryView has stateProvider.count number of panels and i-th panel's expand-or-collapse state depends on the value stateProvider[i].

  • headerIdentifier, bodyIdentifier: SavoryView uses these properties inside its dequeueReusableHeaderCell and dequeueReusableBodyCell method to dequeue reusable cells. So make sure these identifiers are registered to the SavoryView instance somehow (programatically or in Interface Builder)

  • dequeueReusableHeader(Body)Cell(forPanelAt:): Like dequeueReusableCell(withIdentifier:for:) method for UITableView, these methods dequeue reusable cells for panel at certain index.

SavoryStateProvider

SavoryView renders its panels as collapsed or expanded based on its stateProvider property.

Actually [SavoryPanelState] type "conforms to" this protocol naturally. However, because swift hasn't supported an extension like below yet( may come soon according to apple/swift)

extension Array: SavoryStateProvider where Element == SavoryPanelState {} 

Savory provides a wrapper implementation as SimpleStateProvider and it requires a [SavoryPanelState] for initializing and then it acts just like a stored array from SavoryView's perspective.

For most circumstances, this is sufficient unless you want to provide some complex state managing feature.

Remember to call reloadData on SavoryView if you provided a custom implementation of SavoryStateProvider and it changes its state programatically

TODO

  • Animation synchronization
  • Custom Animation
  • Find a way to test commit cc2bc43ad436dc4d9d4a1390e68688e54b44ae12
  • @IBDesignable

License

Savory is released under the MIT license. See LICENSE for details.

You might also like...
OpenSwiftUIViews - A non gesture blocking, non clipping by default custom scroll view implementation with example code.

OpenSwiftUIViews - A non gesture blocking, non clipping by default custom scroll view implementation with example code.

Linenoise-Swift  A pure Swift implementation of the Linenoise library. A minimal, zero-config readline replacement.
Linenoise-Swift A pure Swift implementation of the Linenoise library. A minimal, zero-config readline replacement.

Linenoise-Swift A pure Swift implementation of the Linenoise library. A minimal, zero-config readline replacement. Supports Mac OS and Linux Line edit

Simplex-Swift - A basic implementation of the Simplex algorithm, written in Swift

Simplex-Swift - A basic implementation of the Simplex algorithm, written in Swift

Fancy Swift implementation of the Visual Format Language (experimental and doesn't work with the recent version of Swift)
Fancy Swift implementation of the Visual Format Language (experimental and doesn't work with the recent version of Swift)

VFLToolbox Autolayout is awesome! VFL a.k.a Visual Format Language is even more awesome because it allows you to shorten constraints setting code. The

Swift Server Implementation - RESTful APIs, AWS Lambda Serverless For Swift Runtime amazonlinux: AWS Lambda + API Gateway
Swift Server Implementation - RESTful APIs, AWS Lambda Serverless For Swift Runtime amazonlinux: AWS Lambda + API Gateway

Swift Server Implementation - RESTful APIs, AWS Lambda Serverless For Swift Runtime amazonlinux: AWS Lambda + API Gateway deployed on Graviton arm64 build swift:5.6.2-amazonlinux2-docker image

Player View is a delegated view using AVPlayer of Swift

PlayerView [![CI Status](http://img.shields.io/travis/David Alejandro/PlayerView.svg?style=flat)](https://travis-ci.org/David Alejandro/PlayerView) An

A fully customizable container view controller to display a set of ViewControllers in a horizontal scroll view. Written in Swift.
A fully customizable container view controller to display a set of ViewControllers in a horizontal scroll view. Written in Swift.

DTPagerController This is a control for iOS written in Swift. DTPagerController is simple to use and easy to customize. Screenshots Default segmented

A fully customizable container view controller to display a set of ViewControllers in a horizontal scroll view. Written in Swift.
A fully customizable container view controller to display a set of ViewControllers in a horizontal scroll view. Written in Swift.

DTPagerController This is a control for iOS written in Swift. DTPagerController is simple to use and easy to customize. Screenshots Default segmented

An Event View based on Apple's Event Detail View. Written in Swift 3. Supports ARC, Autolayout and editing via StoryBoard.
An Event View based on Apple's Event Detail View. Written in Swift 3. Supports ARC, Autolayout and editing via StoryBoard.

An Event View based on Apple's Event Detail View. Written in Swift 3. Supports ARC, Autolayout and editing via StoryBoard. Installation CocoaPods PTEv

Modern-collection-view - Modern collection view for swift

Modern collection view Sample application demonstrating the use of collection vi

Spin aims to provide a versatile Feedback Loop implementation working with the three main reactive frameworks available in the Swift community (RxSwift, ReactiveSwift and Combine)
Spin aims to provide a versatile Feedback Loop implementation working with the three main reactive frameworks available in the Swift community (RxSwift, ReactiveSwift and Combine)

With the introduction of Combine and SwiftUI, we will face some transition periods in our code base. Our applications will use both Combine and a thir

Swift implementation of the longest common subsequence (LCS) algorithm.

SwiftLCS SwitLCS provides an extension of Collection that finds the indexes of the longest common subsequence with another collection. The longest com

Swift implementation of Github REST API v3
Swift implementation of Github REST API v3

GitHubAPI Swift implementation of GitHub REST api v3. Library support Swift 4.2. Work is in progress. Currently supported: Issues API. Activity API(Fe

A simple and beautiful chart lib used in Piner and CoinsMan for iOS(https://github.com/kevinzhow/PNChart) Swift Implementation

PNChart-Swift PNChart(https://github.com/kevinzhow/PNChart) Swift Implementation Installation This isn't on CocoaPods yet, so to install, add this to

ReSwift is a Redux-like implementation of the unidirectional data flow architecture in Swift.
ReSwift is a Redux-like implementation of the unidirectional data flow architecture in Swift.

ReSwift is a Redux-like implementation of the unidirectional data flow architecture in Swift. ReSwift helps you to separate three important concerns of your app's components.

When is a lightweight implementation of Promises in Swift
When is a lightweight implementation of Promises in Swift

Description When is a lightweight implementation of Promises in Swift. It doesn't include any helper functions for iOS and OSX and it's intentional, t

A Swift implementation of fastimage. Supports PNG, GIF, and JPEG.
A Swift implementation of fastimage. Supports PNG, GIF, and JPEG.

ImageScout ImageScout is a Swift implementation of fastimage. It allows you to find the size and type of a remote image by downloading as little as po

FlexLayout adds a nice Swift interface to the highly optimized facebook/yoga flexbox implementation. Concise, intuitive & chainable syntax.
FlexLayout adds a nice Swift interface to the highly optimized facebook/yoga flexbox implementation. Concise, intuitive & chainable syntax.

FlexLayout adds a nice Swift interface to the highly optimized Yoga flexbox implementation. Concise, intuitive & chainable syntax. Flexbox is an incre

Implementation of x-callback-url (Inter app communication) in swift
Implementation of x-callback-url (Inter app communication) in swift

CallbackURLKit - Inter app communication Starting to integrate URL scheme in an app, why not be compliant with x-callback-url. CallbackURLKit.register

Owner
Nandin Borjigin
Learn the rules like a pro, so you can break them like an artist. 通术,悟道,破矩。
Nandin Borjigin
Three Level Accordian View for IOS

ThreeLevelAccordian ThreeLevelAccordian is a three level accordian for IOS. It owes its base code to SwiftyAccordionCells. Most of the design is custo

Amrata Baghel 44 Sep 23, 2022
Make your table view expandable just by implementing one method.

ExpyTableView About ExpyTableView is a re-write based on SLExpandableTableView. Takes some ideas, concepts and codes and regenerates them in Swift. Le

Okhan Okbay 359 Dec 27, 2022
`SimpleExpandableView` is a SwiftUI view which can collapse and expand the content

SimpleExpandableView 中文说明 ExpandableView structure Example ExpandableView( headerSize: CGSize(width: 250.0, height: 50.0), cardSize: CGSize(wi

Tomortec 5 Oct 6, 2022
✨ Awesome expandable, collapsible tableview cell for iOS written in Swift 4

USE ExpandableCell. New version of this library. YNExpandableCell Updates See CHANGELOG for details Intoduction Easiest usage of expandable & collapsi

Kyle Yi 457 Dec 26, 2022
✨ Awesome expandable, collapsible tableview cell for iOS written in Swift 5

ExpandableCell Intoduction Fully refactored YNExapnadableCell with more concise, bug free. Easiest usage of expandable & collapsible cell for iOS, wri

Kyle Yi 728 Jan 1, 2023
Use any custom view as custom callout view for MKMapView with cool animations. Use any image as annotation view.

MapViewPlus About MapViewPlus gives you the missing methods of MapKit which are: imageForAnnotation and calloutViewForAnnotationView delegate methods.

Okhan Okbay 162 Nov 16, 2022
A SwiftUI implementation of React Hooks. Enhances reusability of stateful logic and gives state and lifecycle to function view.

SwiftUI Hooks A SwiftUI implementation of React Hooks. Enhances reusability of stateful logic and gives state and lifecycle to function view. Introduc

Ryo Aoyama 441 Jan 6, 2023
WobbleView is an implementation of a recently popular wobble effect for any view in your app

WobbleView is an implementation of a recently popular wobble effect for any view in your app. It can be used to easily add dynamics to user interactions and transitions.

intent 2.2k Nov 29, 2022
A non gesture blocking, non clipping by default custom scroll view implementation with example code

A non gesture blocking, non clipping by default custom scroll view implementation with example code

Marco Boerner 10 Dec 6, 2022