You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:04:52