如何使诸如文本字段之类的元素按比例放大然后连续缩小?
我有这个:
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
}
答案 0 :(得分:2)
一种可能的解决方案是使用(重复,自动反转)动画:
struct ContentView : View {
@State var size: CGFloat = 0.5
var repeatingAnimation: Animation {
Animation
.basic(duration: 2)
.repeatForever()
}
var body: some View {
Text("Hello!")
.padding()
.scaleEffect(size)
.onAppear() {
withAnimation(self.repeatingAnimation) { self.size = 1.3 }
}
}
}
答案 1 :(得分:2)
Animation.basic已弃用。现在,基本动画以其曲线类型命名:例如线性等:
var foreverAnimation: Animation {
Animation.linear(duration: 0.3)
.repeatForever()
}
来源: https://forums.swift.org/t/swiftui-animation-basic-duration-curve-deprecated/27076
答案 2 :(得分:1)
最好的方法是创建单独的动画结构并配置所需的所有选项(这样您的代码将更加紧凑)。
使用@State属性inProgress使其更加清晰和逻辑。您将能够停止动画并再次恢复并了解动画的进行时间。
@State private var isAnimating = false
var foreverAnimation: Animation {
Animation.basic(duration: 0.3)
.repeatForever()
}
var body: some View {
Text("Hello")
.scaleEffect(isAnimating ? 1.5 : 1)
.animation(foreverAnimation)
.onAppear {
self.isAnimating = true
}
}
答案 3 :(得分:0)
在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)
}
}
编辑:
当显示条件为true出现时,过渡不会开始。为了解决这个问题,我确实切换了超级视图的出现条件(在我的示例中为VStack):
.onAppear {
if self.showBlinkingView {
self.showBlinkingView.toggle()
DispatchQueue.main.async {
self.showBlinkingView.toggle()
}
}
}