Code Monkey home page Code Monkey logo

bulletinboard's Introduction

BulletinBoard

CI Status Version License Platform Documentation Contact: @_alexaubry

BulletinBoard is an iOS library that generates and manages contextual cards displayed at the bottom of the screen. It is especially well suited for quick user interactions such as onboarding screens or configuration.

It has an interface similar to the cards displayed by iOS for AirPods, Apple TV configuration and NFC tag scanning.

It has built-in support for accessibility features such as VoiceOver and Switch Control.

Here are some screenshots showing what you can build with BulletinBoard:

Demo Screenshots

Requirements

  • Xcode 9 and later
  • iOS 9 and later
  • Swift 3.2 and later

Demo

A demo project is included in the BulletinBoard workspace. It demonstrates how to:

  • integrate the library (setup, data flow)
  • create standard page cards
  • create custom page subclasses to add features
  • create custom cards from scratch

Two demo targets are available:

  • BB-Swift (demo written in Swift)
  • BB-ObjC (demo written in Objective-C)

Build and run the scheme for your favorite language to open the demo app.

Here's a video showing it in action:

Watch Demo on YouTube

Installation

BulletinBoard is available via CocoaPods and Carthage.

CocoaPods

To install BulletinBoard using CocoaPods, add this line to your Podfile:

pod 'BulletinBoard'

Carthage

To install BulletinBoard using Carthage, add this line to your Cartfile:

github "alexaubry/BulletinBoard"

πŸ¦• Objective-C Integration

BulletinBoard is fully compatible with Objective-C.

To import it in your Objective-C app, just add this line at the top of your files:

@import BulletinBoard; 

Limitations

PageBulletinItem, BulletinAppearance and BulletinInterfaceBuilder subclasses must be written in Swift, as Swift classes cannot be overriden in Objective-C.

You can use Mix and Match to write your subclass in Swift and import it into your Objective-C code, as demonstrated in the example project.

Usage

The Basics

The BulletinManager class generates, manages and displays bulletin cards. Cards are created using bulletin items. Bulletin items are objects that conform to the BulletinItem protocol.

The library provides a standard item type: PageBulletinItem. If you need to customize the items, you can override this class, or create new item types from scratch.

Displaying Bulletins

To display bulletins you first need to create the root item to display (explained in the next sections).

With this root item, you need to create a BulletinManager. We recommend putting it in the view controller that will display the bulletin.

class ViewController: UIViewController {

    lazy var bulletinManager: BulletinManager = {

        let rootItem: BulletinItem = // ... create your item here
        return BulletinManager(rootItem: rootItem)

    }()

}

To present your bulletin, call this method:

bulletinManager.prepare()
bulletinManager.presentBulletin(above: self)

Always call prepare() before calling presentBulletin()! Failure to do so will cause a precondition failure (TL;DR your app will crash).

For the case of onboarding, you can call it in viewWillAppear(animated:) after checking if the user has already completed onboarding.

Creating Page Items

You can create standard page items using the PageBulletinItem class.

It takes care of generating a user interface with standard components:

  • a title (required)
  • an icon image (should be 128x128px or less)
  • a description text
  • a large action button
  • a smaller alternative button

For example, this interface was created using a PageBulletinItem:

Customizing PageBulletinItem

To recreate this interface, use this code:

let page = PageBulletinItem(title: "Push Notifications")
page.image = UIImage(named: "...")

page.descriptionText = "Receive push notifications when new photos of pets are available."
page.actionButtonTitle = "Subscribe"
page.alternativeButtonTitle = "Not now"

If you omit an optional property, the page won't generate a view for it. For instance, if you set alternativeButtonTitle to nil, the card won't display an alternative button.

Customizing the Appearance

The PageBulletinItem class exposes a appearance property that allows you to fully customize the appearance of the generated interface.

This property references a BulletinAppearance, which is used to generate the standard components (more on this later). You can subclass this class in Swift and further customize the appearance of the app.

You can customize both color and fonts. You need to change these before you present / push the item. Changing them after presentation will have no effect.

There are several properties that you can change:

  • tintColor - the tint color of the buttons (defaults to iOS blue)
  • actionButtonTitleColor - the color of action button titles

Example

let greenColor = UIColor(red: 0.294, green: 0.85, blue: 0.392, alpha: 1)
page.appearance.actionButtonColor = greenColor
page.appearance.alternativeButtonColor = greenColor
page.appearance.actionButtonTitleColor = .white

This produces a card with the following appearance:

Demo Tint Color

Handling Button Taps

To handle taps on buttons, set a closure for these properties:

  • actionHandler - called when the action button is tapped.
  • alternativeHandler - called when the alternative button is tapped.
page.actionHandler = { (item: PageBulletinItem) in
    print("Action button tapped")
}

This prints "Action button tapped" when the action button is tapped.

page.alternativeHandler = { (item: PageBulletinItem) in
    print("Alternative button tapped")
}

This prints "Alternative button tapped" when the alternative button is tapped.

Use these handlers as an opportunity to change the presented item, dismiss the bulletin and/or pass data to your model.

Changing the Presented Item

The BulletinItem protocol exposes a manager property that is set when the item is currently being displayed by a manager.

You can use it to interact with the presented bulletin. Call:

  • manager?.popItem() to go back to the previous item
  • manager?.popToRootItem() to go back to the first item
  • manager?.push(item:) with a BulletinItem to present a new item
  • manager?.dismissBulletin(animated:) to dismiss the bulletin
  • manager?.displayNextItem() to display the next item (see below)

You need to call these methods from the main thread. Never force unwrap manager, as this property will be unset as soon as the item is removed from the bulletin.

It is also possible to set the nextItem property to the BulletinItem that should be displayed next and call the displayNextItem() method when you want to display it.

For instance, to present a new card when the user taps the action button:

page.nextItem = makeLocationPage() // Creates a new PageBulletinItem

page.actionHandler = { (item: PageBulletinItem) in
    item.manager?.displayNextItem()
}

This creates the following interaction:

Next Item

Displaying an Activity Indicator

If you need to perform a task between the moment the user taps a button and the moment you'll be able to change the presented item, you can call displayActivityIndicator() method on the item manager to hide the current card and display an activity indicator.

This is especially useful if you need to fetch data from a server (in-app purchase price, subscription status, ...) or save data (e.g. Core Data).

Once your task is finished, call one of the methods described in Changing the Presented Item.

Example:

page.actionHandler = { (item: PageBulletinItem) in
    item.manager?.displayActivityIndicator()
    // do your task
    // ...
    // when your task is finished, transition to the appropriate bulletin item
    item.displayNextItem()
}

This creates the following interaction:

Activity Indicator

Customizing the Background View

By default, the content behind the card is covered with a semi-opaque view (known as the .dimming style).

You can customize the background view by changing the backgroundViewStyle property of the manager before calling prepare().

Example:

manager.backgroundViewStyle = .blurredExtraLight
manager.prepare()

Several styles are available in the BulletinBackgroundViewStyle enum:

Dimming View

Note: blurred backgrounds are available in iOS 10.0 and later.

Dismissal

If you set the isDismissable property to true, the user will be able to dismiss the bulletin by tapping outside of the card or by swiping the card down.

You should set this property to true for the last item.

Creating Custom Items

To create custom bulletin items, create a class that implements the BulletinItem protocol. To learn with a concrete example, you can read the implementation of PageBulletinItem.

Conforming to BulletinItem

To conform to this protocol, you need to add the required properties and implement two methods:

makeArrangedSubviews()

This method should return all the elements to display on the card.

Please note that the alpha and isHidden properties will be ignored.

tearDown()

In this method, clear all the resources allocated for the item (such as notification observers or button targets). After this method is called, the manager will be set to nil and the arranged subviews will be hidden and removed from the card.

Generating Standard Views

Even though you are creating a custom card, you may still want to display some standard elements, such as title labels or action buttons.

To generate standard elements BulletinInterfaceBuilder. Interface builders with appearance objects (BulletinAppearance) to create standard elements.

Use these methods to generate standard components for your custom items:

  • makeTitleLabel(text:) to create a title label with the given title
  • makeDescriptionLabel() to create a description label
  • makeActionButton(title:) to create an action button
  • makeAlternativeButton(title:) to create an alternative button
  • makeGroupStack(spacing:) to create a vertical stack view with the given spacing

Internals

BulletinBoard uses stack views and Auto Layout to display and manage cards. It automatically adapts to changes in width and height. iPad and iPhone X are supported out of the box.

If you are interested in learning how it works in more details, look at the implementation of BulletinManager, BulletinViewController and BulletinInterfaceBuilder.

Contributing

Thank you for your interest in the project! Contributions are welcome and appreciated.

Make sure to read these guides before getting started:

Apps Using BulletinBoard

Feel free to submit a PR if you’re using this library in your apps.

  • SpdrVision mobile - A simple way to watch Italian television on macOS and iOS by Gianpiero Spinelli

Author

Written by Alexis Aubry. You can find me on Twitter.

License

BulletinBoard is available under the MIT license. See the LICENSE file for more info.

bulletinboard's People

Contributors

alexisakers avatar lennet avatar calicastle avatar moogle19 avatar buddax2 avatar lowkostkustomz avatar jyounus avatar pdamonkey avatar devwiththehair avatar gianpispi avatar loicverrall avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.