易于使用的 UI 组件,用于向用户显示简短的瞬态消息
此框架允许您向应用程序添加瞬态应用内消息传递。多个消息将使用流体动画堆叠。消息可以完全主题化,并设置为在指定的时间间隔后过期或保留在屏幕上直到关闭。
Licensing
Y—Snackbar is licensed under the Apache 2.0 license.
Documentation
Documentation is automatically generated from source code comments and rendered as a static website hosted via GitHub Pages at: https://yml-org.github.io/ysnackbar-ios/
Usage
Snack
A is a model that represents a floating ephemeral alert or message to be presented to the user. It consists of the following:Snack
alignment
: Alignment for the snack view. Default is .SnackbarManager.defaultAlignment
title
: Title for the snack view. This is an optional string and the default is nil.message
: Message to be displayed by . This is of type .SnackView
String
reuseIdentifier
: A string for identifying a snack. This is of type and the default is nil.String?
icon
: A small image to be displayed as part of the snack view. This is of type and the default is nil.UIImage?
duration
: The total duration for which the snack will be displayed. The default is 4 seconds.appearance
: Sets the appearance of the . The default isSnackView
SnackView.Appearance()
Two snacks are said to be equal if either the of both snacks are equal or the and of both snacks are equal. This is made possible by the snack’s conformance to both and .reuseIdentifier
title
message
Equatable
Hashable
💡 If the snack is or then the snack lives forever (until you swipe to dismiss it)duration
.nan
.zero
SnackView
A is a view that will be presented to the user through the . The content of the view is populated using a model object. It has one initializer:SnackView
SnackbarManager
Snack
init(snack: Snack)
- Initializes a using the data model.
SnackView
snack
- Initializes a using the data model.
Clients can modify or set the appearance of the while creating a by setting the . This will allow the client to modify the following properties:SnackView
Snack
appearance
title
:- A tuple consisting of and for the title label.
textColor
typography
- Default is .
(.label, .systemLabel.bold)
- A tuple consisting of and for the title label.
message
:- A tuple consisting of and for the message label.
textColor
typography
- Default is .
(.label, .systemLabel)
- A tuple consisting of and for the message label.
backgroundColor
:SnackView
‘s background color. The default is .systemBackground
shadow
:SnackView
‘s shadow property is of type and consists of properties such as color, opacity, etc.Shadow
- The default is .
Shadow()
layout
:SnackView
‘s layout property is of type which consists of properties such as spacing between views, corner radius, etc.Layout
- The default is .
Layout()
How to get SnackView
from a Snack
?
func getSnackAssociatedView() -> SnackUpdatable
SnackUpdatable
- Any object that can be updated with a new model object.
Snack
SnackView
uses this to update an existing view with new information.
SnackbarManager
All snacks are managed by the .SnackbarManager
State
defaultAlignment
- It is a global mutable shared state.
- Describes the default alignment of the snack view.
- Default is
.top
Operations
-
class func add(snack: Snack)
-
Creates a snack view using the snack passed as an argument to display a snack.
-
Depending on the alignment, duplicate snacks will be updated and pushed to the bottom or top.
-
-
class func remove(snack: Snack)
- Removes a snack view using the snack passed as an argument. The will be dismissed after the last snack is removed.
SnackContainerView
- There are 3 ways by which you can remove a snack. They are as follows:
- By calling operation.
class func remove(snack: Snack)
- When the snack has completed its
duration
- Swiping it up or down to dismiss.
- By calling operation.
- Removes a snack view using the snack passed as an argument. The will be dismissed after the last snack is removed.
Clients can control or modify the animation duration, spacing, etc of the by setting the property which is of type . This will allow the client to modify the following properties:SnackbarManager
appearance
SnackbarManager.Appearance
addAnimationDuration
:- Animation duration on adding a snack.
- Default is 0.4
removeAnimationDuration
:- Animation duration on removing a snack.
- The default is 0.4
snackSpacing
:- Spacing between the snacks
- The default is 16.0
contentInset
:- The distance the content is inset from the superview.
- The default is 16.0
maxSnackWidth
:- Maximum width of a snack view.
- Helps to keep a fixed width for a snack view on an iPad screen.
- The default is 428.0
Default Features
Every snack added has the following default features:
- corner radius based on appearance
- shadow based on appearance
- swipe enabled to dismiss snack view
Usage
-
Importing the framework
import YSnackbar
-
Create a snack
func makeSnack() -> Snack { Snack( alignment: .bottom, title: "Network Reachable", message: "You are currently online.", reuseIdentifier: "yml.co", icon: UIImage(named: "wifi"), duration: 8.0 ) }
-
Add a snack
// Creates a snack using `SnackbarManager.defaultAlignment = .top` let snack = Snack(message: "No network") // Adds to the top of the screen SnackbarManager.add(snack: snack)
// Creates a snack with bottom alignment let snack = Snack(alignment: .bottom, message: "Copied to clipboard") // Adds to the bottom of the screen SnackbarManager.add(snack: snack)
// Set `SnackbarManager.defaultAlignment` to bottom SnackbarManager.defaultAlignment = .bottom // Creates a snack using defaultAlignment. let snack = Snack(message: "Copied to clipboard") // Adds to the bottom of the screen SnackbarManager.add(snack: snack)
-
Remove a snack
let snack = Snack() SnackbarManager.remove(snack)
-
Create a custom Snack
final class ImageSnack: Snack { convenience init(named: String) { self.init(message: named, reuseIdentifier: "co.yml.page") } override func getSnackAssociatedView() -> SnackUpdatable { SnackImageView(snack: self) } } final class SnackImageView: UIImageView { private(set) var snack: Snack required init(snack: Snack) { self.snack = snack super.init(image: UIImage(named: snack.message)) setUp() } required init?(coder: NSCoder) { nil } private func setUp() { self.contentMode = .scaleAspectFit } } extension SnackImageView: SnackUpdatable { func update(_ snack: Snack) { self.image = UIImage(named: snack.message) self.snack = snack } }
Installation
You can add Y—Snackbar to an Xcode project by adding it as a package dependency.
- From the File menu, select Add Packages…
- Enter “https://github.com/yml-org/ysnackbar-ios” into the package repository URL text field
- Click Add Package
Contributing to Y—Snackbar
Requirements
SwiftLint (linter)
brew install swiftlint
Jazzy (documentation)
sudo gem install jazzy
Setup
Clone the repo and open in Xcode.Package.swift
Versioning strategy
We utilize semantic versioning.
{major}.{minor}.{patch}
e.g.
1.0.5
Branching strategy
We utilize a simplified branching strategy for our frameworks.
- main (and development) branch is
main
- both feature (and bugfix) branches branch off of
main
- feature (and bugfix) branches are merged back into as they are completed and approved.
main
main
gets tagged with an updated version # for each release
Branch naming conventions:
feature/{ticket-number}-{short-description}
bugfix/{ticket-number}-{short-description}
e.g.
feature/CM-44-button
bugfix/CM-236-textview-color
Pull Requests
Prior to submitting a pull request you should:
- Compile and ensure there are no warnings and no errors.
- Run all unit tests and confirm that everything passes.
- Check unit test coverage and confirm that all new / modified code is fully covered.
- Run from the command line and confirm that there are no violations.
swiftlint
- Run from the command line and confirm that you have 100% documentation coverage.
jazzy
- Consider using to squash your last {commit-count} commits together into functional chunks.
git rebase -i HEAD~{commit-count}
- If HEAD of the parent branch (typically ) has been updated since you created your branch, use to rebase your branch.
main
git rebase main
- Never merge the parent branch into your branch.
- Always rebase your branch off of the parent branch.
When submitting a pull request:
- Use the provided pull request template and populate the Introduction, Purpose, and Scope fields at a minimum.
- If you’re submitting before and after screenshots, movies, or GIF’s, enter them in a two-column table so that they can be viewed side-by-side.
When merging a pull request:
- Make sure the branch is rebased (not merged) off of the latest HEAD from the parent branch. This keeps our git history easy to read and understand.
- Make sure the branch is deleted upon merge (should be automatic).
Releasing new versions
- Tag the corresponding commit with the new version (e.g.
1.0.5
) - Push the local tag to remote
Generating Documentation (via Jazzy)
You can generate your own local set of documentation directly from the source code using the following command from Terminal:
jazzy
This generates a set of documentation under . The default configuration is set in the default config file file./docs
.jazzy.yaml
To view additional documentation options type:
jazzy --help
A GitHub Action automatically runs each time a commit is pushed to that runs Jazzy to generate the documentation for our GitHub page at: https://yml-org.github.io/ysnackbar-ios/main