重寫View,監聽Animation Complete
//VectorArithmetic 可動畫類型的數據 extension View { //定義Data 為 VectorArithmetic //ModifiedContent是指,將此Self示圖,經由AnimationDataChangeModifier,修改後產生新的示圖 //modifier主要是回傳ModifiedContent /*@inlinable public func modifier<T>(_ modifier: T) -> ModifiedContent<Self, T>*/ func onAnimationDataChange<Data: VectorArithmetic>(for data: Data, onComplete: @escaping () -> Void) -> ModifiedContent<Self, AnimationDataChangeModifier<Data>> { return modifier(AnimationDataChangeModifier(changeData: data, onComplete: onComplete)) } } //指處where Data: VectorArithmetic,確保資料類型是VectorArithmetic // AnimatableModifier繼承於 Animatable, ViewModifier,就是可動畫的修改器 struct AnimationDataChangeModifier<Data>: AnimatableModifier where Data: VectorArithmetic { //animatableData是繼承Animatable的資料,監聽他的變化 //didSet是當資料變化的時候觸發 var animatableData: Data { didSet { dataChangeCallback() } } private var previousData: Data private var onComplete: () -> Void //此處要注意,順序很重要 init(changeData: Data, onComplete: @escaping () -> Void) { //先註冊callback,確保觸發的時候,可以正常回調 self.onComplete = onComplete //animatableData發生改變的時候,會調用dataChangeCallback(),才往下執行 //此處是關鍵,因為animatableData改變時,previousData這個還是上次的資料 //可以確定資料是否有改變完成 self.animatableData = changeData previousData = changeData } private func dataChangeCallback() { guard animatableData == previousData else { return } DispatchQueue.main.async { self.onComplete() } } func body(content: Content) -> some View { return content } }
引用方式
//onAnimationDataChange必須要使用withAnimation的變數變化,才會觸發 //因為VectorArithmetic 可動畫類型的數據 struct MainView: View { @State var opacity: Double = 1 @State var animation = false var body: some View { Text("1234567890abcdefg") .opacity(animation ? opacity : 1) .animation(animation ? Animation.linear(duration: 1) : nil) .onAnimationDataChange(for: opacity) { if opacity == 0.1 { withAnimation(Animation.default, { opacity = 1 }) } else { withAnimation(Animation.default, { opacity = 0.1 }) } } .onAppear { animation = true withAnimation(Animation.default, { opacity = 0.1 }) } } }
最後更新日期:2021/01/15