tToastKit / ドキュメント

SWIFTUI · オープンソース

自然になじむ
通知を。

SwiftUI アプリに、積み重ね表示のトースト通知を追加しましょう。ジェスチャ、タイマー、スタイルがそろっています。

使い始める ↓iOS 17+ · Swift 5.10
01

すぐに使える

はじめに

Swift Package Manager で ToastKit を追加し、通知を表示するビューに ToastCenter を付けます。

ContentView.swiftSWIFT
import SwiftUI
import ToastKit

struct ContentView: View {
    @State private var toasts = ToastCenter()

    var body: some View {
        Button("保存") {
            toasts.present(.normal, title: "変更を保存しました")
        }
        .toasts(toasts)
    }
}
✳

これだけで完了です。トーストはセーフエリアの下部に4秒間表示されます。標準のスワイプ操作で削除したり、次回まで保留したりできます。

Xcode の File → Add Package Dependencies を選び、https://github.com/DavidRicardoWilde/swiftui-toastkit を入力してください。

02

メッセージ

トーストメッセージ

ToastMessage には、表示内容、意味を持つステータス、表示時間、任意のタップ操作とスワイプ操作を設定します。簡単な通知には便利メソッドを、細かな制御が必要な場合はメッセージを直接作成します。

toasts.present(.warning,
    title: "ストレージの空き容量が不足しています",
    message: "同期を続けるには空き容量を増やしてください。"
)

let message = ToastMessage(
    status: .notification,
    title: "新しい写真",
    message: "今日の写真が12枚あります",
    icon: .system("photo.on.rectangle"),
    duration: 6
)
toasts.present(message)
NORMAL

通常

日常的な確認に使う、控えめな表示です。

WARNING

注意

問題が失敗に至る前に確認を促します。

ERROR

エラー

失敗を明確に伝える視覚的な合図です。

NOTIFICATION

お知らせ

アプリのアクセントカラーで通知します。

表示中のメッセージと同じ id を使って再度表示すると、複製せずに内容を更新して先頭へ移動します。「同期中…」から「同期完了」への更新に便利です。

03

少しだけ表示

表示時間

.automatic は ToastCenter の既定値である4秒を使います。秒数を直接指定するか、ユーザーの操作が必要な通知には .indefinite を使います。

// 2秒間表示
ToastMessage(title: "コピーしました", duration: 2)

// 閉じられるまで表示
ToastMessage(title: "同期に失敗しました", duration: .indefinite)

let toasts = ToastCenter(defaultDuration: 6)
  • カウントダウンするのは先頭のトーストだけです。
  • 後ろに隠れたトーストは、先頭に移動するまで表示時間を使いません。
  • スタックに触れている間やアプリがバックグラウンドにある間はタイマーが止まります。
04

次の操作を明確に

ジェスチャと操作

タップ、左右へのスワイプ、長押しが使えます。長押しすると両方のスワイプ操作を確認してから選べます。VoiceOver でも同じ操作を名前から選択できます。

ジェスチャ既定の動作カスタマイズ
タップ操作なし。背後のコンテンツへ通過tapAction または onTap
leading 側へスワイプトーストを削除swipeActions.leading
trailing 側へスワイプ次にページを開いたときに再表示swipeActions.trailing
長押し両方の操作をプレビュースワイプ操作と同じ設定
let archive = ToastAction(
    id: "archive",
    title: "アーカイブ",
    icon: .system("archivebox"),
    confirmation: "アーカイブしました"
) { toast in
    store.archive(toast.id)
}

toasts.present(ToastMessage(
    title: "Ana からのメッセージ",
    tapAction: ToastAction(title: "開く") { toast in
        router.open(toast.id)
    },
    swipeActions: ToastSwipeActions(leading: archive, trailing: .later)
))

操作は handler、スタックの onToastAction オブザーバー、操作の効果の順に実行されます。組み込みの .later は、ページが再び表示されるまでトーストを保留します。

05

自由にカスタマイズ

スタイルとテーマ

既定の .glass スタイルは、ステータスに合わせて色が変わるすりガラスのカードです。ToastTheme でデザイントークンを調整したり、装飾のない .plain を選んだり、ToastStyle に準拠した独自カードを作成したりできます。

MyScreen()
    .toasts(toasts)
    .toastTheme(ToastTheme(
        titleFont: .headline,
        tint: { status in
            status == .notification ? .pink : ToastTheme.standardTint(status)
        },
        cornerRadius: 16
    ))

// 背景や固定色のないスタイルから始める
MyScreen().toasts(toasts).toastStyle(.plain)
モーション 色 面 文字

カスタムスタイルからはアイコン、タイトル、本文、ステータス、長押しトラックに持ち上げられているかを参照できます。レイアウトとジェスチャはスタックが管理します。

06

適切な場所に表示

配置と幅

既定では画面下部から積み重なり、安全領域の幅の60%で表示されます。

// 上端に配置
MyScreen().toasts(toasts, placement: .top)

// 安全領域の90%、または固定幅
MyScreen().toasts(toasts, width: .fraction(0.9))
MyScreen().toasts(toasts, width: .points(320))

TabView 内では、タブのコンテンツに .toasts(toasts) を付けます。システムのタブバーや下部アクセサリは安全領域に含まれます。独自のフローティングバーには .toastObstruction() を付けると、スタックが重ならないように移動します。

✓保存しました下部 · 60%
セーフエリア
07

すべての人のために

アクセシビリティ

特定のジェスチャを使わなくても操作でき、SwiftUI 環境のアクセシビリティ設定に従います。

  • VoiceOver が各カードを読み上げ、アクションローターから両方の操作を選べます。
  • 視差効果を減らす設定では、スライドがフェード表示に変わります。
  • 透明度を下げる設定では、ガラス面が不透明になります。
  • コントラストを上げる設定では、ガラスの縁がはっきりした境界線になります。
  • Dynamic Type に合わせて文字とアイコンが拡大します。
08

ユーザーの言語で

アプリのローカライズ

ToastKit の組み込み操作ラベルは英語、日本語、簡体字中国語、繁体字中国語に対応しています。タイトル、本文、独自の操作ラベルはアプリ側でローカライズしてください。

// アプリの文言は String Catalog または Localizable.strings に登録します。
toasts.present(.warning,
    title: String(localized: "storage.low.title"),
    message: String(localized: "storage.low.message")
)

ToastKit の組み込みラベルはホストアプリのロケールに従います。独自の ToastAction タイトルと確認文は通常の文字列なので、アプリと同じローカライズ手段を使えます。

さらに詳しく

もう少し仕上げてみましょう

ソースコードで API の使い方を確認できます。

GitHub で見る ↗