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...
MarvelComics-ViewCode é um app  para fins de estudo, desenvolvido em Swift utilizando View Code.
MarvelComics-ViewCode é um app para fins de estudo, desenvolvido em Swift utilizando View Code.

MarvelComics-ViewCode - iOS O MarvelComics-ViewCode é um app para listar todos os personagens da Marvel, implementado em Swift utilizando View Code co

Simple way to set up half modal view
Simple way to set up half modal view

HalfModalView Requirements iOS 9.0+ Xcode 10.0+ Swift 4.0+ Example Installation CocoaPods is a dependency manager for Cocoa projects. You can install

BCSwiftTor - Opinionated pure Swift controller for Tor, including full support for Swift 5.5 and Swift Concurrency

BCSwiftTor Opinionated pure Swift controller for Tor, including full support for

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Swift Markdown is a Swift package for parsing, building, editing, and analyzing Markdown documents.

Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer documentation.

Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer docum

Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. (Pure Swift, Supports Linux)

SwiftFoundation Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. Goals Provide a cross-platform in

Swift - ✏️Swift 공부 저장소✏️

Swift 스위프트의 기초 1. Swift의 기본 2. 변수와 상수 [3. 데이터 타입 기본] [4. 데이터 타입 고급] 5. 연산자 6. 흐름 제어 7. 함수 8. 옵셔널 객체지향 프로그래밍과 스위프트 9. 구조체와 클래스 10. 프로퍼티와 메서드 11. 인스턴스 생

Swift-ndi - Swift wrapper around NewTek's NDI SDK

swift-ndi Swift wrapper around NewTek's NDI SDK. Make sure you extracted latest

__.swift is a port of Underscore.js to Swift.

__.swift Now, __.swift is version 0.2.0! With the chain of methods, __.swift became more flexible and extensible. Documentation: http://lotz84.github.

Owner
Nandin Borjigin
Learn the rules like a pro, so you can break them like an artist. 通术,悟道,破矩。
Nandin Borjigin
Swift implementation of the package url spec

PackageURL Swift implementation of the package url specification. Requirements Swift 5.3+ Usage import PackageURL let purl: PackageURL = "pkg:swift/a

Mattt 21 Jun 14, 2022
Swift implementation of AWS Lambda Events

Swift AWS Lambda Events Overview Swift AWS Lambda Runtime was designed to make building Lambda functions in Swift simple and safe. The library is an i

Swift on Server 29 Dec 19, 2022
SwiftRedux is a Swift implementation of the Redux state container

SwiftRedux is a Swift implementation of the Redux state container. It relies on the same concepts and provides familiar Hooks through property wrappers.

Lucas Lima 8 Feb 1, 2022
Swift implementation of the QOI Format

Swift-QOI Swift implementation of the QOI Format. Contains extensions for AppKit and UIKit to integrate into your projects with ease. Documentation //

Amy While 18 Oct 21, 2022
Swift implementation of the QOI Format

Swift-QOI Swift implementation of the QOI Format. Contains extensions for AppKit and UIKit to integrate into your projects with ease. Documentation //

Amy While 1 Dec 9, 2021
UIViewController extension to present view / view controller as bottom-half modal.

UIViewController extension to present view / view controller as bottom-half modal. Installation CocoaPods pod 'SemiModalViewController' Swift Package

Winter 78 Mar 3, 2022
The sample implementation of zip-archived document for a macOS AppKit platform.

The sample implementation of zip-archived document for a macOS AppKit platform. You can implement NSDocument-based I/O of archived document in your application like .sketch or .key.

usagimaru 4 Nov 12, 2022
Swift-HorizontalPickerView - Customizable horizontal picker view component written in Swift for UIKit/iOS

Horizontal Picker View Customizable horizontal picker view component written in

Afraz Siddiqui 8 Aug 1, 2022
Using UI Table View With Swift

News-App - Apple 관련 기사를 보여주는 News app을 만들 것입니다. - 자세한 과정은 리드미에 있습니다. Table View와 Table view controller Table View : Table의 크기를 지정할 수 있다. Table View Co

Jiwon 0 Dec 9, 2021
Array diffs as collection view wants it - now in Swift ✨

Doppelganger-Swift Inspired by Doppelganger written in Swift Features Removes confusion from users when data changes Animates moving, inserting and de

Szymon Maślanka 9 Jul 9, 2019