watchOS 和 SwiftUI 中的菜鳥。我創建了一個帶有多個按鈕的網格視圖。每當單擊按鈕時,我希望打開一個帶有導航鏈接的新視圖。由于視圖上有多個按鈕,我創建了一個可重用的視圖并且很難實作導航到下一個視圖。下面是我的代碼:
內容視圖:
struct ContentView: View {
@Namespace var namespace
@State var selected: [MenuItem] = []
var body: some View {
MainMenuCircularGridView()
}
}
MainMenuCircularGridView:
struct MainMenuCircularGridView: View {
let columns = Array(repeating: GridItem(.fixed(72.0), spacing: 10), count: 2)
var body: some View {
NavigationView {
ScrollView {
let menuOptions = MenuOptions()
let menuOptionsAction = MenuActions()
LazyVGrid(columns: columns, spacing: 5) {
ForEach(menuOptions.menu) { item in
MenuItemCircularGridView(imageName: item.imageName, menuItemName: item.name, action: (menuOptionsAction.menuActions.first {$0.id == item.id})?.action ?? {})
}
}.padding()
}.navigationTitle("Sample App")
}
}
}
選單項圓形網格視圖:
struct MenuItemCircularGridView: View {
var imageName: String = ""
var menuItemName: String = ""
var action: () -> Void
var body: some View {
VStack {
CircularButtonWithImage(imageName:imageName,
imageBackgroundColor:Color(red: 34 / 255, green: 34 / 255, blue: 34 / 255),
imageForegroundColor: Color(red: 23 / 255, green: 121 / 255, blue: 232 / 255),
imageFrameWidth: 30.0,
imageFrameHeight: 30.0,
imagePadding: 10.0,
action: action)
Text(menuItemName).font(.system(size: 10))
}.padding(10)
}
}
CircularButtonWithImage:
struct CircularButtonWithImage: View {
var imageName: String = ""
var imageBackgroundColor: Color?
var imageForegroundColor: Color?
var imageFrameWidth: CGFloat = 0.0
var imageFrameHeight: CGFloat = 0.0
var imagePadding: CGFloat = 0.0
var action: () -> Void
var body: some View {
Button(action: { action() }) {
VStack{
Image(imageName)
.renderingMode(.template)
.resizable()
.scaledToFill()
.frame(width: imageFrameWidth, height: imageFrameHeight)
.padding(imagePadding)
.background(imageBackgroundColor)
.foregroundColor(imageForegroundColor)
.clipShape(Circle())
}
}
.buttonStyle(PlainButtonStyle())
}
}
這是我的應用程式的外觀:

每當我點擊這些按鈕中的任何一個時,我都想打開一個帶有導航鏈接的新視圖。如下所示:
NavigationLink(destination: DetailView()) {
Text("Show Detail View")
}.navigationBarTitle("Navigation")
由于我已將視圖分解為多個可重用檔案,因此我不確定我應該將這個邏輯放在哪里以在按鈕單擊時打開一個新視圖。
編輯:添加我正在使用的硬編碼資料。我試圖將導航鏈接作為操作傳遞給按鈕。
struct MenuOptions {
let menu: [MenuItem] = [
MenuItem(id: 0, name: "Option 1", imageName: "settings-gray"),
MenuItem(id: 1, name: "Option 2", imageName: "settings-gray"),
MenuItem(id: 2, name: "Option 3", imageName: "settings-gray"),
MenuItem(id: 3, name: "Set 1", imageName: "settings-gray"),
MenuItem(id: 4, name: "Set 2", imageName: "settings-gray"),
MenuItem(id: 5, name: "Settings", imageName: "settings-gray")
]
}
struct MenuActions {
let menuActions: [MenuItemAction] = [
MenuItemAction(id: 1, action: { NavigationLink("New View 1", destination: View1()) }),
MenuItemAction(id: 5, action: { NavigationLink("Settings", destination: SettingsView()) })
]
}
uj5u.com熱心網友回復:
ANavigationLink必須在視圖層次結構中,因此我們需要在其中放置一些模型,而不是將其付諸實施。
可能的方法的草圖
- 目的地模型
enum MenuDestination: String, CaseIterable, Hashable {
case set1(MenuItem), set2
@ViewBuilder var view: some View {
switch self {
case .set1(let item): View1(item: item)
case .set2: SettingsView()
}
}
}
- 視圖中的導航鏈接
@State private var selection: MenuDestination?
var isActive: Binding<Bool> {
Binding(get: { selection != nil }, set: { selection = nil } )
}
var body: some View {
NavigationView {
ScrollView {
// ...
}
.background(
if let selection = selection {
NavigationLink(isActive: isActive, destination: { selection.view }) {
EmptyView()
}})
}
}
- 按鈕操作分配相應的值,例如
MenuItemAction作為引數系結到選擇并在內部將目標分配給該系結
MenuItemCircularGridView(imageName: item.imageName, menuItemName: item.name,
action: (menuOptionsAction.menuActions.first {$0.id == item.id})?.action($selection) ?? { _ in })
并MenuItemAction以相應的情況開始MenuDestination
另見這篇文章
uj5u.com熱心網友回復:
感謝@Asperi 幫助我!
我意識到我將視圖分解為不同的檔案可能會使事情變得更加復雜。由于我只有 6 個按鈕,因此我決定將視圖保存在一個檔案中,并使用您創建 MenuDestination 的想法來傳遞正確的視圖。在下面分享我的更新代碼。
然而,我想使用 NavigationLink 的主要原因是在目標視圖上獲取后退按鈕按鈕和導航標題名稱以回傳主選單。我沒有在目標視圖的左上方看到帶有導航標題的后退按鈕。如果您知道我可能會丟失什么,請告訴我。我的理解是使用 NavigationLink 自動將其添加到目標視圖。
更新代碼 - MainMenuCircularGridViewNew:
import SwiftUI
struct MainMenuCircularGridViewNew: View {
let columns = Array(repeating: GridItem(.fixed(72.0), spacing: 10), count: 2)
@State private var destination: MenuDestination?
var isActive: Binding<Bool> { Binding(get: { destination != nil }, set: { _ in destination = nil } ) }
var body: some View {
NavigationView {
ScrollView {
let menuOptions = MenuOptions()
LazyVGrid(columns: columns, spacing: 5) {
ForEach(menuOptions.menu) { item in
VStack {
Button(action: { self.destination = MenuDestination(rawValue: item.id) }) {
VStack{
Image(item.imageName)
.circularImageStyle(width: 30, height: 30, padding: 10,
backgroundColor: Color(red: 34 / 255, green: 34 / 255, blue: 34 / 255),
foregroundColor: Color(red: 23 / 255, green: 121 / 255, blue: 232 / 255))
}
}
.buttonStyle(PlainButtonStyle())
Text(item.name).font(.system(size: 10))
}.padding(10)
}
}
}.background(
NavigationLink("", isActive: isActive, destination: { destination?.view }).buttonStyle(PlainButtonStyle()).navigationViewStyle(.stack)
)
}.navigationTitle("Sample Application")
}
}
選單目的地:
enum MenuDestination: Int, CaseIterable, Hashable {
case option1 = 0, option2 = 1, option3 = 2, option4 = 3, option5 = 4, settings = 5
@ViewBuilder var view: some View {
switch self {
case .option1: EmptyView()
case .option2: MyCustomView()
case .option3: EmptyView()
case .option4: EmptyView()
case .option5: EmptyView()
case .settings: SettingsView()
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/494330.html
