SwiftUI中如何自定义嵌套Menu菜单项及按钮的外观?
解决方案
问题原因
SwiftUI 内置 Menu 展开后的子项默认遵循系统菜单样式规范,你直接给内部 label 添加的 background 修饰符会被系统预设的列表单元格样式覆盖,因此无法正常渲染。
适配代码(iOS 15+)
import SwiftUI struct ContentView: View { var body: some View { DropDownMenu() } } struct DropDownMenu: View { private let categories: [Category] @State private var selectedSubcategory = "Select a category" let letters = ["a", "b", "c"] init() { self.categories = [Category(name: "letters", subcategories: letters)] } var body: some View { Menu { Menu { Button { selectedSubcategory = categories[0].subcategories[0] } label: { Text(categories[0].subcategories[0]) .foregroundColor(.white) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) } .listRowBackground(Color.blue) Button { selectedSubcategory = categories[0].subcategories[1] } label: { Text(categories[0].subcategories[1]) .foregroundColor(.white) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) } .listRowBackground(Color.blue) Button { selectedSubcategory = categories[0].subcategories[2] } label: { Text(categories[0].subcategories[2]) .foregroundColor(.white) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) } .listRowBackground(Color.blue) } label: { Text(categories[0].name) .foregroundColor(.white) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) } .listRowBackground(Color.blue) } label: { Text(selectedSubcategory) .foregroundColor(.black) .background(Color.blue) } } } struct Category: Hashable { var id = UUID() var name: String var subcategories: [String] }
核心修改说明
listRowBackground(Color.blue):Menu 展开后的子项本质是列表单元格,该修饰符直接设置单元格的背景色,不会被系统样式覆盖frame(maxWidth: .infinity, alignment: .leading):让文本内容撑满整个单元格宽度,避免背景仅显示在窄小的文本区域contentShape(Rectangle()):扩大点击响应区域,保证点击单元格任意位置都能触发对应操作
如果需要适配 iOS 15 以下的系统版本,可以自定义弹出视图替代系统内置 Menu 组件实现同等效果。
效果演示:
内容的提问来源于stack exchange,提问作者cbusch
相关产品推荐
相关产品推荐

