SwiftEntryKit
トーストやポップアップ、プッシュ通知のようなビューを簡単に導入できるすごいライブラリ SwiftEntryKit をこの記事で紹介する。いくつか同様のライブラリ(Toast-Swiftなど)を試したが、SwiftEntryKitが圧倒的にイケてるUIUXを作れると感じた。イメージは以下の通り。
Toasts | Notes | Floats | Popups |
---|---|---|---|
Alerts | Forms | Rating | More... |
---|---|---|---|
インストール
ここに丁寧に書いてあるのでここでは言及しない。CocoaPodsやCarthageで入れるだけ。
使い方のイメージ
import SwiftEntryKit
///
func test() {
var attributes = EKAttributes.bottomFloat // bottomFloat以外に様々なタイプがある
// プロパティを設定していく
// attributes.xxx = xxx
// たとえば以下の通り
attributes.entryBackground = .gradient(gradient: .init(colors: [EKColor(UIColor.red), EKColor(UIColor.orange)], startPoint: .zero, endPoint: CGPoint(x: 1, y: 1)))
attributes.popBehavior = .animated(animation: .init(translate: .init(duration: 0.3), scale: .init(from: 1, to: 0.7, duration: 0.7)))
attributes.shadow = .active(with: .init(color: .black, opacity: 0.5, radius: 10, offset: .zero))
attributes.statusBar = .light
attributes.scroll = .enabled(swipeable: true, pullbackAnimation: .jolt)
attributes.positionConstraints.maxSize = .init(width: .constant(value: UIScreen.main.bounds.width), height: .intrinsic)
// EKNotificationMessageViewなど、EKxxxViewを作ってattributesとともにSwiftEntryKitに渡す
// UIFont() は任意の形に変更する必要がある
let title = EKProperty.LabelContent(text: "Sample Notification", style: .init(font: UIFont(), color: .standardContent))
let description = EKProperty.LabelContent(text: "Body message", style: .init(font: UIFont(), color: .standardContent))
let image = EKProperty.ImageContent(image: UIImage(named: "some image"), size: CGSize(width: 35, height: 35))
let simpleMessage = EKSimpleMessage(image: image, title: title, description: description)
let notificationMessage = EKNotificationMessage(simpleMessage: simpleMessage)
let contentView = EKNotificationMessageView(with: notificationMessage)
// あとはSwiftEntryKit.displayを呼ぶだけ
SwiftEntryKit.display(entry: contentView, using: attributes)
}
このライブラリでは、ビューのトップ、中央、ボトムの3つの位置(top
/ center
/ bottom
)を選択でき、ビューのタイプは以下のような感じで10個以上定義されている。位置とビューのタイプを組み合わせて使うことになる。
- EKAlertMessageView
- EKFormMessageView
- EKNotificationMessageView
- EKNoteMessageView
- EKPopUpMessageView
- EKRatingMessageView
iOSのプッシュ通知のようなバナーを表示する
struct NotificationBanner {
static func show(title: String, body: String, image: UIImage) {
var attributes = EKAttributes.topFloat
attributes.entryBackground = .gradient(gradient: .init(colors: [EKColor(UIColor.red), EKColor(UIColor.orange)], startPoint: .zero, endPoint: CGPoint(x: 1, y: 1)))
attributes.popBehavior = .animated(animation: .init(translate: .init(duration: 0.3), scale: .init(from: 1, to: 0.7, duration: 0.7)))
attributes.shadow = .active(with: .init(color: .black, opacity: 0.5, radius: 10, offset: .zero))
attributes.statusBar = .light
attributes.scroll = .enabled(swipeable: true, pullbackAnimation: .jolt)
attributes.positionConstraints.maxSize = .init(width: .constant(value: UIScreen.main.bounds.width), height: .intrinsic)
// UIFont() は任意の形に変更する必要がある
let title = EKProperty.LabelContent(text: title, style: .init(font: UIFont(), color: .white))
let description = EKProperty.LabelContent(text: body, style: .init(font: UIFont(), color: .white))
let image = EKProperty.ImageContent(image: image, size: CGSize(width: 35, height: 35))
let simpleMessage = EKSimpleMessage(image: image, title: title, description: description)
let notificationMessage = EKNotificationMessage(simpleMessage: simpleMessage)
let contentView = EKNotificationMessageView(with: notificationMessage)
SwiftEntryKit.display(entry: contentView, using: attributes)
}
}
利用するのはこんな感じ。
NotificationBanner.show(title: "Notification title", body: "Notification body", image: UIImage(named: "xxx"))
お洒落なアラートを表示する
struct Alert {
// ここではアクションが一つの場合
static func show(title: String, body: String, image: UIImage, action: @escaping () -> Void) {
var attributes = EKAttributes.topFloat
attributes.displayDuration = .infinity
attributes.entryBackground = .gradient(gradient: .init(colors: [EKColor(UIColor.purple), EKColor(UIColor.blue)], startPoint: .zero, endPoint: CGPoint(x: 1, y: 1)))
attributes.screenBackground = .visualEffect(style: .prominent)
attributes.popBehavior = .animated(animation: .init(translate: .init(duration: 0.3), scale: .init(from: 1, to: 0.7, duration: 0.7)))
attributes.shadow = .active(with: .init(color: .black, opacity: 0.5, radius: 10, offset: .zero))
attributes.scroll = .enabled(swipeable: true, pullbackAnimation: .jolt)
attributes.positionConstraints.maxSize = .init(width: .constant(value: UIScreen.main.bounds.width), height: .intrinsic)
// これがないとアクションが実行されない
attributes.entryInteraction = .absorbTouches
// UIFont() は任意の形に変更する必要がある
let title = EKProperty.LabelContent(text: title, style: .init(font: UIFont(), color: .white))
let description = EKProperty.LabelContent(text: body, style: .init(font: UIFont(), color: .white))
let image = EKProperty.ImageContent(image: image, size: CGSize(width: 35, height: 35))
let simpleMessage = EKSimpleMessage(image: image, title: title, description: description)
let label = EKProperty.LabelContent(text: "OK", style: .init(font: UIFont(), color: .black))
let button = EKProperty.ButtonContent(label: label, backgroundColor: .white, highlightedBackgroundColor: .standardBackground) {
// dismissを自分で呼ばないとビューが消えない
SwiftEntryKit.dismiss()
action()
}
let content = EKProperty.ButtonBarContent(with: [button], separatorColor: EKColor(UIColor.black), expandAnimatedly: true)
let alertMessage = EKAlertMessage(simpleMessage: simpleMessage, buttonBarContent: content)
let view = EKAlertMessageView(with: alertMessage)
SwiftEntryKit.display(entry: view, using: attributes)
}
}
利用するのはこんな感じ。
Alert.show(title: "Alert title", body: "Alert body") {
print("tapped!!")
}
ポップアップを表示する
struct Popup {
static func show(title: String, body: String, action: @escaping () -> Void) {
var attributes = EKAttributes.centerFloat
attributes.displayDuration = .infinity
attributes.entryBackground = .gradient(gradient: .init(colors: [EKColor(UIColor.purple), EKColor(UIColor.blue)], startPoint: .zero, endPoint: CGPoint(x: 1, y: 1)))
attributes.screenBackground = .visualEffect(style: .prominent)
attributes.popBehavior = .animated(animation: .init(translate: .init(duration: 0.3), scale: .init(from: 1, to: 0.7, duration: 0.7)))
attributes.shadow = .active(with: .init(color: .black, opacity: 0.5, radius: 10, offset: .zero))
attributes.scroll = .enabled(swipeable: true, pullbackAnimation: .jolt)
attributes.positionConstraints.maxSize = .init(width: .constant(value: UIScreen.main.bounds.width), height: .intrinsic)
// これがないとアクションが実行されない
attributes.entryInteraction = .absorbTouches
// UIFont() は任意の形に変更する必要がある
let title = EKProperty.LabelContent(text: title, style: .init(font: UIFont(), color: .white))
let description = EKProperty.LabelContent(text: body, style: .init(font: UIFont(), color: .white))
let label = EKProperty.LabelContent(text: "OK", style: .init(font: UIFont(), color: .black))
let button = EKProperty.ButtonContent(label: label, backgroundColor: .white, highlightedBackgroundColor: .standardBackground)
let action: EKPopUpMessage.EKPopUpMessageAction = {
SwiftEntryKit.dismiss()
// ここにボタン押下時のアクションを入れることができる
action()
}
let popupMessage = EKPopUpMessage(title: title, description: description, button: button, action: action)
let view = EKPopUpMessageView(with: popupMessage)
SwiftEntryKit.display(entry: view, using: attributes)
}
}
利用するのはこんな感じ。
Popup.show(title: "Popup title", body: "Popup body") {
print("tapped!!")
}
フォーム付きのポップアップを表示する
struct Form {
// フォームが1つの場合
static func show(title: String, placeholder: String = "", image: UIImage, action: @escaping (String) -> Void) {
var attributes = EKAttributes.centerFloat
attributes.displayDuration = .infinity
attributes.entryBackground = .gradient(gradient: .init(colors: [EKColor(UIColor.purple), EKColor(UIColor.blue)], startPoint: .zero, endPoint: CGPoint(x: 1, y: 1)))
attributes.screenBackground = .visualEffect(style: .prominent)
attributes.popBehavior = .animated(animation: .init(translate: .init(duration: 0.3), scale: .init(from: 1, to: 0.7, duration: 0.7)))
attributes.shadow = .active(with: .init(color: .black, opacity: 0.5, radius: 10, offset: .zero))
attributes.scroll = .enabled(swipeable: true, pullbackAnimation: .jolt)
attributes.positionConstraints.maxSize = .init(width: .constant(value: UIScreen.main.bounds.width), height: .intrinsic)
// これがないとアクションが実行されない
attributes.entryInteraction = .absorbTouches
let white = EKColor(UIColor.white)
let black = EKColor(UIColor.black)
let gray = EKColor(UIColor.gray)
let whiteStyle = EKProperty.LabelStyle(font: UIFont(), color: white)
let blackStyle = EKProperty.LabelStyle(font: UIFont(), color: black)
let title = EKProperty.LabelContent(text: title, style: whiteStyle)
let ok = EKProperty.LabelContent(text: "OK", style: blackStyle)
let placeholder = EKProperty.LabelContent(text: placeholder, style: whiteStyle)
let content = EKProperty.TextFieldContent(keyboardType: .asciiCapable, placeholder: placeholder, tintColor: white, displayMode: .inferred, textStyle: whiteStyle, leadingImage: image, bottomBorderColor: white)
let button = EKProperty.ButtonContent(label: ok, backgroundColor: .white, highlightedBackgroundColor: gtray) {
SwiftEntryKit.dismiss()
action(content.textContent)
}
let view = EKFormMessageView(with: title, textFieldsContent: [content], buttonContent: button)
SwiftEntryKit.display(entry: view, using: attributes)
}
}
利用するのはこんな感じ。
Form.show(title: "Form title", body: "Form body") { value in
print("input value: \(value)")
}
まとめ
他にもToast、Note、Rating等のビューが用意されているが、同様の要領で利用できる。繰り返しになるが、EKNotificationMessageView
など、EKxxxView
を作ってattributes
とともにSwiftEntryKit
に渡せば良い。