Skip to content

Commit

Permalink
Add cross-platform SwiftUI wrapper for AnimatedButton (#2139)
Browse files Browse the repository at this point in the history
  • Loading branch information
calda authored Aug 15, 2023
1 parent acb433e commit 283a303
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 53 deletions.
8 changes: 6 additions & 2 deletions Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
0820D59B2A8ACE64007D705C /* LottieButtonRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D59A2A8ACE64007D705C /* LottieButtonRow.swift */; };
085D97852A5DF94C00C78D18 /* AnimationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085D97832A5DF76C00C78D18 /* AnimationListView.swift */; };
085D97872A5E0DB600C78D18 /* AnimationPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085D97862A5E0DB600C78D18 /* AnimationPreviewView.swift */; };
085D97892A5E0DBE00C78D18 /* AnimationPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085D97862A5E0DB600C78D18 /* AnimationPreviewView.swift */; };
Expand Down Expand Up @@ -49,6 +50,7 @@

/* Begin PBXFileReference section */
080864BD2A4C955F00D70F30 /* Lottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Lottie.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0820D59A2A8ACE64007D705C /* LottieButtonRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieButtonRow.swift; sourceTree = "<group>"; };
085D97832A5DF76C00C78D18 /* AnimationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationListView.swift; sourceTree = "<group>"; };
085D97862A5E0DB600C78D18 /* AnimationPreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationPreviewView.swift; sourceTree = "<group>"; };
0861BBCC2898964400C3FC66 /* Lottie.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Lottie.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -103,10 +105,11 @@
085D97832A5DF76C00C78D18 /* AnimationListView.swift */,
085D97862A5E0DB600C78D18 /* AnimationPreviewView.swift */,
08E359932A55FFC400141956 /* LottieViewLayoutDemoView.swift */,
08E6CF832A86C49300A6D92F /* ControlsDemoView.swift */,
08E6CF812A86C35B00A6D92F /* LottieSwitchRow.swift */,
0820D59A2A8ACE64007D705C /* LottieButtonRow.swift */,
08E359972A55FFC600141956 /* Example.entitlements */,
607FACD11AFB9204008FA782 /* Products */,
08E6CF812A86C35B00A6D92F /* LottieSwitchRow.swift */,
08E6CF832A86C49300A6D92F /* ControlsDemoView.swift */,
);
path = Example;
sourceTree = "<group>";
Expand Down Expand Up @@ -286,6 +289,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0820D59B2A8ACE64007D705C /* LottieButtonRow.swift in Sources */,
08E359942A55FFC400141956 /* LottieViewLayoutDemoView.swift in Sources */,
08E359922A55FFC400141956 /* ExampleApp.swift in Sources */,
085D97872A5E0DB600C78D18 /* AnimationPreviewView.swift in Sources */,
Expand Down
16 changes: 7 additions & 9 deletions Example/Example/ControlsDemoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,13 @@ struct ControlsDemoView: View {
],
])

// TODO: Add SwiftUI support for AnimatedButton
// AnimatedButtonRow(
// animationName: "Samples/TwitterHeartButton",
// title: "Twitter Heart Button",
// playRanges: [
// .init(fromMarker: "touchDownStart", toMarker: "touchDownEnd", event: .touchDown),
// .init(fromMarker: "touchDownEnd", toMarker: "touchUpCancel", event: .touchUpOutside),
// .init(fromMarker: "touchDownEnd", toMarker: "touchUpEnd", event: .touchUpInside),
// ]))
LottieButtonRow(
animationName: "Samples/TwitterHeartButton",
title: "Twitter Heart Button")

LottieButtonRow(
animationName: "Samples/Switch",
title: "Switch as Button")

LottieSwitchRow(
animationName: "Samples/Issues/issue_1877",
Expand Down
33 changes: 33 additions & 0 deletions Example/Example/LottieButtonRow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Created by Cal Stephens on 8/14/23.
// Copyright © 2023 Airbnb Inc. All rights reserved.

import Lottie
import SwiftUI

// MARK: - LottieSwitchRow

struct LottieButtonRow: View {

// MARK: Internal

var animationName: String
var title: String

var body: some View {
HStack {
LottieButton(animation: .named(animationName)) {
pressCount += 1
}
.animate(fromMarker: "touchDownStart", toMarker: "touchDownEnd", on: .touchDown)
.animate(fromMarker: "touchDownEnd", toMarker: "touchUpCancel", on: .touchUpOutside)
.animate(fromMarker: "touchDownEnd", toMarker: "touchUpEnd", on: .touchUpInside)
.frame(width: 80, height: 80)

Text(verbatim: "\(title) (pressCount=\(pressCount))")
}
}

// MARK: Private

@State private var pressCount = 0
}
26 changes: 17 additions & 9 deletions Lottie.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
0819D2A12A718CAE00D7DE49 /* LottieAnimationSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0819D2A02A718CAE00D7DE49 /* LottieAnimationSource.swift */; };
0819D2A22A718CAE00D7DE49 /* LottieAnimationSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0819D2A02A718CAE00D7DE49 /* LottieAnimationSource.swift */; };
0819D2A32A718CAE00D7DE49 /* LottieAnimationSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0819D2A02A718CAE00D7DE49 /* LottieAnimationSource.swift */; };
0820D5932A8ACD67007D705C /* LottieButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D5922A8ACD67007D705C /* LottieButton.swift */; };
0820D5942A8ACD67007D705C /* LottieButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D5922A8ACD67007D705C /* LottieButton.swift */; };
0820D5952A8ACD67007D705C /* LottieButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D5922A8ACD67007D705C /* LottieButton.swift */; };
0820D5972A8ACDD8007D705C /* AnimatedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D5962A8ACDD7007D705C /* AnimatedButton.swift */; };
0820D5982A8ACDD8007D705C /* AnimatedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D5962A8ACDD7007D705C /* AnimatedButton.swift */; };
0820D5992A8ACDD8007D705C /* AnimatedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0820D5962A8ACDD7007D705C /* AnimatedButton.swift */; };
0887346F28F0CBDE00458627 /* LottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0887346E28F0CBDE00458627 /* LottieAnimation.swift */; };
0887347028F0CBDE00458627 /* LottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0887346E28F0CBDE00458627 /* LottieAnimation.swift */; };
0887347128F0CBDE00458627 /* LottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0887346E28F0CBDE00458627 /* LottieAnimation.swift */; };
Expand Down Expand Up @@ -708,9 +714,6 @@
2EAF5AC527A0798700E00531 /* UIColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D527A0798700E00531 /* UIColorExtension.swift */; };
2EAF5AC627A0798700E00531 /* UIColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D527A0798700E00531 /* UIColorExtension.swift */; };
2EAF5AC727A0798700E00531 /* UIColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D527A0798700E00531 /* UIColorExtension.swift */; };
2EAF5AC827A0798700E00531 /* AnimatedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D627A0798700E00531 /* AnimatedButton.swift */; };
2EAF5AC927A0798700E00531 /* AnimatedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D627A0798700E00531 /* AnimatedButton.swift */; };
2EAF5ACA27A0798700E00531 /* AnimatedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D627A0798700E00531 /* AnimatedButton.swift */; };
2EAF5ACB27A0798700E00531 /* LottieAnimationViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D727A0798700E00531 /* LottieAnimationViewBase.swift */; };
2EAF5ACC27A0798700E00531 /* LottieAnimationViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D727A0798700E00531 /* LottieAnimationViewBase.swift */; };
2EAF5ACD27A0798700E00531 /* LottieAnimationViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EAF59D727A0798700E00531 /* LottieAnimationViewBase.swift */; };
Expand Down Expand Up @@ -855,6 +858,8 @@

/* Begin PBXFileReference section */
0819D2A02A718CAE00D7DE49 /* LottieAnimationSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieAnimationSource.swift; sourceTree = "<group>"; };
0820D5922A8ACD67007D705C /* LottieButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieButton.swift; sourceTree = "<group>"; };
0820D5962A8ACDD7007D705C /* AnimatedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedButton.swift; sourceTree = "<group>"; };
0887346E28F0CBDE00458627 /* LottieAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LottieAnimation.swift; sourceTree = "<group>"; };
0887347228F0CCDD00458627 /* LottieAnimationHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LottieAnimationHelpers.swift; sourceTree = "<group>"; };
0887347328F0CCDD00458627 /* LottieAnimationViewInitializers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LottieAnimationViewInitializers.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1103,7 +1108,6 @@
2EAF59D227A0798700E00531 /* FilepathImageProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilepathImageProvider.swift; sourceTree = "<group>"; };
2EAF59D427A0798700E00531 /* BundleImageProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BundleImageProvider.swift; sourceTree = "<group>"; };
2EAF59D527A0798700E00531 /* UIColorExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColorExtension.swift; sourceTree = "<group>"; };
2EAF59D627A0798700E00531 /* AnimatedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedButton.swift; sourceTree = "<group>"; };
2EAF59D727A0798700E00531 /* LottieAnimationViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LottieAnimationViewBase.swift; sourceTree = "<group>"; };
2EAF59D827A0798700E00531 /* AnimationSubview.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationSubview.swift; sourceTree = "<group>"; };
2EAF59DB27A0798700E00531 /* AnimationTime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationTime.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1353,9 +1357,11 @@
08E6CF852A86E26F00A6D92F /* Controls */ = {
isa = PBXGroup;
children = (
08E6CF882A86E26F00A6D92F /* AnimatedControl.swift */,
08E6CF862A86E26F00A6D92F /* AnimatedSwitch.swift */,
0820D5962A8ACDD7007D705C /* AnimatedButton.swift */,
08E6CF872A86E26F00A6D92F /* LottieSwitch.swift */,
08E6CF882A86E26F00A6D92F /* AnimatedControl.swift */,
0820D5922A8ACD67007D705C /* LottieButton.swift */,
08E6CF922A86E29100A6D92F /* LottieViewType.swift */,
);
path = Controls;
Expand Down Expand Up @@ -1931,7 +1937,6 @@
2EAF59D227A0798700E00531 /* FilepathImageProvider.swift */,
2EAF59D427A0798700E00531 /* BundleImageProvider.swift */,
2EAF59D527A0798700E00531 /* UIColorExtension.swift */,
2EAF59D627A0798700E00531 /* AnimatedButton.swift */,
2EAF59D727A0798700E00531 /* LottieAnimationViewBase.swift */,
2EAF59D827A0798700E00531 /* AnimationSubview.swift */,
);
Expand Down Expand Up @@ -2269,6 +2274,7 @@
82A552752A2FD44B00E47AC8 /* LottieAnimationLayer.swift in Sources */,
08C001FF2A46150D00AB54BA /* Archive+Writing.swift in Sources */,
2E9C97442822F43100677516 /* AnimatorNodeDebugging.swift in Sources */,
0820D5932A8ACD67007D705C /* LottieButton.swift in Sources */,
2E9C96D82822F43100677516 /* AnimatorNode.swift in Sources */,
2E9C96212822F43100677516 /* Bundle.swift in Sources */,
2E9C96CF2822F43100677516 /* ShapeContainerLayer.swift in Sources */,
Expand Down Expand Up @@ -2400,6 +2406,7 @@
08E206F12A56014E002DCE17 /* IndexChangeset.swift in Sources */,
7E48BF582860CECF00A39198 /* UnitBezier.swift in Sources */,
2E9C971A2822F43100677516 /* ShapeAnimation.swift in Sources */,
0820D5972A8ACDD8007D705C /* AnimatedButton.swift in Sources */,
2E9C974A2822F43100677516 /* CGColor+RGB.swift in Sources */,
2E9C96572822F43100677516 /* ShapeCompositionLayer.swift in Sources */,
08E207512A56014E002DCE17 /* ClassReference.swift in Sources */,
Expand Down Expand Up @@ -2514,7 +2521,6 @@
2E9C962A2822F43100677516 /* TextDocument.swift in Sources */,
08E206FA2A56014E002DCE17 /* DiffableSection.swift in Sources */,
2EAF5AE627A0798700E00531 /* LRUAnimationCache.swift in Sources */,
2EAF5AC827A0798700E00531 /* AnimatedButton.swift in Sources */,
08C001FD2A46150D00AB54BA /* URL+ZIP.swift in Sources */,
2E9C962D2822F43100677516 /* Glyph.swift in Sources */,
2E9C96D52822F43100677516 /* RenderNode.swift in Sources */,
Expand Down Expand Up @@ -2605,6 +2611,7 @@
08EF21DD289C643B0097EA47 /* KeyframeInterpolator.swift in Sources */,
2E9C96162822F43100677516 /* Transform.swift in Sources */,
2E9C97482822F43100677516 /* CGFloatExtensions.swift in Sources */,
0820D5942A8ACD67007D705C /* LottieButton.swift in Sources */,
2EAF5AC627A0798700E00531 /* UIColorExtension.swift in Sources */,
08E207072A56014E002DCE17 /* EpoxySwiftUIIntrinsicContentSizeInvalidator.swift in Sources */,
2E9C967F2822F43100677516 /* GradientStrokeRenderer.swift in Sources */,
Expand Down Expand Up @@ -2638,6 +2645,7 @@
2E9C97332822F43100677516 /* CALayer+addAnimation.swift in Sources */,
2E9C969A2822F43100677516 /* ShapeNode.swift in Sources */,
08E206E32A56014E002DCE17 /* ViewType.swift in Sources */,
0820D5982A8ACDD8007D705C /* AnimatedButton.swift in Sources */,
2EAF5AD527A0798700E00531 /* AnimationTime.swift in Sources */,
08E207552A56014E002DCE17 /* AnyEpoxyModelProperty.swift in Sources */,
08C002D72A46196300AB54BA /* Entry+ZIP64.swift in Sources */,
Expand Down Expand Up @@ -2813,7 +2821,6 @@
2E9C962B2822F43100677516 /* TextDocument.swift in Sources */,
08E207012A56014E002DCE17 /* UIViewConfiguringSwiftUIView.swift in Sources */,
2EAF5AE727A0798700E00531 /* LRUAnimationCache.swift in Sources */,
2EAF5AC927A0798700E00531 /* AnimatedButton.swift in Sources */,
08C002D92A46196300AB54BA /* URL+ZIP.swift in Sources */,
2E9C962E2822F43100677516 /* Glyph.swift in Sources */,
2E9C96D62822F43100677516 /* RenderNode.swift in Sources */,
Expand Down Expand Up @@ -2848,6 +2855,7 @@
82A552772A2FD44B00E47AC8 /* LottieAnimationLayer.swift in Sources */,
2E9C97462822F43100677516 /* AnimatorNodeDebugging.swift in Sources */,
2E9C96DA2822F43100677516 /* AnimatorNode.swift in Sources */,
0820D5952A8ACD67007D705C /* LottieButton.swift in Sources */,
08C002E92A46196300AB54BA /* Entry+ZIP64.swift in Sources */,
2E9C96232822F43100677516 /* Bundle.swift in Sources */,
2E9C96D12822F43100677516 /* ShapeContainerLayer.swift in Sources */,
Expand Down Expand Up @@ -2979,6 +2987,7 @@
08E206F32A56014E002DCE17 /* IndexChangeset.swift in Sources */,
7E48BF5A2860CECF00A39198 /* UnitBezier.swift in Sources */,
2E9C971C2822F43100677516 /* ShapeAnimation.swift in Sources */,
0820D5992A8ACDD8007D705C /* AnimatedButton.swift in Sources */,
2E9C974C2822F43100677516 /* CGColor+RGB.swift in Sources */,
2E9C96592822F43100677516 /* ShapeCompositionLayer.swift in Sources */,
08E207532A56014E002DCE17 /* ClassReference.swift in Sources */,
Expand Down Expand Up @@ -3089,7 +3098,6 @@
2E9C963B2822F43100677516 /* PrecompAsset.swift in Sources */,
2E9C962C2822F43100677516 /* TextDocument.swift in Sources */,
2EAF5AE827A0798700E00531 /* LRUAnimationCache.swift in Sources */,
2EAF5ACA27A0798700E00531 /* AnimatedButton.swift in Sources */,
2E9C962F2822F43100677516 /* Glyph.swift in Sources */,
08E206FC2A56014E002DCE17 /* DiffableSection.swift in Sources */,
2E9C96D72822F43100677516 /* RenderNode.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Sources/Public/Animation/LottieAnimationLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import QuartzCore
// MARK: - LottieAnimationLayer

/// A CALayer subclass for rendering Lottie animations.
/// All functionality is also available in a UIView as `LottieAnimationView`.
/// - Also available as a SwiftUI view (`LottieView`) and a UIView subclass (`LottieAnimationView`)
public class LottieAnimationLayer: CALayer {

// MARK: Lifecycle
Expand Down
2 changes: 1 addition & 1 deletion Sources/Public/Animation/LottieAnimationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ extension LottieLoopMode: Equatable {
// MARK: - LottieAnimationView

/// A UIView subclass for rendering Lottie animations.
/// All functionality is also available in a CALayer as `LottieAnimationLayer`.
/// - Also available as a SwiftUI view (`LottieView`) and a CALayer subclass (`LottieAnimationLayer`)
@IBDesignable
open class LottieAnimationView: LottieAnimationViewBase {

Expand Down
4 changes: 2 additions & 2 deletions Sources/Public/Animation/LottieView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ public struct LottieView<Placeholder: View>: UIViewConfiguringSwiftUIView {
/// when an animation finishes playing.
public func animationDidFinish(_ animationCompletionHandler: LottieCompletionBlock?) -> Self {
var copy = self
copy.animationCompletionHandler = { completed in
copy.animationCompletionHandler = { [previousCompletionHandler = self.animationCompletionHandler] completed in
previousCompletionHandler?(completed)
animationCompletionHandler?(completed)
copy.animationCompletionHandler?(completed)
}
return copy
}
Expand Down
Loading

0 comments on commit 283a303

Please sign in to comment.