animation - SwiftUI animation 视图更改后不连续

这是测试代码:

import SwiftUI
struct ContentView: View {
  @State private var pad: Bool = false
  @State private var showDot: Bool = true
  var body: some View {
    VStack {
      Button {showDot.toggle()} label: {Text("Toggle Show Dot")}
      Spacer().frame(height: pad ? 100 : 10)
      Circ(showDot: showDot)
      Spacer()
    }.onAppear {
      withAnimation(.linear(duration: 3).repeatForever()) {pad = true}
    }
  }
}

struct Circ: View {
  let showDot: Bool
  var body: some View {
    Circle().stroke().frame(height: 50).overlay {if showDot {Circle().frame(height: 20)}}
  }
}

碰巧在我切换showDot之后,点圈又不在笔画圈的中心了!我怎样才能解决这个问题? Circ 视图已给出,我无法更改该视图!

回答1

编辑

如果您可以隐藏视图,请参阅解决方案 1,这是首选。如果需要重新构建视图,请参见解决方案 2。

解决方案 1

showDottrue 时,将 if 条件替换为读取 1 的 .opacity() 修饰符。

这样,点不会完全消失,它就在那里,但你看不到它。您将切换可见性,而不是视图本身。

像这样:

@State private var pad: Bool = false
    @State private var showDot: Bool = true
    
    var body: some View {
        VStack {
            Button {
                showDot.toggle()
            } label: {
                Text("Toggle Show Dot")
            }
            
            Spacer()
                .frame(height: pad ? 100 : 10)
            
            Circle().stroke()
                .frame(height: 50)
                .overlay {
                    Circle()
                        .frame(height: 20)
                        .opacity(showDot ? 1 : 0)   // <- Here
                }
            
            Spacer()
            
        }
        .onAppear {
            withAnimation(.linear(duration: 3).repeatForever()) {pad = true}
        }
    }

解决方案 2

您可以将 animation 替换为计时器。每次触发时,都会通过改变Spacer()的高度来移动整个视图。

// These variables will track the position and moving direction of the dot
    @State private var pos: CGFloat = 0
    @State private var movingUp = false
    
    @State private var showDot: Bool = true
    
    // This variable will change the position
    // This is a dummy iniatialization, the .onAppear modifier sets the real timer
    @State private var timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in }
        
    var body: some View {
        VStack {
            Button {
                showDot.toggle()
            } label: {
                Text("Toggle Show Dot")
            }
            
            Spacer()
                .frame(height: pos)

            Circle().stroke()
                .frame(height: 50)
                .overlay {
                    if showDot {
                        Circle().frame(height: 20)
                    }
                }
            
            Spacer()
            
        }
        .onAppear {
            
            // The timer interval will define the speed
            timer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { _ in
                moveCircle()
            }
        }
    }
    
    private func moveCircle() {
        if movingUp {
            if pos <= 0 {
                pos = 0
                movingUp = false
            } else {
                pos -= 1
            }
        } else {
            if pos >= 100 {
                pos = 100
                movingUp = true
            } else {
                pos += 1
            }
        }
    }

相似文章

javascript - 改变 h1 的宽度

我在下面有这段代码,可以让文本很好地淡入。但是,正如您在下面运行它时所看到的,它没有显示在h1.h中指定的整个文本。所以我对如何解决这个问题有点困惑,因为查看css,它没有指定div或h1的宽度实际在...

随机推荐

最新文章