如何通过函数为TabView传入内容
How to pass in content for TabView through a function
我正在尝试构建一个可重复使用的入职寻呼机叠加层。所以我想根据变量 IntroType
将不同的“幻灯片”传递到寻呼机 TabView
中。但是,由于 TabView
无需任何容器即可直接获取内容,因此 return 类型是什么?
这就是我希望它的工作方式:
struct IntroViewTabPageTest: View {
// MARK: Variables
@Binding var isPresented: Bool
@State var activeSlide: Int = 0
var introType: IntroType
// MARK: UI
var body: some View {
ZStack(alignment: .bottom) {
Color.darkGalaxy
TabView(selection: $activeSlide) {
getContentBasedOnType() // <---- Content here
}
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
}
}
// MARK: Functions
private func getContentBasedOnType() -> some View {
switch (introType) {
case .Main:
return introContentMain
case .SA:
return introContentSA
case .Journey:
return introContentJourney
}
}
}
// Static content blocks for each type
extension IntroViewTabPageTest {
// ----> Of course everywhere errors here, "some View" is not the right return type;
// But what is it?
private var introContentMain: some View {
MainIntroSlide1()
TextSlide(headline: "Headline", text: "Text")
}
private var introContentSA: some View {
TextSlide(headline: "Headline", text: "Text")
TextSlide(headline: "Headline2", text: "Text2")
TextSlide(headline: "Headline3", text: "Text3")
}
private var introContentJourney: some View {
TextSlide(headline: "Headline", text: "Text")
}
}
enum IntroType: String {
case Main, SA, Journey
}
struct IntroViewTabPageTest_Previews: PreviewProvider {
static var previews: some View {
IntroViewTabPageTest(isPresented: .constant(true), introType: .Main)
}
}
另一种方法是将扩展 return 中的每个变量作为一个整体 TabView
,但这非常丑陋,我也没有完全弄明白,仍然会遇到一些其他错误那条路线。
我认为必须有 一些 方法来做到这一点,我只是还不太了解 SwiftUI 的可用工具。我可以想象一个带有 @ViewBuilder 包装器的函数可以在这里使用,但到目前为止我还没有完全理解它背后的逻辑。
我最接近的是使用一组 AnyView() 幻灯片的向下转换,但这使得使用 ForEach 变得困难并删除了类型。
你可以这样传递内容:
import SwiftUI
struct IntroViewTabPageTest<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
ZStack(alignment: .bottom) {
Color.gray
TabView() {
self.content
}
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
}
}
}
struct IntroViewTabPageTest_Previews: PreviewProvider {
static var previews: some View {
Group {
IntroViewTabPageTest {
Text("hello 1")
Text("hello 2")
}
IntroViewTabPageTest {
Rectangle()
.fill(Color.green)
.frame(width: 100, height: 100)
}
}
}
}
在@Chris 的帮助下,我使其工作如下:
import SwiftUI
struct IntroView: View {
@Binding var isPresented: Bool
var introType: IntroType
var body: some View {
if (introType == .Main) {
getContentMain()
}
else if (introType == .SA) {
getContentSA()
}
else if (introType == .Journey) {
getContentJourney()
}
}
}
fileprivate struct IntroTabView<Content: View>: View {
let content: Content
@Binding var isPresented: Bool
@State var activeSlide: Int = 0
let slideAmount: Int
init(isPresented: Binding<Bool>, slideAmount: Int, @ViewBuilder content: () -> Content) {
self._isPresented = isPresented
self.slideAmount = slideAmount
self.content = content()
}
var body: some View {
ZStack(alignment: .bottom) {
Color.darkGalaxy
TabView(selection: $activeSlide) {
self.content
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(.page(backgroundDisplayMode: .always))
// Buttons
HStack { ... }
.padding(16)
}
}
}
// Static content blocks for each type
fileprivate extension IntroView {
private func getContentMain() -> some View {
IntroTabView(isPresented: $isPresented, slideAmount: 3) {
MainIntroSlide1().tag(0)
TextSlide(headline: "Headline", text: "Text").tag(1)
TextSlide(headline: "Headline2", text: "Text2").tag(2)
}
}
private func getContentSA() -> some View {
IntroTabView(isPresented: $isPresented, slideAmount: 2) {
TextSlide(headline: "Headline", text: "Text").tag(0)
TextSlide(headline: "Headline2", text: "Text2").tag(1)
}
}
private func getContentJourney() -> some View {
IntroTabView(isPresented: $isPresented, slideAmount: 1) {
TextSlide(headline: "Headline", text: "Text").tag(0)
}
}
}
enum IntroType: String {
case Main, SA, Journey
}
struct IntroView_Previews: PreviewProvider {
static var previews: some View {
IntroView(isPresented: .constant(true), introType: .Main)
}
}
产生了这个美丽的景色:
我正在尝试构建一个可重复使用的入职寻呼机叠加层。所以我想根据变量 IntroType
将不同的“幻灯片”传递到寻呼机 TabView
中。但是,由于 TabView
无需任何容器即可直接获取内容,因此 return 类型是什么?
这就是我希望它的工作方式:
struct IntroViewTabPageTest: View {
// MARK: Variables
@Binding var isPresented: Bool
@State var activeSlide: Int = 0
var introType: IntroType
// MARK: UI
var body: some View {
ZStack(alignment: .bottom) {
Color.darkGalaxy
TabView(selection: $activeSlide) {
getContentBasedOnType() // <---- Content here
}
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
}
}
// MARK: Functions
private func getContentBasedOnType() -> some View {
switch (introType) {
case .Main:
return introContentMain
case .SA:
return introContentSA
case .Journey:
return introContentJourney
}
}
}
// Static content blocks for each type
extension IntroViewTabPageTest {
// ----> Of course everywhere errors here, "some View" is not the right return type;
// But what is it?
private var introContentMain: some View {
MainIntroSlide1()
TextSlide(headline: "Headline", text: "Text")
}
private var introContentSA: some View {
TextSlide(headline: "Headline", text: "Text")
TextSlide(headline: "Headline2", text: "Text2")
TextSlide(headline: "Headline3", text: "Text3")
}
private var introContentJourney: some View {
TextSlide(headline: "Headline", text: "Text")
}
}
enum IntroType: String {
case Main, SA, Journey
}
struct IntroViewTabPageTest_Previews: PreviewProvider {
static var previews: some View {
IntroViewTabPageTest(isPresented: .constant(true), introType: .Main)
}
}
另一种方法是将扩展 return 中的每个变量作为一个整体 TabView
,但这非常丑陋,我也没有完全弄明白,仍然会遇到一些其他错误那条路线。
我认为必须有 一些 方法来做到这一点,我只是还不太了解 SwiftUI 的可用工具。我可以想象一个带有 @ViewBuilder 包装器的函数可以在这里使用,但到目前为止我还没有完全理解它背后的逻辑。
我最接近的是使用一组 AnyView() 幻灯片的向下转换,但这使得使用 ForEach 变得困难并删除了类型。
你可以这样传递内容:
import SwiftUI
struct IntroViewTabPageTest<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
ZStack(alignment: .bottom) {
Color.gray
TabView() {
self.content
}
.tabViewStyle(.page)
.indexViewStyle(.page(backgroundDisplayMode: .always))
}
}
}
struct IntroViewTabPageTest_Previews: PreviewProvider {
static var previews: some View {
Group {
IntroViewTabPageTest {
Text("hello 1")
Text("hello 2")
}
IntroViewTabPageTest {
Rectangle()
.fill(Color.green)
.frame(width: 100, height: 100)
}
}
}
}
在@Chris 的帮助下,我使其工作如下:
import SwiftUI
struct IntroView: View {
@Binding var isPresented: Bool
var introType: IntroType
var body: some View {
if (introType == .Main) {
getContentMain()
}
else if (introType == .SA) {
getContentSA()
}
else if (introType == .Journey) {
getContentJourney()
}
}
}
fileprivate struct IntroTabView<Content: View>: View {
let content: Content
@Binding var isPresented: Bool
@State var activeSlide: Int = 0
let slideAmount: Int
init(isPresented: Binding<Bool>, slideAmount: Int, @ViewBuilder content: () -> Content) {
self._isPresented = isPresented
self.slideAmount = slideAmount
self.content = content()
}
var body: some View {
ZStack(alignment: .bottom) {
Color.darkGalaxy
TabView(selection: $activeSlide) {
self.content
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(.page(backgroundDisplayMode: .always))
// Buttons
HStack { ... }
.padding(16)
}
}
}
// Static content blocks for each type
fileprivate extension IntroView {
private func getContentMain() -> some View {
IntroTabView(isPresented: $isPresented, slideAmount: 3) {
MainIntroSlide1().tag(0)
TextSlide(headline: "Headline", text: "Text").tag(1)
TextSlide(headline: "Headline2", text: "Text2").tag(2)
}
}
private func getContentSA() -> some View {
IntroTabView(isPresented: $isPresented, slideAmount: 2) {
TextSlide(headline: "Headline", text: "Text").tag(0)
TextSlide(headline: "Headline2", text: "Text2").tag(1)
}
}
private func getContentJourney() -> some View {
IntroTabView(isPresented: $isPresented, slideAmount: 1) {
TextSlide(headline: "Headline", text: "Text").tag(0)
}
}
}
enum IntroType: String {
case Main, SA, Journey
}
struct IntroView_Previews: PreviewProvider {
static var previews: some View {
IntroView(isPresented: .constant(true), introType: .Main)
}
}
产生了这个美丽的景色: