SwiftUI 菜单按钮中的子标签。

13
我尝试使用SwiftUI创建一个菜单,其中包含主要和次要标签的按钮,就像下面的照片一样,所以我将按钮和文本(作为次要标签)嵌入到VStack中,但它不起作用。我该如何在SwiftUI中创建这个视图?

enter image description here

代码

 Menu {
        Section {
            search
        }
        Section {
// The sort button
        Menu  {
            Picker("Sorting options", selection: $sort) {
                ForEach(SortType.allCases, id: \.self) { type in
                    Label("title", systemImage: "chevron.up")
                        .tag(type)
                }
            }
        } label: {
// Here I should embed title and subtitle like the photo but I don't know how.
            Label("Sort By", systemImage: "arrow.up.arrow.down")
        }
        }
    } label: {
        menuLabel
    }

1
你应该使用这个社区来提出能够帮助你解决问题的问题,而不是分享你的计划。如果那确实是一个问题,请在你尝试过之后提供你尝试了什么以及为什么没有成功的细节在这里 - HunterLion
1
对于之前的误解,我很抱歉。我已经编辑了问题,以更清晰地表达我的疑问。 - Ammar Ahmad
你能展示一下你的代码吗?这样我们才能帮助你。我们无法猜测你到目前为止做了什么。 - Ptit Xav
展示你的尝试,让大家评论/修改以提供帮助。当然,你也需要一些主动性。 - Ron
2
据我所知,在纯SwiftUI中这是不可能的。菜单只接受一个Text和一个Image的标签。 - ChrisR
显示剩余2条评论
3个回答

6

新答案

如果您正在尝试获得类似于以下内容的行为,请使用 Buttoncontent 闭包。

enter image description here

Menu("HI") {
    Button(action: {}) {
        Text(temperatureType.localizedDescription)
        Text(formatTemperature(sensor.temperature, to: 
    temperatureType.toUnitTemperature()))
    }
}

在这里,我正在模仿iOS 16的UITextView提供的新数据检测功能。然后,您可以添加任何想要的修饰符。


旧答案

我找到了一种部分方法来实现这个,但是它没有副标题文本小一些,并且在 foregroundStyle(.secondary) 中:

enter image description here

Picker(selection: $pointsSortType) {
    Button(PointsSortType.date            .displayName) {}.tag(PointsSortType.date            .rawValue)
    Button(PointsSortType.type            .displayName) {}.tag(PointsSortType.type            .rawValue)
    Button(PointsSortType.submissionStatus.displayName) {}.tag(PointsSortType.submissionStatus.rawValue)
    Button(PointsSortType.duration        .displayName) {}.tag(PointsSortType.duration        .rawValue)
} label: {
    Label {
        Text("""
             Sort By
             Manual
             """)
    } icon: {
        Image(systemName: "arrow.up.arrow.down")
    }
}
.pickerStyle(.menu)

在这里,我们使用多行字符串来欺骗它。我尝试通过在一堆Stack中添加多个Text,甚至尝试使用AnyView(erasing:)进行类型抹消,但不知何故它仍然更聪明。我甚至尝试插值Text视图,并添加诸如Bold之类的Text修饰符,但它也覆盖了它。

对不起,间隔有点大,但这是我喜欢格式化我的代码的方式。


我知道这不是最好的解决方案,但在此期间可以使用它。另一种显示字幕数据的方法是使用一个项目符号 Text("Sort By • Manual")https://i.stack.imgur.com/aRGNz.png - Awesomeplayer165
显然,一个简单的换行符也可以使用“\n”。 - JHSnows
这是一个很好的发现。而且,菜单竟然“接受”了第二段文字,并自动将其样式化为描述风格,这完全出乎意料。 不过,添加第三段文字是行不通的。请记住,系统将描述限制在两行文字,多余的部分将被裁剪。 - undefined
它在 macOS 上也能运行吗?那将会很棒。 - undefined

2
您可以通过使用UIKit自iOS 15.0版本以来实现此功能。
var menu = UIMenu()

if #available(iOS 15.0, *) {
   menu = UIMenu(title: "Sort By",
                 subtitle: "Name",
                 children: provideJobSortOptions())
} else {
   menu = UIMenu(title: "Sort By"), children: provideJobSortOptions())
}

4
请纠正我,但这是指 UIMenu,它是 UIKit 的一部分,而不是 OP 特别提到的 SwiftUI。您能否扩展您的示例,以显示在 SwiftUI Menu 中使用 UIMenu?谢谢! - Mark A. Donohoe

0

一个有点糟糕的解决方案是扩展UIMenu并重写其subtitle属性。您可以创建一个菜单观察者类,允许修改该属性的值。

类似于这样:

extension UIMenu {
  
  open override var subtitle: String? {
    get { MenuObserver.shared.menuSubtitle }
    set { }
  }
}

class MenuObserver {
  
  static var shared = MenuObserver()
  
  var menuSubtitle: String? = nil
}

然后,您可以通过更改观察者的属性,在代码中的任何位置更新菜单副标题。
MenuObserver.shared.menuSubtitle = "someString"

这个解决方案不适用于包含多个嵌套菜单的情况,因为相同的副标题会显示在每个菜单中。

附注:这个解决方案适用于SwiftUI,因为SwiftUI的菜单实际上是底层的UIMenu。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接