我想做一个视图,通过一个viewBuilder接收异构的内容,像正常一样,然后有选择地只显示一个这样提供的子视图,隐藏其余的。
类似于TabView的功能**,但在我的编程控制下,没有实际的标签栏,强制背景和全屏抓取。它应该能够接受任何类型的混合内容项,如ForEach
输出,Group
元素等。就像TabView一样,或VStack或HStack或List或任何接受许多孩子并以不同方式对待每个孩子的Apple视图。
我拥有的:
但是我只希望这三个子视图中的一个可见(我的选择)。
下面是我想使工作的代码,目标应该是明确的...
import SwiftUI
struct SwitcherView<Content>: View where Content: View {
let content: () -> Content
// NOT this, yuck:
// let content: [AnyView]
@State var selection: Int = 0 // will be changed by logic not shown
public init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
@MainActor public var body: some View {
VStack {
//// bad approaches:
//// obviously this doesn't work, I wish...
// (Group { content() })[selection]
//// This would work, if Layouts could hide
//// subviews (they can't)
// MyPickOneLayout(selection) { content() }
//// With the [AnyView] above, this "works" but
//// is slow, and awful to use as a client
// content[selection]
//// Would work, if modifyEach existed, and would
//// connect back to this view via Preferences
//// or Environment:
// content().modifyEach( MyHideShowModifier() )
//// Requiring the client to wrap each view in
//// MyHideShowModifier itself might work but is
//// intrusive to the client
//// not what I want:
content()
}
}
}
struct SwitcherView_Previews: PreviewProvider {
static var previews: some View {
VStack {
Text("I would like to show just one of these at a time:")
SwitcherView {
// Note heterogeneous content: each element
// has its own type and state, none of which
// SwitcherView gets to know about explicitly..
// just like TabView!
Text("First Content")
.frame(width: 100, height: 100)
.background(.red)
Button(action: {}, label: {
Text("I'm a yellow button!")
})
.buttonStyle(.borderedProminent)
.tint(.green)
.frame(width: 100, height: 100)
HStack {
Text("Some thing").background(.yellow)
Text("Else").background(.blue)
}
.frame(width: 100, height:100)
.background(.brown)
}
}
}
}
TabView做到了,所以这显然是可能的!(对于苹果来说。
如上文评论所述,迄今为止尝试的方法:
- 在自定义
Layout
中私下 Package 内容:*Layout
s不能隐藏子视图,它们必须定位并显示所有子视图
- 在自定义
- 以数组的形式接收内容:* 非常不受SwiftUI的欢迎,并强制使用
AnyView
,这是性能毒药
- 以数组的形式接收内容:* 非常不受SwiftUI的欢迎,并强制使用
- 使用特殊的
ViewModifier
Package 每个子视图,然后使用首选项或环境系统连接回SwitcherView以进行显示/隐藏逻辑:* 强制所有内容的最外层ViewModifier
成为此修饰符,并显示缺少它的所有内容。
- 使用特殊的
- 显式列出我的子视图,并将显示/隐藏逻辑附加到每个子视图:* 封装不好,视图很大。(但这是我的真实的应用程序现在正在做的事情,我想改进)
我是不是找错人了?我该去哪找?
1条答案
按热度按时间nwnhqdif1#
如果你想有选择地隐藏一个子视图,一种方法是使用一个父视图,它包含一个数组和当前选择。有了这个信息,你就可以从数组中选择要显示的子视图。
为了演示这一点,我创建了一个Model结构体,其中包含一个
word
和一个color
。父视图有一个
model
和selection state variable
的数组,表示当前选定数组的索引。SwitcherView
是一个通用视图,它接受一个选择绑定和一个闭包,该闭包返回要显示的内容。在本例中,内容是一个带有所选单词的彩色正方形。总的来说,这种方法允许我们通过改变选择状态变量来选择性地显示子视图。
此代码中需要改进的一个方面是用于表示数组大小的硬编码值4。如果数组的大小发生更改,则可能导致内存泄漏。
要解决这个问题,建议使用数组的实际大小而不是硬编码的值。这可以通过将数组的count属性传递给子视图或使用一个常量来实现,该常量在数组更改大小时更新。
通过这样做,子视图将始终具有正确的大小,并且您不必担心每次数组更改时手动更新值。