在 SwiftUI 中连续重复操作
Repeating Action Continuously In SwiftUI
如何使文本字段等元素连续放大然后缩小?
我有这个:
struct ContentView : View {
@State var size:Double = 0.5
var body: some View {
ZStack {
Text("Hello!")
.padding()
.scaleEffect(size)
}
}
}
我知道我需要增加大小然后在某种循环中减少它,但在 SwiftUI 中无法完成以下操作:
while true {
self.size += 0.8
sleep(0.2)
self.size -= 0.8
}
一个可能的解决方案是使用(重复,auto-reversing)动画:
struct ContentView : View {
@State var size: CGFloat = 0.5
var repeatingAnimation: Animation {
Animation
.easeInOut(duration: 2) //.easeIn, .easyOut, .linear, etc...
.repeatForever()
}
var body: some View {
Text("Hello!")
.padding()
.scaleEffect(size)
.onAppear() {
withAnimation(self.repeatingAnimation) { self.size = 1.3 }
}
}
}
最好的方法是创建单独的动画结构并配置您需要的所有选项(这样您的代码会更紧凑)。
为了使其更加清晰和合乎逻辑,请使用@State 属性 isAnimating
。您将能够停止动画并再次恢复并了解动画何时进行。
@State private var isAnimating = false
var foreverAnimation: Animation {
Animation.linear(duration: 0.3)
.repeatForever()
}
var body: some View {
Text("Hello")
.scaleEffect(isAnimating ? 1.5 : 1)
.animation(foreverAnimation)
.onAppear {
self.isAnimating = true
}
}
Animation.basic 已弃用。基本动画现在以其曲线类型命名:如线性等:
var foreverAnimation: Animation {
Animation.linear(duration: 0.3)
.repeatForever()
}
来源:
https://forums.swift.org/t/swiftui-animation-basic-duration-curve-deprecated/27076
在 if 语句中使用时,在视图上使用重复动画会出现奇怪的行为。
如果你想做:
if something {
BlinkingView()
}
使用带有动画修饰符的转换,否则即使 something
设置为 false,视图仍停留在屏幕上。
我进行此扩展以显示重复从一种状态到另一种状态并返回的视图:
extension AnyTransition {
static func repeating<T: ViewModifier>(from: T, to: T, duration: Double = 1) -> AnyTransition {
.asymmetric(
insertion: AnyTransition
.modifier(active: from, identity: to)
.animation(Animation.easeInOut(duration: duration).repeatForever())
.combined(with: .opacity),
removal: .opacity
)
}
}
这使得视图随着 AnyTransition.opacity
出现和消失,并且在显示时它会在 from
和 to
状态之间切换,延迟 duration
。
用法示例:
struct Opacity: ViewModifier {
private let opacity: Double
init(_ opacity: Double) {
self.opacity = opacity
}
func body(content: Content) -> some View {
content.opacity(opacity)
}
}
struct ContentView: View {
@State var showBlinkingView: Bool = false
var body: some View {
VStack {
if showBlinkingView {
Text("I am blinking")
.transition(.repeating(from: Opacity(0.3), to: Opacity(0.7)))
}
Spacer()
Button(action: {
self.showBlinkingView.toggle()
}, label: {
Text("Toggle blinking view")
})
}.padding(.vertical, 50)
}
}
编辑:
当显示条件为真时,转换不会开始。为了解决这个问题,我确实切换了超级视图出现的条件(在我的例子中是 VStack):
.onAppear {
if self.showBlinkingView {
self.showBlinkingView.toggle()
DispatchQueue.main.async {
self.showBlinkingView.toggle()
}
}
}
如何使文本字段等元素连续放大然后缩小?
我有这个:
struct ContentView : View {
@State var size:Double = 0.5
var body: some View {
ZStack {
Text("Hello!")
.padding()
.scaleEffect(size)
}
}
}
我知道我需要增加大小然后在某种循环中减少它,但在 SwiftUI 中无法完成以下操作:
while true {
self.size += 0.8
sleep(0.2)
self.size -= 0.8
}
一个可能的解决方案是使用(重复,auto-reversing)动画:
struct ContentView : View {
@State var size: CGFloat = 0.5
var repeatingAnimation: Animation {
Animation
.easeInOut(duration: 2) //.easeIn, .easyOut, .linear, etc...
.repeatForever()
}
var body: some View {
Text("Hello!")
.padding()
.scaleEffect(size)
.onAppear() {
withAnimation(self.repeatingAnimation) { self.size = 1.3 }
}
}
}
最好的方法是创建单独的动画结构并配置您需要的所有选项(这样您的代码会更紧凑)。
为了使其更加清晰和合乎逻辑,请使用@State 属性 isAnimating
。您将能够停止动画并再次恢复并了解动画何时进行。
@State private var isAnimating = false
var foreverAnimation: Animation {
Animation.linear(duration: 0.3)
.repeatForever()
}
var body: some View {
Text("Hello")
.scaleEffect(isAnimating ? 1.5 : 1)
.animation(foreverAnimation)
.onAppear {
self.isAnimating = true
}
}
Animation.basic 已弃用。基本动画现在以其曲线类型命名:如线性等:
var foreverAnimation: Animation {
Animation.linear(duration: 0.3)
.repeatForever()
}
来源: https://forums.swift.org/t/swiftui-animation-basic-duration-curve-deprecated/27076
在 if 语句中使用时,在视图上使用重复动画会出现奇怪的行为。
如果你想做:
if something {
BlinkingView()
}
使用带有动画修饰符的转换,否则即使 something
设置为 false,视图仍停留在屏幕上。
我进行此扩展以显示重复从一种状态到另一种状态并返回的视图:
extension AnyTransition {
static func repeating<T: ViewModifier>(from: T, to: T, duration: Double = 1) -> AnyTransition {
.asymmetric(
insertion: AnyTransition
.modifier(active: from, identity: to)
.animation(Animation.easeInOut(duration: duration).repeatForever())
.combined(with: .opacity),
removal: .opacity
)
}
}
这使得视图随着 AnyTransition.opacity
出现和消失,并且在显示时它会在 from
和 to
状态之间切换,延迟 duration
。
用法示例:
struct Opacity: ViewModifier {
private let opacity: Double
init(_ opacity: Double) {
self.opacity = opacity
}
func body(content: Content) -> some View {
content.opacity(opacity)
}
}
struct ContentView: View {
@State var showBlinkingView: Bool = false
var body: some View {
VStack {
if showBlinkingView {
Text("I am blinking")
.transition(.repeating(from: Opacity(0.3), to: Opacity(0.7)))
}
Spacer()
Button(action: {
self.showBlinkingView.toggle()
}, label: {
Text("Toggle blinking view")
})
}.padding(.vertical, 50)
}
}
编辑:
当显示条件为真时,转换不会开始。为了解决这个问题,我确实切换了超级视图出现的条件(在我的例子中是 VStack):
.onAppear {
if self.showBlinkingView {
self.showBlinkingView.toggle()
DispatchQueue.main.async {
self.showBlinkingView.toggle()
}
}
}