- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最近发现了 SwiftUI 的 OutlineGroup
在 iOS 14 中(我使用的是 Xcode 12 beta 6)。这非常有效,无论是单独使用还是在使用 List
时,都可以计算“根据树结构的、已识别数据的基础集合按需查看和披露组。”
即如果您有递归定义的 struct
,这对于构建 DisclosureGroup
元素非常有效。但是,我正在寻找可以让我构建“下拉”(或汉堡包)菜单的稍微不同的东西。
还有另一个控件叫做 Menu
,在 iOS 14 中,它完全按照我的意愿呈现“下拉”(或汉堡包)菜单:
但是我似乎无法同时使用两者来构建基于 data represented recursively 的动态 Menu
,例如:
struct Tree<Value: Hashable>: Hashable {
let value: Value
var children: [Tree]? = nil
}
菜单按以下方式构建:
struct SideMenu: View {
var body: some View {
Menu {
Button(action: {}) {
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Profile")
.foregroundColor(.gray)
.font(.headline)
}
Button(action: {}) {
Image(systemName: "person.3")
.foregroundColor(.gray)
.imageScale(.large)
Text("Family Members")
.foregroundColor(.gray)
.font(.headline)
}
Button(action: {}) {
Image(systemName: "calendar")
.foregroundColor(.gray)
.imageScale(.large)
Text("Events")
.foregroundColor(.gray)
.font(.headline)
}
} label: {
Image(systemName: "line.horizontal.3")
}
}
}
有没有一种方法可以从递归数据构建Menu
,类似于OutlineGroup
?
最佳答案
我喜欢用枚举来表示树,以避免出现不可能或不一致的状态。此外,您需要一个递归的 UI 函数调用,但是使用方法会使编译器对我来说失败(Xcode 12 beta 6),所以我将菜单部分分开在不同的 View 中,这似乎可行。现在您有一个完全动态的菜单,可以从您的 ViewModel 构建。
import SwiftUI
enum ViewEvent {
case profileTapped
case familyMembersTapped
case eventsTapped
case foldersTapped
case deletedItemsTapped
}
struct MenuItem: Identifiable {
var id: String { return text }
let text: String
let systemImage: String?
let action: ViewEvent?
}
enum MenuContent: Identifiable {
var id: String {
switch self {
case let .item(item): return item.id
case let .submenu(text, _): return text
}
}
case item(MenuItem)
indirect case submenu(text: String, content: [MenuContent])
}
struct ViewState {
let menu: [MenuContent]
let content: String
static var `default`: ViewState {
.init(
menu: [
.item(MenuItem(text: "Profile", systemImage: "person", action: .profileTapped)),
.item(MenuItem(text: "Family Members", systemImage: "person.3", action: .familyMembersTapped)),
.item(MenuItem(text: "Events", systemImage: "calendar", action: .familyMembersTapped)),
.submenu(text: "More", content: [
.item(MenuItem(text: "Folders", systemImage: "folder.fill", action: .foldersTapped)),
.item(MenuItem(text: "Deleted", systemImage: "trash.fill", action: .deletedItemsTapped))
])
],
content: "Content")
}
}
struct ContentView: View {
@State var viewState: ViewState
var body: some View {
HStack(alignment: .top, spacing: 16) {
AppMenu(contents: viewState.menu) {
Image(systemName: "line.horizontal.3")
}
Text("Content")
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.padding()
}
}
struct AppMenuItem: View {
let item: MenuItem
func dispatch(_ action: ViewEvent) {
// todo: call viewModel.dispatch
print("Sending action \(action)")
}
init(item: MenuItem) {
self.item = item
}
var body: some View {
Button(action: {
item.action.map { action in dispatch(action) }
}) {
item.systemImage.map { systemImage in
Image(systemName: systemImage)
.foregroundColor(.gray)
.imageScale(.large)
}
Text(item.text)
.foregroundColor(.gray)
.font(.headline)
}
}
}
struct AppSubmenu: View {
let text: String
let contents: [MenuContent]
var body: some View {
AppMenu(contents: contents) {
HStack {
Text(text)
Image(systemName: "chevron.right")
}
}
}
}
struct AppMenu<Label: View>: View {
let label: () -> Label
let contents: [MenuContent]
init(contents: [MenuContent], @ViewBuilder label: @escaping () -> Label) {
self.contents = contents
self.label = label
}
var body: some View {
Menu {
ForEach(contents) { content in
// In case this is an item
if case let .item(item) = content {
AppMenuItem(item: item)
}
// In case this is a submenu
if case let .submenu(text, contents) = content {
AppSubmenu(text: text, contents: contents)
}
}
} label: { label() }
}
}
关于swift - 在 SwiftUI 中递归构建菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63802388/
有没有办法在 .swift 文件(编译成 .swift 模块)中声明函数,如下所示: 你好.swift func hello_world() { println("hello world")
我正在尝试使用 xmpp_messenger_ios 和 XMPPFramework 在 iOS 上执行 MUC 这是加入房间的代码。 func createOrJoinRoomOnXMPP()
我想在我的应用程序上创建一个 3D Touch 快捷方式,我已经完成了有关快捷方式本身的所有操作,它显示正确,带有文本和图标。 当我运行这个快捷方式时,我的应用程序崩溃了,因为 AppDelegate
我的代码如下: let assetTag = Expression("asset_tag") let query2 = mdm.select(mdm[assetTag],os, mac, lastRe
我的 swift 代码如下所示 Family.arrayTuple:[(String,String)]? = [] Family.arrayTupleStorage:String? Family.ar
这是我的 JSON,当我读取 ord 和 uniq 数据时出现错误 let response2 : [String: Any] = ["Response":["status":"SUCCESS","
我想将 swift 扩展文件移动到 swift 包中。但是,将文件移动到 swift 包后,我遇到了这种错误: "Type 'NSAttributedString' has no member 'ma
使用CocoaPods,我们可以设置以下配置: pod 'SourceModel', :configurations => ['Debug'] 有什么方法可以用 Swift Package Manag
我正在 Xcode 中开发一个 swift 项目。我将其称为主要项目。我大部分都在工作。我在日期选择器、日期范围和日期数学方面遇到了麻烦,因此我开始了另一个名为 StarEndDate 的项目,其中只
这是 ObjectiveC 代码: CCSprite *progress = [CCSprite spriteWithImageNamed:@"progress.png"]; mProgressBar
我正在创建一个命令行工具,在 Xcode 中使用 Swift。我想使用一个类似于 grunt 的配置文件确实如此,但我希望它是像 Swift 包管理器的 package.swift 文件那样的快速代码
我假设这意味着使用系统上安装的任何 swift 运行脚本:#!/usr/bin/swift 如何指定脚本适用的解释器版本? 最佳答案 Cato可用于此: #!/usr/bin/env cato 1.2
代码说完全没问题,没有错误,但是当我去运行模拟器的时候,会出现这样的字样: (Swift.LazyMapCollection (_base:[ ] 我正在尝试创建一个显示报价的报价应用。 这是导入
是否可以在运行 Swift(例如 Perfect、Vapor、Kitura 等)的服务器上使用 RealmSwift 并使用它来存储数据? (我正在考虑尝试将其作为另一种解决方案的替代方案,例如 no
我刚开始学习编程,正在尝试完成 Swift 编程书中的实验。 它要求““编写一个函数,通过比较两个 Rank 值的原始值来比较它们。” enum Rank: Int { case Ace = 1 ca
在您将此问题标记为重复之前,我检查了 this question 它对我不起作用。 如何修复这个错误: error: SWIFT_VERSION '5.0' is unsupported, suppo
从 Xcode 9.3 开始,我在我的模型中使用“Swift.ImplicitlyUnwrappedOptional.some”包裹了我的字符串变量 我不知道这是怎么发生的,但它毁了我的应用程序! 我
这个问题在这里已经有了答案: How to include .swift file from other .swift file in an immediate mode? (2 个答案) 关闭 6
我正在使用 Swift Package Manager 创建一个应用程序,我需要知道构建项目的配置,即 Debug 或 Release。我试图避免使用 .xcodeproj 文件。请有人让我知道这是否
有一个带有函数定义的文件bar.swift: func bar() { println("bar") } 以及一个以立即模式运行的脚本foo.swift: #!/usr/bin/xcrun s
我是一名优秀的程序员,十分优秀!