SwiftUI - 使用 .easeInOut 在 ZStack 中动画化视图不透明度

SwiftUI - animating View opacity in ZStack with .easeInOut

我有一个位于 mapView 顶部的视图(在 ZStack 中),并且希望能够使用应用于视图不透明度的 .easeInOut 动画修改器使绿色的上方视图淡入淡出.正如您在 gif 中看到的,它很好地淡入但突然消失。

如果我删除 mapView 那么一切都很好。如果我用简单的 Rectangle() 替换 mapView 那么问题 returns 所以我相信它与 ZStack 而不是地图有关。有趣的是,我实际上使用的是 Mapbox 而不是 MapKit(为简单起见,在下面的代码中)并且 fade/abrupt 消失行为是相反的。

import SwiftUI
import MapKit

struct ContentView: View {
    @State private var show = false

    var body: some View {
        VStack {
            ZStack {
                MapView()
                if show {
                    LabelView()
                        .transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
                }
            }
            Button("Animate") {
                self.show.toggle()
            }.padding(20)
        }
    }
}

struct MapView: UIViewRepresentable {
    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.mapType = .standard
        return mapView
    }

    func updateUIView(_ uiView: MKMapView, context: Context) { }
}

struct LabelView: View {
    var body: some View {
        Text("Hi there!")
            .padding(10)
            .font(.title)
            .foregroundColor(.white)
            .background(RoundedRectangle(cornerRadius: 8).fill(Color.green).shadow(color: .gray, radius: 3))
    }
}

我尝试使用替代动画代码,将 LabelView 过渡替换为:

.transition(.opacity)

并将按钮代码更改为:

Button("Animate") {
    withAnimation(.easeInOut(duration: 1.0)) {
        self.show.toggle()
    }
}

但每次都出现相同的行为。我猜这是一个 SwiftUI 错误,但找不到任何以前的参考资料。

这是有效的解决方案。使用 Xcode 11.4 / iOS 13.4.

测试

如演示中所示,透明标签的存在不会影响地图视图的功能。

    var body: some View {
        VStack {
            ZStack {
                MapView()
                LabelView().opacity(show ? 1 : 0)   // here !!
            }.animation(.easeInOut(duration: 1.0))

            Button("Animate") {
                self.show.toggle()
            }.padding(20)
        }
    }

另一种实际上具有相同视觉效果的替代方法是将 LabelView 嵌入到容器中并对其应用过渡(必须留下一些东西来呈现视图消失)

var body: some View {
    VStack {
        ZStack {
            MapView()
            VStack {              // << here !!
                if show {
                    LabelView()
                }
            }.transition(.opacity).animation(.easeInOut(duration: 1.0))
        }
        Button("Animate") {
            self.show.toggle()
        }.padding(20)
    }
}

试试这个:-> 刚刚添加了 zIndex ...其他都一样

struct ContentView: View {
    @State private var show = false

    var body: some View {
        VStack {
            ZStack {
                MapView().zIndex(0)
                if show {
                    LabelView()
                    .zIndex(1)
                        .transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
                }
            }
            Button("Animate") {
                self.show.toggle()
            }.padding(20)
        }
    }
}

并阅读: