Azh*_*mil 15 swiftui ios14 xcode12
我正在使用新的 Xcode 12 beta 和 SwiftUi 2.0。.matchedGeometryEffect()修改器非常适合做英雄动画。@NamespaceSwiftUI 中引入了一个新属性。它超级酷。工作真棒。
我只是想知道是否有可能将命名空间变量传递给多个视图?
这是我正在研究的一个例子,
struct HomeView: View {
@Namespace var namespace
@State var isDisplay = true
var body: some View {
ZStack {
if isDisplay {
VStack {
Image("share sheet")
.resizable()
.frame(width: 150, height: 100)
.matchedGeometryEffect(id: "img", in: namespace)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.onTapGesture {
withAnimation {
self.isDisplay.toggle()
}
}
} else {
VStack {
Spacer()
Image("share sheet")
.resizable()
.frame(width: 300, height: 200)
.matchedGeometryEffect(id: "img", in: namespace)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.onTapGesture {
withAnimation {
self.isDisplay.toggle()
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常。
但是如果我想将其提取Vstack为子视图,则下图显示我已将第一个 VStack 提取到子视图中。
我得到了赞美 Cannot find 'namespace' in scope
有没有办法跨多个视图传递命名空间?
Asp*_*eri 24
The@Namespace是 的包装器Namespace.ID,您可以将Namespace.ID参数传递给子视图。
这是可能的解决方案的演示。使用 Xcode 12 / iOS 14 测试
struct HomeView: View {
@Namespace var namespace
@State var isDisplay = true
var body: some View {
ZStack {
if isDisplay {
View1(namespace: namespace, isDisplay: $isDisplay)
} else {
View2(namespace: namespace, isDisplay: $isDisplay)
}
}
}
}
struct View1: View {
let namespace: Namespace.ID
@Binding var isDisplay: Bool
var body: some View {
VStack {
Image("plant")
.resizable()
.frame(width: 150, height: 100)
.matchedGeometryEffect(id: "img", in: namespace)
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.onTapGesture {
withAnimation {
self.isDisplay.toggle()
}
}
}
}
struct View2: View {
let namespace: Namespace.ID
@Binding var isDisplay: Bool
var body: some View {
VStack {
Spacer()
Image("plant")
.resizable()
.frame(width: 300, height: 200)
.matchedGeometryEffect(id: "img", in: namespace)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.onTapGesture {
withAnimation {
self.isDisplay.toggle()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
mic*_*ben 11
Namespace将 注入的一种无警告方法Environment是创建一个ObservableObject名为 的,以在创建后NamespaceWrapper保存。Namespace这可能看起来像:
class NamespaceWrapper: ObservableObject {
var namespace: Namespace.ID
init(_ namespace: Namespace.ID) {
self.namespace = namespace
}
}
Run Code Online (Sandbox Code Playgroud)
然后您将创建并传递Namespace类似的内容:
struct ContentView: View {
@Namespace var someNamespace
var body: some View {
Foo()
.environmentObject(NamespaceWrapper(someNamespace))
}
}
struct Foo: View {
@EnvironmentObject var namespaceWrapper: NamespaceWrapper
var body: some View {
Text("Hey you guys!")
.matchedGeometryEffect(id: "textView", in: namespaceWrapper.namespace)
}
}
Run Code Online (Sandbox Code Playgroud)
虽然接受的答案有效,但在多个嵌套子视图之间共享名称空间会有点烦人,特别是如果您希望初始化器干净且切中要点。在这种情况下,使用环境值可能会更好:
struct NamespaceEnvironmentKey: EnvironmentKey {
static var defaultValue: Namespace.ID = Namespace().wrappedValue
}
extension EnvironmentValues {
var namespace: Namespace.ID {
get { self[NamespaceEnvironmentKey.self] }
set { self[NamespaceEnvironmentKey.self] = newValue }
}
}
extension View {
func namespace(_ value: Namespace.ID) -> some View {
environment(\.namespace, value)
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以在任何视图中创建命名空间并允许其所有后代使用它:
/// Main View
struct PlaygroundView: View {
@Namespace private var namespace
var body: some View {
ZStack {
SplashView()
...
}
.namespace(namespace)
}
}
/// Subview
struct SplashView: View {
@Environment(\.namespace) var namespace
var body: some View {
ZStack(alignment: .center) {
Image("logo", bundle: .module)
.matchedGeometryEffect(id: "logo", in: namespace)
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1955 次 |
| 最近记录: |