Skip to main content

Widget styling and customization

The best way to style and customize the widget is using StorifyMe Widget Editor, which is a visual tool available inside StorifyMe platform.

SDK specific styling

Loading animation

You can display a loading animation while the story widget fetches and renders content.

info

The loading animation is disabled by default. You must explicitly enable it with setWidgetLoadingAnimationStyle.

Default animation

Enable the built-in spinner with an optional tint color:

// Default gray spinner
storifyMeWidget.setWidgetLoadingAnimationStyle(enabled: true)

// Custom tint color
storifyMeWidget.setWidgetLoadingAnimationStyle(enabled: true, color: .systemBlue)

Custom animation

Pass any UIView subclass to fully replace the built-in spinner. The view is centered inside the widget while content loads and removed automatically once loading completes.

let loadingView = MyLoadingAnimationView()
storifyMeWidget.setWidgetLoadingAnimationStyle(
type: .custom(view: loadingView),
enabled: true
)

Below is an example of a dot-wave loading animation — 12 dots arranged in a circle with a staggered pulse effect.

Click to view DotWaveLoadingView example
import UIKit

class DotWaveLoadingView: UIView {

private let dotCount = 12
private let animDuration: TimeInterval = 1.2
private let delayPerDot: TimeInterval = 0.1

private var dotColor: UIColor = .darkGray
private var displayLink: CADisplayLink?

override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
}

@available(*, unavailable)
required init?(coder: NSCoder) { fatalError() }

override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
if newWindow != nil {
startDisplayLink()
} else {
stopDisplayLink()
}
}

override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }

let cx = rect.midX
let cy = rect.midY
let circleRadius = min(cx, cy) * 0.75
let dotRadius = min(cx, cy) * 0.11
let now = CACurrentMediaTime()

for i in 0..<dotCount {
let angleDeg = -90.0 + Double(i) * 30.0
let angleRad = angleDeg * .pi / 180.0
let dotX = cx + CGFloat(cos(angleRad)) * circleRadius
let dotY = cy + CGFloat(sin(angleRad)) * circleRadius

let delay = Double(i) * delayPerDot
let elapsed = (now - delay).truncatingRemainder(dividingBy: animDuration)
let wrappedElapsed = elapsed < 0 ? elapsed + animDuration : elapsed
let t = CGFloat(wrappedElapsed / animDuration)

let pulse = (1.0 - cos(2.0 * .pi * t)) / 2.0
let alpha = 0.3 + pulse * 0.7
let radius = dotRadius * (1.0 + pulse * 0.5)

ctx.setFillColor(dotColor.withAlphaComponent(alpha).cgColor)
ctx.fillEllipse(in: CGRect(
x: dotX - radius,
y: dotY - radius,
width: radius * 2,
height: radius * 2
))
}
}

func setColor(_ color: UIColor) {
dotColor = color
setNeedsDisplay()
}

private func startDisplayLink() {
guard displayLink == nil else { return }
let link = CADisplayLink(target: self, selector: #selector(tick))
link.add(to: .main, forMode: .common)
displayLink = link
}

private func stopDisplayLink() {
displayLink?.invalidate()
displayLink = nil
}

@objc private func tick() { setNeedsDisplay() }
}

Use it with the widget:

let dotWave = DotWaveLoadingView(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
dotWave.setColor(.darkGray)

storifyMeWidget.setWidgetLoadingAnimationStyle(
type: .custom(view: dotWave),
enabled: true
)

Disable animation

storifyMeWidget.setWidgetLoadingAnimationStyle(enabled: false)

Custom font

Download the font, it should be in .ttf format, maybe some others will do. Place it somewhere in the project you want.

In Info.plist you need to set

  • Source code
<dict>
....
<key>UIAppFonts</key>
<array>
<string>Finger Paint.ttf</string>
</array>
....
  • Regular view

Add view

Opening story animation

Stories presenting can be customized by setting StorifyMeStoryViewerOptions.

The default behavior is listed below and can be easily customized.

storifyMeWidget.setStoryViewerOptions(
options: StorifyMeStoryViewerOptions(
thumbnailItemOpeningAnimationDuration: 0.2,
thumbnailItemClosingAnimationDuration: 0.2,
storyPreviewerOpeningAnimationDuration: 0.2,
storyPreviewerClosingAnimationDuration: 0.2,
enabled: true))

If for some reason you want to disable the animations, just use the code below.

storifyMeWidget.setStoryViewerOptions(
options: StorifyMeStoryViewerOptions(
enabled: false))

Grid Collection View Behavior

StorifyMeGridCollectionViewBehavior which offers flexible options for customizing the behavior of grid collection views. This includes the capability to adjust the height of the first story using the setGridCollectionViewBehavior(.adjustFirstStoryHeight(byMultiplier:)) method.

storifyMeWidget.setGridCollectionViewBehavior(
.adjustFirstStoryHeight(byMultiplier: 0.75))