Notifly

Commit Platform Swift 5.0 iOS 13.0+ MIT


一个极简且可定制的 iOS 通知库

Notifly 是一个轻量级的 iOS 通知库。它提供了多种通知类型和自定义选项,使其易于集成并适应您的需求。

📖 文档

⚠️重要提示
当前版本仍在开发中。在 1.0 版本发布之前,版本更新中可能会有重大变更。

特性

快速开始

简单通知

let banner = SimpleNotifly("Link copied", direction: .top)
banner.present()
默认通知

let banner = Notifly("A Banner with just a text", subtitle: "{subtitle}", direction: .top)
banner.present()
卡片通知

CardNotifly 提供了一种可定制且视觉上吸引人的卡片式横幅,可以包含标题、副标题、按钮和自定义视图。 它旨在提供一种简洁且引人入胜的方式向用户呈现信息或操作。 但是,重要的是要注意,这仍然是一个横幅,用户可以随时将其关闭。 您的应用程序不应依赖 CardNotifly 进行关键操作或信息显示。 如果您需要呈现用户无法离开的模态页面,请查看 ModalKit,它可能更适合。

⚠️实验性
CardNotifly 目前是实验性的,不应在生产环境中使用。 欢迎贡献并帮助改进此功能!

let banner = CardNotifly(title: "How to use", subtitle: "Simply download the notification banner and get started with your own notifications.")
banner.addButton(CardNotiflyButton(title: "Skip ", style: .dismiss))
banner.addButton(CardNotiflyButton(title: "Get started", style: .default, handler: {
    // Do something on button press
}))

// See Banner options for more
banner.setBannerOptions([
  .showExitButton(true),
  .customView(yourCustomView()),
])

banner.dismissOnSwipe = false
banner.show()
自定义通知

通过重写其属性和方法,BaseNotifly 允许您创建完全自定义的横幅。 通过完全控制 UI 和行为,您可以设计满足您需求的横幅。

class MyCustomBanner: BaseNotifly {
    override init(direction: NotiflyDirection, queue: NotiflyQueue = .default, on parent: UIViewController? = nil) {
        super.init(direction: direction, queue: queue, on: parent)
        setupUI()
    }

    func setupUI() {
         // Create the banner's appearance
    }
}

let banner = MyCustomBanner(direction: .top)
banner.present()

配置

Notifly 提供了一种使用 Configuration 自定义其外观和行为的简单方法。 每个配置都允许您定义文本、背景、图标、对齐方式等的样式。 您可以使用默认配置或创建自定义配置。

自定义配置

要创建自定义配置,请使用所需的参数初始化 Notifly.Configuration 的实例。 例如

let customConfig = Notifly.Configuration(
    titleColor: .white,
    titleFont: .systemFont(ofSize: 18, weight: .semibold),
    subtitleColor: .gray,
    subtitleFont: .systemFont(ofSize: 14, weight: .regular),
    backgroundColor: .default(.blue),
    icon: .init(image: UIImage(systemName: "bell.fill"), tintColor: .white),
    cornerRadius: .rounded,
    textAlignment: .leading,
    contentAlignment: .center,
    imagePadding: 10,
    titleSubtitleSpacing: 4
)

let banner = Notifly(
    "Custom Banner",
    subtitle: "This banner uses a custom configuration.",
    configuration: customConfig,
    direction: .top
)
banner.present()
预定义配置

Notifly 包括针对常见场景的预定义配置:Info、Success 和 Warning。 这些配置已准备好使用,并且包含文本、图标和背景颜色的预设样式。

let infoBanner = Notifly(
    "Information",
    subtitle: "This is an informational banner.",
    configuration: .info()
)
banner.present()

队列

NotiflyQueue 系统提供队列管理来处理多个横幅。 它确保横幅按顺序显示,限制一次可见的横幅数量,并在其他横幅被关闭时自动调整横幅的位置。

默认情况下,每个横幅都放置在队列的末尾。 如果您想立即显示横幅,请将其放置在队列的前面。

let queue = NotiflyQueue.default
let banner1 = Notifly("Banner 1", direction: .top, queue: queue)
let banner2 = Notifly("Banner 2", direction: .top, queue: queue)
let banner3 = Notifly("Banner 3", direction: .top, queue: queue)

queue.addBanner(banner1, queuePosition: .back) // Add at the back of the queue
queue.addBanner(banner2, queuePosition: .front) // Add at the front of the queue
banner.present(queuePosition: .back)  // Add at the back of the queue

默认情况下,每个横幅都会在一段时间后被关闭。 如果您想禁用该功能,请将 autoDismiss 设置为 false 并手动关闭。

banner.autoDismiss = false

// .. some long task
banner.dismiss()

呈现器

NotiflyPresenter 协议及其各种实现定义了如何使用动画呈现和关闭横幅。 呈现器控制横幅的生命周期,并提供灵活地自定义其动画以适应各种用例。

使用呈现器

每个横幅都有一个呈现器属性,用于确定其动画行为。 例如,您可以将 NotiflyDefaultPresenter 用于基本动画,或者将其替换为更动态的呈现器,如 NotiflyBouncePresenter

呈现器 演示
默认
淡入
缩放
弹跳
let banner = SimpleNotifly("Dynamic Banner", presenter: NotiflyBouncePresenter(animationDuration: 0.4))
banner.present()
创建呈现器

您可以通过遵循 NotiflyPresenter 协议或 NotiflyDefaultPresenter 来创建自己的呈现器。 例如,这是一个自定义滑入动画的示例

class CustomSlidePresenter: NotiflyDefaultPresenter {
    override public func presentationAnimator(_ banner: NotiflyBaseBanner, in superview: UIView) -> UIViewPropertyAnimator {
        let animator = UIViewPropertyAnimator(duration: animationDuration, curve: .easeInOut)

        animator.addAnimations {
            banner.frame = self.finalFrame(for: banner, in: superview)
        }

        return animator
    }

    override public func dismissAnimator(_ banner: NotiflyBaseBanner, in superview: UIView) -> UIViewPropertyAnimator {
        let animator = UIViewPropertyAnimator(duration: animationDuration, curve: .easeInOut)

        animator.addAnimations {
            banner.frame = self.initialFrame(for: banner, in: superview)
        }

        return animator
    }
}

高亮器

高亮器定义了用户与横幅交互时的视觉反馈,例如点击或拖动等触摸事件。 它们用于提供强调交互的动画,例如缩放或 alpha 更改。 Notifly 包括 NotiflyHighlighter 协议,允许开发人员定义自定义高亮器行为。 它还提供了默认实现 NotiflyDefaultHighlighter,用于标准高亮效果。

使用高亮器

您可以通过设置其 highlighter 属性将高亮器分配给横幅。 默认情况下,横幅使用 NotiflyDefaultHighlighter。

let banner = NotiflySimpleBanner("Dynamic Banner")
banner.highlighter = NotiflyDefaultHighlighter(animationScale: 0.9, animationDuration: 0.2)
banner.present()
创建高亮器

您可以实现 NotiflyHighlighter 协议来定义自定义行为。 例如,您可能希望添加旋转效果以及缩放

class CustomHighlighter: NotiflyHighlighter {
    private let rotationAngle: CGFloat = .pi / 12
    private let animationDuration: TimeInterval = 0.3

    func highlight(_ button: NotiflyBaseBanner, at location: CGPoint) {
        UIView.animate(withDuration: animationDuration) {
            button.transform = CGAffineTransform(scaleX: 0.9, y: 0.9).rotated(by: self.rotationAngle)
        }
    }

    func stopHighlight(_ button: NotiflyBaseBanner) {
        UIView.animate(withDuration: animationDuration) {
            button.transform = .identity
        }
    }

    func locationMoved(_ button: NotiflyBaseBanner, to location: CGPoint) {
        // Optional: Track touch location and adjust highlighting
    }
}

反馈

Notifly 中的反馈系统旨在在显示横幅时提供触觉或视觉提示。 Notifly 包括 NotiflyFeedback 协议,允许您定义自定义反馈行为。 它还提供了常见反馈类型的默认实现,例如触觉反馈。 您可以通过设置其反馈属性将反馈分配给横幅。 默认情况下,横幅使用 .impact(style: .light)。

let banner = Notifly("Success!")
banner.feedback = .notification(type: .success)
banner.present()
自定义反馈

要定义自定义反馈行为,请实现 NotiflyFeedback 协议。 例如,您可以播放声音效果或执行视觉动画

class SoundFeedback: NotiflyFeedback {
    func generate() {
        // Play a sound or perform custom feedback
        AudioServicesPlaySystemSound(1057) // Example: system sound
    }
}

let banner = Notifly("Success!")
banner.feedback = SoundFeedback()
banner.present()

Notifly 中的代理和用户交互

Notifly 提供了一种通过 NotiflyDelegate 协议和直接闭包来处理横幅事件的简单方法,用于用户交互,例如点击或滑动。

代理

NotiflyDelegate 协议允许您响应横幅的关键生命周期事件,例如它出现、消失或被关闭时。

class MyViewController: UIViewController, NotiflyDelegate {
  override func viewDidLoad() {
    let banner = Notifly("Link copied", direction: .top)
    banner.delegate = self
    banner.show()
  }

  // Banner delegate
  func notificationWillAppear(_ notification: NotiflyBase) {
    // Do something before the banner appears
  }

  func notificationDidAppear(_ notification: NotiflyBase) {
    // Do something when the banner appeared
  }
  func notificationWillDisappear(_ notification: NotiflyBase) {
    // Do something before the banner disappears
  }

  func notificationDidDisappear(_ notification: NotiflyBase) {
    // Do something after the banner disappeared
  }
}
用户交互

Notifly 还提供了用于直接处理交互(例如点击和滑动)的闭包,而无需代理。 默认情况下,这些交互会关闭横幅。

banner.onSwipe = { sender in
    // Do something on swipe
}

banner.didTap = {
    // Do something on tap
}

选项

选项名称 描述
feedback 显示横幅时要触发的触觉反馈 (NotiflyFeedback,默认为 .impact(style: .light))。
highlighter 负责处理触摸交互的高亮器 (NotiflyHighlighter?,默认为 NotiflyDefaultHighlighter())。
autoDismiss 指示横幅是否应在指定的时间间隔后自动关闭 (Bool,默认为 false)。
autoDismissInterval 如果启用 autoDismiss,则横幅将自动关闭的时间间隔 (TimeInterval,默认为 2 秒)。
didTap 点击横幅时执行的闭包 (默认情况下关闭横幅)。
onSwipe 滑动横幅时执行的闭包 (默认情况下关闭横幅)。
direction 横幅将从哪个方向出现 (例如,.top.bottom)
delegate 处理横幅生命周期事件的代理 (NotiflyDelegate?,默认为 nil)。
presentationState 横幅在其生命周期中的当前状态 (NotiflyState,例如 .presentingpresented)。
bannerType 横幅的类型 (例如,stick 或 float) (NotiflyType,默认为 .float)。
parentViewController 显示横幅的父视图控制器 (UIViewController?,默认为 nil)。
hasBeenSeen 指示横幅是否已至少显示一次 (Bool,默认为 false)。
notificationQueue 将放置横幅的队列 (NotiflyQueue,默认为 .default)。

要求

安装

Swift Package Manager

要使用 Swift Package Manager 将 Notifly 集成到您的项目中,请将以下内容添加到您的 Package.swift 文件中

dependencies: [
    .package(url: "https://github.com/emrearmagan/Notifly.git")
]
CocoaPods

⚠️注意
CocoaPods 支持已在 0.1.0 版本中删除。在此之前,将不存在支持。强烈建议使用 SPM。

手动安装 Notifly
  1. 从最新版本下载 Notifly.zip 并将其内容解压缩到您的项目文件夹中。
  2. 从 Xcode 项目中,从“文件”菜单中选择“添加到 ...”,然后添加解压缩的文件。

贡献

非常感谢您的贡献! 要提交一个

  1. Fork
  2. 将更改提交到您的 Fork 中的一个分支
  3. 推送您的代码并发出拉取请求