默认情况下,SwiftUI 似乎使用过渡.opacity,因此当视图在动画期间出现/消失时,它会淡入/淡出。这会创建一种交叉淡入淡出效果,通常效果很好,但当一个重叠视图替换另一个视图时,有时可能会出现不良效果。
我遇到的情况是,我\xe2\x80\x99d 宁愿让新视图淡入即将被替换的视图之上。旧视图根本不应该改变不透明度,而应该在转换完成后消失。
\n我不希望在转换过程中的任何时刻我看到旧视图的透明度只有 100%。例如,默认的处理方式会导致过渡中间的某个点,在该点我们会看到后视图和前视图的 50% 不透明度版本相互叠加。
\n需要明确的是,我已经有了一个解决方法:如果我使用 ZStack 始终将背景视图保留在那里,我就可以获得我想要的效果 - 这样只有新视图会淡入(因为它是唯一的视图)变化)。不过,我的解决方案感觉是错误的、浪费的、不优雅的。(背景中的视图将不断地由系统合成,尽管在实际图像加载后它完全不可见且不需要。我只希望背景视图存在直到转换完成,但我无法理解知道如何让它做到这一点。)
\n这是一些显示我的意思的代码。顶部视图使用默认的过渡和交叉淡入淡出显示,但代码按照我期望的方式显示 - 当新视图存在时,我们只使用它。底部按照我想要的方式显示 - 但这样做的代价是始终将背景视图保留在那里,以便只有新视图在第一次出现时才会消失:
\nimport SwiftUI\nimport PlaygroundSupport\n\nstruct ContentView: View {\n let transaction = Transaction(animation: .linear(duration: 10))\n let imageURL = URL(string: "https://www.nasa.gov/sites/default/files/thumbnails/image/main_image_star-forming_region_carina_nircam_final-5mb.jpg")!\n \n var body: some View {\n VStack(spacing: 10) {\n AsyncImage(url: imageURL, transaction: transaction) { phase in\n if let img = phase.image {\n img.resizable()\n } else {\n Color.red\n }\n }\n .aspectRatio(CGSize(width: 3600, height: 2085), contentMode: .fit)\n\n AsyncImage(url: imageURL, transaction: …Run Code Online (Sandbox Code Playgroud)