How can I create a smooth colour change animation using swiftUI? (Example in question)
Here is a demo of possible approach - just use some shape (circle in this case) between text and opaque background and move it depending on state.
Prepared with Xcode 12.4 / iOS 14.4
Note: you can use just tap gesture instead of button and tune all parameters and colors, but in general the idea remains the same
struct DemoView: View {
@State private var playing = false
var body: some View {
Button(action: { playing.toggle() }) {
HStack{
Image(systemName: playing ? "pause" : "play")
Text(playing ? "STOP" : "PLAY")
.bold()
}
.background(
Circle().fill(Color.purple)
.frame(width: 160, height: 160, alignment: .leading)
.blur(radius: 3)
.offset(x: playing ? 0 : -160, y: -40)
.animation(.easeInOut(duration: 1), value: playing)
)
.padding()
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(25)
.clipped()
.shadow(radius: 20)
}
}
}
How can I create an animation color change from center of a view in SwiftUI?
You can use two Circle
s in a ZStack
and animate the scale effect value of the top most circle.
struct ContentView: View {
private let colors: [Color] = [.red, .yellow, .blue, .pink, .orange]
private let maxScaleEffect: CGFloat = 4.0
private let minScaleEffect: CGFloat = 0
private let animationDuration = 0.6
private let animationDelay = 0.1
@State private var shouldTransition = true
@State private var colorIndex = 0
var body: some View {
ZStack {
Circle()
.fill(previousColor)
.scaleEffect(maxScaleEffect)
Circle()
.fill(transitioningColor)
.scaleEffect(shouldTransition ? maxScaleEffect : minScaleEffect)
Button("Change color") {
shouldTransition = false
colorIndex += 1
// Removing DispatchQueue here will cause the first transition not to work
DispatchQueue.main.asyncAfter(deadline: .now() + animationDelay) {
withAnimation(.easeInOut(duration: animationDuration)) {
shouldTransition = true
}
}
}
.foregroundColor(.primary)
}
}
private var previousColor: Color {
colors[colorIndex%colors.count]
}
private var transitioningColor: Color {
colors[(colorIndex+1)%colors.count]
}
}
SwiftUI - Animate resize of a view frame
I don't know exactly what you need but here is a very basic example with a Rectangle
that gets scaled when you tap the Button
:
struct ContentView: View {
@State var animate = false
var body: some View {
VStack {
Button(action: {
withAnimation {
self.animate.toggle()
}
}, label: {
Text("Animate")
})
Rectangle()
.foregroundColor(.blue)
.frame(width: self.animate ? 100 : 150, height: self.animate ? 60 : 90)
}
}
}
Please add some code to your next question or edit the question so people can provide a more specific answer.
Make the soft gradient between colors of LinearGradient removed
You can use LinearGradient(stops: ) init. It will not give you a full hard edge, but quite close. You can then change the stop values or the array for animation.
struct ContentView: View {
let stops = [Gradient.Stop(color: Color.green, location: 0.0),
Gradient.Stop(color: Color.green, location: 0.33),
Gradient.Stop(color: Color.blue, location: 0.33),
Gradient.Stop(color: Color.blue, location: 0.66),
Gradient.Stop(color: Color.red, location: 0.66),
Gradient.Stop(color: Color.red, location: 1.0)]
var body: some View {
Rectangle()
.fill(
LinearGradient(stops: stops, startPoint: .trailing, endPoint: .leading)
)
.frame(height: 200)
.padding()
}
}
How to animate/transition text value change in SwiftUI
So it turns out this is really easy
Text(textValue)
.font(.largeTitle)
.frame(width: 200, height: 200)
.transition(.opacity)
.id("MyTitleComponent" + textValue)
Note the additional id
at the end. SwiftUI uses this to decide if it's dealing with the same view or not when doing a redraw. If the id is different then it assumes the previous view was removed and this one has been added. Because it's adding a new view it applies the specified transition as expected.
NB: It's quite possible that this id should be unique for the entire view tree so you probably want to take care to namespace it accordingly (hence the MyTitleComponent
prefix in the example).
Animation transition of one gradient to another SwiftUI
We need to animate container to make transition work, so here is a solution:
Text("random button")
.background(
VStack {
if self.animCheck {
LinearGradient(gradient: Gradient(colors: [.white, .green]), startPoint: .leading, endPoint: .trailing)
.transition(.slide)
} else {
LinearGradient(gradient: Gradient(colors: [.black, .orange]), startPoint: .leading, endPoint: .trailing)
.transition(.slide)
}
}.animation(.spring()))
iOS - Smooth Color Change Transition/Animation
One possible way of doing it is apply background color animation on view's layer.
Now to pass through entire spectrum you have to work on combinations of three colors.
The best way to achieve this is to use 'Hue'.
[[UIColor alloc] initWithHue:135/360.0f saturation:1
brightness:1 alpha:1]
Now you have to iterate for all Hue values and you will get the smooth transition that goes across all the spectrum.
Sample code:
- make a local variable
int _currentColorHue = 0;
- recursive call for change background color.
-(void)animateMyView
{[UIView animateWithDuration:0.01 animations:^{
self.view.layer.backgroundColor = [[UIColor alloc] initWithHue:_currentColorHue/360.0f saturation:1 brightness:1 alpha:1].CGColor;
} completion:^(BOOL finished)
{
_currentColorHue++;
if (_currentColorHue > 360)
{
_currentColorHue = 0;
}
[self animateMyView];
}];
}
You can stop the animation according to your use.
How to animate transition between views in SwiftUI?
With the following approach you can modify your appMode
as you wish (onAppear, onTapGesture, etc.). Animation duration is, of course, can be set any you wish (as well as kind of transition, actually, however some transitions behaves bad in Preview, and should be tested on Simulator or real device).
Demo: (first blink is just Preview launch, then two transitions for onAppear, then for onTap)
Tested with Xcode 11.4 / iOS 13.4 - works and in Preview and in Simulator.
Code: Important parts marked with comments inline.
var body: some View {
ZStack {
// !! to keep background deepest, `cause it affects removing transition
Color.blue.zIndex(-1)
// !! keep any view in explicit own `if` (don't use `else`)
if .game == self.appStore.appMode {
GameView()
.transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
}
if .options == self.appStore.appMode {
OptionsView()
.transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
}
if .menu == self.appStore.appMode {
MenuView()
.transition(AnyTransition.scale.animation(.easeInOut(duration: 1)))
}
}
}
Update: for .slide
(and probably other moving transitions) the change of state should be wrapped into explicit withAnimation
, like below
withAnimation {
self.appStore.appMode = new_mode_here
}
Note: these is one of transitions that is not supported by Preview - test in Simulator.
Example for transition like
...
if .menu == self.appStore.appMode {
Text("MenuView").frame(width: 300, height: 100).background(Color.red)
.transition(AnyTransition.move(edge: .bottom).combined(with: .opacity).animation(.easeInOut(duration: 1)))
}
}
.onTapGesture {
withAnimation {
let next = self.appStore.appMode.rawValue + 1
self.appStore.appMode = next > 2 ? .game : AppStore.AppMode(rawValue: next)!
}
}
Related Topics
How to Completely Remove All Xcode Program and Cache Files
Check If Class Has a Value for a Key
Swift Type Inference and Type Checking Issue
Testing a Timer in Xcode with Xctest
Swift Unable to Locate and Read Property List (.Plist) File
Save/Copy a File from Bundle to Desktop Using Nssavepanel
Navigationlink Inside .Searchable Does Not Work
Swiftui: What Are The Differences Between Image and UIimage
Extra Argument Userinfo in Call
Nscollectionview Selection Handling in Swift
Bundle.Main.Path(Forresource... Always Returns Nil When Looking for Xml File
Load Viewcontroller Swift - Black Screen
Accessing an Actor's Isolated State from Within a Swiftui View
Storagemetadata' Has No Member 'Downloadurl'
Keyboard Height Change Observer Swift
How to Use Passed Parameters in Swift Setmethodcallhandler - Self.Methodname(Result: Result)
How to Get The Coordinates of The Point on a Line That Has The Smallest Distance from Another Point