【问题标题】:SwiftUI - animating View opacity in ZStack with .easeInOutSwiftUI - 使用 .easeInOut 为 ZStack 中的视图不透明度设置动画
【发布时间】:2020-08-16 22:52:22
【问题描述】:

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

如果我删除 mapView,那么一切都很好。如果我用简单的Rectangle() 替换 mapView,那么问题就会再次出现,所以我相信它与 ZStack 而不是地图有关。有趣的是,我实际上使用的是 Mapbox 而不是 MapKit(为简单起见,如下代码所示)并且淡入淡出/突然消失的行为是相反的。

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 错误,但找不到任何以前的参考。

【问题讨论】:

    标签: animation swiftui opacity zstack easeinout


    【解决方案1】:

    这是可行的解决方案。使用 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)
        }
    }
    

    【讨论】:

      【解决方案2】:

      试试这个:-> 刚刚添加了 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)
              }
          }
      }
      

      并阅读:

      Transition animation not working in SwiftUI

      【讨论】:

        猜你喜欢
        • 2021-04-20
        • 2011-01-11
        • 1970-01-01
        • 2019-12-24
        • 1970-01-01
        • 2011-10-09
        • 2012-05-31
        • 2010-11-28
        • 1970-01-01
        相关资源
        最近更新 更多