这个 SwiftUI 动画应该只会淡出。为什么会向右移动?

This SwiftUI animation should only fade out. Why does it move to the right?

我很难理解为什么会这样。我将问题简化为最小表达方式。

我有一个 Text 视图,删除后应该会淡出。添加 .transition(.opacity) 只是为了清楚起见。不需要它,因为它是默认设置。然而结果是,除了淡出之外,文本视图向右滑动。

通过调整文本长度,我意识到在转换过程中,它的左边距要与 CHANGE 按钮的左边距对齐。但是为什么?!

反之,加回去时,工作正常,没有动静。只是一个很好的淡入效果。

问题不仅出现在 iOS 上,也出现在 macOS 上。使用 Xcode 11 测试版 2.

import SwiftUI

struct ContentView : View {
    @State private var showText = true
    
    var body: some View {
        VStack {
            Spacer()
            
            if showText {
                Text("I should always be centered!")
                    .font(.largeTitle)
                    .transition(.opacity)
            }
            
            Spacer()
            
            Button {
                withAnimation(.basic(duration: 1.5)) {
                    self.showText.toggle() 
                }
            } label: {
                Text("CHANGE")
                    .font(.title)
            }
            
            Spacer()
        }
    }
}

SwiftUI 自动为布局更改设置动画。

我的理论是当你隐藏它时 Spacer 取代了 Text,并且通过扩展来填充超级视图,它将 Text 推向屏幕.

您可以通过以下方法解决问题:

Text("I should always be centered!")
                .font(.largeTitle)
                .opacity(showText ? 1 : 0)

Text 不往这边移动会淡出 in/out。

我会回答我自己的问题...事实证明,父视图在转换过程中缩小,使文本视图随之移动。为了说明,我在视图中添加了一些边框:

为了解决问题,我必须保证父视图不收缩。就像添加这个一样简单:

HStack { Spacer() }

修改后的代码如下所示:

import SwiftUI

struct ContentView : View {
    @State private var showText = true
    
    var body: some View {
        VStack {
            Spacer()
            
            if showText {
                Text("I should always be centered!")
                    .font(.largeTitle)
                    .transition(.opacity)
                    .border(Color.blue)
            }
            
            Spacer()
            
            Button {
                withAnimation(.basic(duration: 1.5)) {
                    self.showText.toggle() 
                }
            } label: {
                Text("CHANGE")
                    .font(.title)
                    .border(Color.blue)
            }
            
            Spacer()
            
            // This ensures the parent is kept wide to avoid the shift.
            HStack { Spacer() }   
        }
        .border(Color.green)
    }
}

我仍然认为这是一个错误,否则,fade-in 应该有相同的行为,但事实并非如此。如果这不是错误,那么这不是人们所期望的。我将提交错误报告。