如何为SwiftUI Picker的选项及选中项设置自定义字体?
SwiftUI Picker 自定义字体不生效的解决方法
问题描述
App已正确配置自定义字体,但SwiftUI Picker的选中项文本和下拉选项均无法应用自定义字体或设置的fontWeight(.black)。示例代码中尝试给Picker内的Text设置样式,实际显示仍为系统字体。
示例代码
enum PickerChoice: CaseIterable, Identifiable, Hashable { var id: Self { self } case choiceA case choiceB case iDontWantToChoose var label: String { switch self { case .choiceA: "Choice A" case .choiceB: "Choice B" case .iDontWantToChoose: "I don't want to choose" } } } struct ContentView: View { @State var pickerChoice: PickerChoice = .choiceA var body: some View { HStack(spacing: 0) { Text("Picker: ") .fontWeight(.black) Picker(selection: $pickerChoice) { ForEach(PickerChoice.allCases) { Text($0.label) .fontWeight(.black) .tag($0.id) } } label: { Text("Picking...") } } .frame(maxWidth: .infinity, alignment: .leading) .padding() } } #Preview { ContentView() }
当前问题效果
Picker的选中文本和下拉选项均使用系统字体,未应用设置的加粗样式或自定义字体。
解决方案
方法1:全局配置UIKit控件样式(默认Picker适用)
SwiftUI默认Picker基于UIKit实现,直接设置SwiftUI Text样式无法穿透到UIKit内部。可在App启动时通过UIApperance全局配置对应控件的字体:
@main struct YourApp: App { init() { // 配置Picker选中项的字体 UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self, UIPickerView.self]).font = UIFont(name: "YourCustomFontName", size: 12) // 配置Picker下拉列表的字体 UILabel.appearance(whenContainedInInstancesOf: [UITableViewCell.self, UIPickerView.self]).font = UIFont(name: "YourCustomFontName", size: 12) // 如需加粗,直接使用带加粗字重的自定义字体,例如: // UILabel.appearance(...).font = UIFont(name: "YourCustomFont-Black", size: 12) } var body: some Scene { WindowGroup { ContentView() } } }
方法2:自定义Picker样式(灵活可控,推荐)
通过自定义PickerStyle,完全控制选中视图和下拉选项的样式,彻底摆脱系统默认UI限制:
// 自定义Picker样式实现 struct CustomPickerStyle: PickerStyle { func makeBody(configuration: Configuration) -> some View { // 选中项按钮,点击触发下拉列表 Button { withAnimation { configuration.isPresented.toggle() } } label: { HStack(alignment: .center, spacing: 4) { // 显示当前选中的文本 (configuration.selectedLabel ?? Text("请选择")) .font(.custom("YourCustomFontName", size: 12, relativeTo: .body)) .fontWeight(.black) // 下拉箭头 Image(systemName: "chevron.down") .font(.system(size: 10)) } } // 下拉列表使用Sheet展示 .sheet(isPresented: $configuration.isPresented) { NavigationStack { List(configuration.options) { option in Button { withAnimation { configuration.select(option.tag) configuration.isPresented.toggle() } } label: { // 给每个选项应用自定义字体 option.label .font(.custom("YourCustomFontName", size: 12, relativeTo: .body)) .fontWeight(.black) } } .navigationTitle("选择选项") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("取消") { configuration.isPresented.toggle() } } } } } } } // 在ContentView中应用自定义样式 struct ContentView: View { @State var pickerChoice: PickerChoice = .choiceA var body: some View { HStack(spacing: 0) { Text("Picker: ") .fontWeight(.black) Picker(selection: $pickerChoice) { ForEach(PickerChoice.allCases) { Text($0.label) .tag($0.id) } } label: { Text("Picking...") } .pickerStyle(CustomPickerStyle()) // 应用自定义样式 } .frame(maxWidth: .infinity, alignment: .leading) .padding() } }
方法3:Menu样式Picker的快速适配
如果使用.menu样式的Picker,可直接给Picker的label和内部选项设置字体:
struct ContentView: View { @State var pickerChoice: PickerChoice = .choiceA var body: some View { HStack(spacing: 0) { Text("Picker: ") .fontWeight(.black) Picker(selection: $pickerChoice) { ForEach(PickerChoice.allCases) { option in Text(option.label) .font(.custom("YourCustomFontName", size: 12)) .tag(option.id) } } label: { // 给选中状态的文本设置自定义字体 Text(pickerChoice.label) .font(.custom("YourCustomFontName", size: 12)) .fontWeight(.black) } .pickerStyle(.menu) } .frame(maxWidth: .infinity, alignment: .leading) .padding() } }
内容的提问来源于stack exchange,提问作者invalidArgument
相关产品推荐
相关产品推荐

