Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

AnimationLimitBreaker

This enables infinite loop animations in Widget.
And this library is implemented with reference to brycebostwick/WidgetAnimation.

sample widget animation

Requirements

  • Development with Xcode 16.4+
  • Written in Swift 6.1
  • Compatible with iOS 18.0+

Usage

import AnimationLimitBreaker
import SwiftUI
import WidgetKit
structSampleEntry:TimelineEntry{vardate:Date}structSampleProvider:TimelineProvider{func placeholder(in context:Context)->SampleEntry{SampleEntry(date:.now)}func getSnapshot(in context:Context, completion:@escaping(SampleEntry)->()){completion(SampleEntry(date:.now))}func getTimeline(in context:Context, completion:@escaping(Timeline<Entry>)->()){completion(Timeline(entries:[SampleEntry(date:.now)], policy:.never))}}structSampleWidgetEntryView:View{varentry:SampleProvider.Entryvarimages:[Image]init(entry:SampleProvider.Entry){self.entry = entry
self.images =[0,33,50,67,100,67,50,33].map{ i inImage(systemName:"gauge.with.dots.needle.\(i)percent")}}varbody:someView{GeometryReader{ proxy in
// Use ForceAnimatingView in the widget.
// The provided image will loop playback at 2-second intervals.
ForceAnimatingView(
size:min(proxy.size.width, proxy.size.height),
images: images
).frame(maxWidth:.infinity, alignment:.center)}}}structSampleWidget:Widget{letkind:String="SampleWidget"init(){
// As a preparatory step, you need to register the custom font.
AnimationLimitBreaker.registerFont()}varbody:someWidgetConfiguration{StaticConfiguration(kind: kind, provider:SampleProvider()){ entry inSampleWidgetEntryView(entry: entry).containerBackground(.fill.tertiary, for:.widget)}.configurationDisplayName("Sample Widget").description("This is a sample widget.")}}@mainstructSampleWidgetBundle:WidgetBundle{varbody:someWidget{SampleWidget()}}

Principle

First, the only component in Widgets that can animate infinitely is a timer using Text (e.g., Text(date: .now, style: .timer)). Therefore, we take full advantage of this Text-based timer to implement frame-by-frame animation.

Since Text allows custom fonts, we apply a specially designed font in which odd values render as transparent and even values render as black squares. This creates a view that blinks between transparent and black every second.

Next, by overlapping and slightly offsetting this view in time and using it as a mask, the black square will only appear during the intervals when all layers are non-transparent. By then masking any arbitrary view with this mechanism, it becomes possible to display that view only for the specified short duration.

Finally, stacking these layers with ZStack enables frame-by-frame animation.

animation principle

About

This enables infinite loop animations in Widget.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages