skedgo/tgcardviewcontroller
Provides a card-based view controller for mapping applications where the card's content is in sync with a map, similar to how Apple Maps works. For an application of this see the [TripKitUI SDK](https://github.com/skedgo/tripkit-ios) and [TripGo](https://apps.apple.com/au/app/tri
Installation and usage
Install
<details> <summary>Via Swift Package Manager (recommended)</summary>
- Add it to your
Package.swiftfile (or add it as a dependency through Xcode):
.package(url: "https://github.com/skedgo/TGCardViewController.git", from: "1.7.5")</details>
<details> <summary>Via CocoaPods</summary>
- Check out the repo and make it accessible to your project, e.g., as a git submodule
- Add it to your
Podfile, e.g.:
pod 'TGCardViewController
- Run
pod update
</details>
Add it to your app
- Create a
TGCardViewControllersubclass and use it in your storyboard - Override
init(coder:)so that the instance from the storyboard isn't used, but insteadTGCardViewController.xib:
```swift import TGCardViewController
class CardViewController: TGCardViewController {
required init(coder aDecoder: NSCoder) { // When loading from the storyboard we don't want to use the controller // as defined in the storyboard but instead use the TGCardViewController.xib super.init(nibName: "TGCardViewController", bundle: TGCardViewController.bundle) }
... } ```
- Create a
TGCardsubclass, that represents the card at the top level, and add then push that in your view controller'sviewDidLoad:
``swift override func viewDidLoad() { rootCard = MyRootCard() super.viewDidLoad() } ``
Specs
1. Basic functionality of cards
Behaviour:
- Card positions:
1. collapsed: Only shows header of card 2. peaking: Shows half of card's content and the map content 3. extended: Shows card fully, map shows a little bit on top but is greyed out
- Pushing a card from another card
- [x] Adds (x) button unless it’s the root card - [x] Card has a preferred position which is used when pushing - [x] Animation: Slide up from the bottom; fading black view on card below with alpha from 0% to 25% - [x] Pass on appearance callbacks appropriately to involved cards
- Popping a card
- [x] Tap (x) to pop card - [x] When popping top card, restore card position of card below when something got pushed on it - [x] Animation: Slide back down; fading out black view on card below with alpha from 25% to 0% - [x] Pass on appearance callbacks appropriately to involved cards
- Cards are draggable
- [x] Snap to collapsed (only title), peaking (near half-way showing both map and card content), extended (still shows a bit of the map on top, but darkened) - [x] Cards can be dragged up and down anywhere on the card - [x] Tap title when collapsed: go to peaking - [x] Tap title when peaking: go to extended - [x] Tap title when extended: do nothing - [x] Tap map when extended: go to peaking
- Cards are scrollable
- [x] Cards typically have scrolling content: when scrolling down the card's header stays at the top and a bit of the map still keeps peaking through at the top. - [x] When scrolling down show a thin separator line between the card's scrolling content and the card's header - [x] When scrolling to the top and keeping to scroll, start dragging card
Styles:
- [x] Animation curve for push and pop
- [x] Blurry view under status bar (like Maps app)
- [x] When rotating device and card is collapsed, make sure card ends up in correct position
2. Card content and gestures
Card types:
- Plain card
- [x] On top: Title, (x), optional subtitle and optional accessory view - [x] Add accessory view - [x] Content can be scrollable and size adjusts to content. If it fits, it shouldn’t be scrollable - [x] Add optional floaty button
- Table card
- [x] Same as plain card, but with a table view as its content - [x] Allow specifying plain (e.g., for departures) or grouped style (e.g., for profile)
- Collection card
- [x] Same as plain card, but with a collection view as its content - [x] Allow specifying collection view layout
- Hosting card
- [x] Allow using a SwiftUI view as the card's content
- Paging card
- [x] Handles list of child cards on the same hierarchical level which can be paged programatically and through gestures - [x] Has header view: Used for titles (child cards shouldn't show them then) and navigation; Header view is separate from sticky bar, i.e., you can have both. - [x] Re-uses the top card's map manager - [x] Pass on appearance callbacks appropriately to child cards
Card styles:
- [x] Rounded corners to cards
- [x] Grab handle for cards
- [x] Nice close buttons (and next button for paging cards)
- [x] Title and subtitle styling
- [x] Add mini drop shadow to card views
- [x] Bottom view
3. Map content
Map content:
- [x] Cards can optionally have map content
- [x] When showing the content, the insets should be respected to account for the card overlapping the map
- [x] If there’s no map content: Show card always extended and don't allow dragging it down (or just snap back up when using tries)
Map buttons:
- [x] Optional list of buttons that float on the right above the card or in the top right corner (when collapsed or peaking)
- [x] When dragging up the card to
extended, the buttons fade away
4. Large width (iPad + iPhone in landscape)
- [x] Move card to the side with min (iPhone Plus) and max (iPad) width
- [x] Make sure transitions work when changing size and traits
5. UIKit features
- [x] State restoration, using
NSUserActivity - [x] VoiceOver Accessibility
- [x] Keyboard shortcuts
End-user documentation
Keyboard shortcuts
- Card controller
- ⌃+↑: Expand card - ⌃+↓: Expand/collapse card - ⌘+w: Pop card or dismiss modal
- Table view cards
- ↑: Highlight previous item - ↓: Highlight next item - ⌘+↑: Highlight item at start of list - ⌘+↓: Highlight item at end of list - Space or enter: select item - Esc: deselect
- Paging cards
- ⌃+←: Previous card - ⌃+→: Next card
Package Metadata
Repository: skedgo/tgcardviewcontroller
Default branch: main
README: README.md