在SwiftUI中连续重复操作

时间:2019-06-08 18:20:35

标签: swift 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

}

4 个答案:

答案 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的延迟在toduration状态之间切换。

用法示例:

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()
        }
    }
}