【发布时间】:2022-01-21 20:31:05
【问题描述】:
我之前问过一个关于如何在此处将一组 TabButtons 链接到 .tag() 的问题:.tag() in TabView in SwiftUI challenge,但现在我想自定义每个 TabView 以具有不同的信息,而不仅仅是从中读取的一行文本创建的枚举案例。在下面的代码中,我添加了我想用每个 TabView 填充的其他视图。我希望将来能够插入其他选项卡/视图。我在底部创建了自定义视图,但不确定如何与枚举链接,然后在 TabView 中使用 ForEach。
import SwiftUI
struct ContentView: View {
var body: some View {
CustomTabView()
}
}
struct CustomTabView: View {
@State var selectedTab = ViewSelect.HomeView // This is an enum defined below.
@State var viewData : AllViewData!
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)) {
TabView(selection: $selectedTab) {
ForEach(ViewSelect.allCases, id: \.self) { view in // This iterates through all of the enum cases.
ViewsCardView(viewData: view.allViewData)
.tag(view.rawValue) // by having the tag be the enum's raw value,
// you can always compare enum to enum.
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.ignoresSafeArea(.all, edges: .bottom)
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(ViewSelect.allCases ,id: \.self){viewSelect in
TabButton(viewSelect: viewSelect, selectedTab: $selectedTab)
}
}
})
.padding(.horizontal, 25)
.padding(.vertical, 5)
.background(Color.white)
.clipShape(Capsule())
.shadow(color: Color.black.opacity(0.15), radius: 5, x: 5, y: 5)
.shadow(color: Color.black.opacity(0.15), radius: 5, x: -5, y: -5)
.padding(.horizontal)
}
.background(Color.black.opacity(0.05).ignoresSafeArea(.all, edges: .all))
}
}
struct TabButton: View {
let viewSelect: ViewSelect
@Binding var selectedTab: ViewSelect
var body: some View {
Button(action: {selectedTab = viewSelect}) {
Image(systemName: viewSelect.tabIcon)
.renderingMode(.template)
// this compares the selection to the button's associated enum.
// The enum provides the image name to the button,
// but we are always dealing with a case of the enum.
.opacity(selectedTab == viewSelect ? (1) : (0.5))
.padding()
}
}
}
struct ViewsCardView: View {
@State var viewData: AllViewData
var body: some View {
VStack {
Text(viewData.name)
}
}
}
struct AllViewData : Identifiable, Hashable {
var id = UUID().uuidString
var name : String
var text : Int
}
public enum ViewSelect: String, CaseIterable {
case HomeView, EnvelopeView, FolderView, SettingsView
var tabIcon: String {
switch self {
case .HomeView:
return "house"
case .EnvelopeView:
return "envelope"
case .FolderView:
return "folder"
case .SettingsView:
return "gear"
}
}
var allViewData: AllViewData {
return AllViewData(name: self.rawValue, text: self.hashValue)
}
}
struct DataForViews : Identifiable {
var id = UUID().uuidString
var someText : SomeText
var someImage : SomeImage
var someData : String
var moreText : String
enum SomeText : String, CaseIterable {
case friends
case enemies
case neutral
case both
}
enum SomeImage : String, CaseIterable {
case friends = "person.3"
case enemies = "person.fill.xmark"
case neutral = "person"
case both = "person.circle"
}
}
struct HomeView: View {
@State var viewData = DataForViews(someText: .friends, someImage: .friends, someData: "Some Data", moreText: "More Text")
var body: some View {
VStack {
Text(viewData.someText.rawValue)
Image(systemName: viewData.someImage.rawValue)
.resizable()
.frame(width: 40, height: 40)
Text(viewData.someData)
Text(viewData.moreText)
}
}
}
struct EnvelopeView: View {
@State var viewData = DataForViews(someText: .enemies, someImage: .enemies, someData: "Some Data", moreText: "More Text")
var body: some View {
VStack {
Text(viewData.someText.rawValue)
Image(systemName: viewData.someImage.rawValue)
.resizable()
.frame(width: 40, height: 40)
Text(viewData.moreText)
}
}
}
struct FolderView: View {
@State var viewData = DataForViews(someText: .neutral, someImage: .neutral, someData: "Some Data", moreText: "More Text")
var body: some View {
VStack {
Text(viewData.someText.rawValue)
Image(systemName: viewData.someImage.rawValue)
.resizable()
.frame(width: 40, height: 40)
Text(viewData.someData)
Text(viewData.moreText)
}
}
}
struct SettingsView: View {
@State var viewData = DataForViews(someText: .both, someImage: .both, someData: "Some Data", moreText: "More Text")
var body: some View {
VStack {
Text(viewData.someText.rawValue)
Image(systemName: viewData.someImage.rawValue)
.resizable()
.frame(width: 40, height: 40)
Text(viewData.someData)
}
}
}
【问题讨论】:
-
问题不清楚 - 是什么阻止了你这样做?
-
我其实不知道该怎么做。我不知道如何在 TabView() ForEach 循环中实现 HomeView()、EnvelopeView()、FolderView() 和 SettingsView(),或者是否有不同的方法来解决这个问题?我知道你可以通过 TabView() 来实现,然后调用视图,然后是 tabItem,最后是 .tag()。但是,如果我要插入新视图以及重构 .tag() 的选项卡,就会变得很麻烦。 @Asperi
标签: swiftui enums swiftui-tabview