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

UIFontPicker嵌入Sheet无法下滑关闭及样式适配问题

问题解答

问题1:Sheet下滑关闭时出现多余空白区域

原因

直接将UIFontPickerViewController作为SwiftUI Sheet的根视图时,其内部布局系统与SwiftUI Sheet的容器环境不兼容。触发Sheet下滑手势时,UIFontPickerViewController的视图未正确响应容器布局变化,导致出现空白区域。

解决方案

将UIFontPickerViewController嵌入UINavigationController中,利用导航控制器的布局系统适配Sheet环境。修改SUIFontPicker的makeUIViewController方法:

public func makeUIViewController(context: UIViewControllerRepresentableContext<SUIFontPicker>) -> UINavigationController {
    let configuration = UIFontPickerViewController.Configuration()
    configuration.includeFaces = true
    configuration.displayUsingSystemFont = false
    
    let fontPickerVC = UIFontPickerViewController(configuration: configuration)
    fontPickerVC.delegate = context.coordinator
    
    return UINavigationController(rootViewController: fontPickerVC)
}

嵌入导航控制器后,布局会正确响应Sheet下滑手势,空白区域问题将被修复。


问题2:在Sheet中实现原生present的UIFontPicker效果

原因

原生present(_:animated:)弹出UIFontPickerViewController时,系统会自动为其添加带标题和Cancel按钮的导航栏,且搜索栏固定顶部。但SwiftUI Sheet直接展示该VC时,导航栏未被正确初始化显示,导致丢失这些原生元素。

解决方案

通过UINavigationController包装UIFontPickerViewController,手动配置标题和Cancel按钮:

  1. 修改SUIFontPicker的makeUIViewController方法:
public func makeUIViewController(context: UIViewControllerRepresentableContext<SUIFontPicker>) -> UINavigationController {
    let configuration = UIFontPickerViewController.Configuration()
    configuration.includeFaces = true
    configuration.displayUsingSystemFont = false
    
    let fontPickerVC = UIFontPickerViewController(configuration: configuration)
    fontPickerVC.delegate = context.coordinator
    
    let navController = UINavigationController(rootViewController: fontPickerVC)
    navController.navigationBar.topItem?.title = "Choose Font"
    
    // 添加Cancel按钮并绑定回调
    let cancelBtn = UIBarButtonItem(barButtonSystemItem: .cancel, target: context.coordinator, action: #selector(context.coordinator.dismissSheet))
    navController.navigationBar.topItem?.leftBarButtonItem = cancelBtn
    
    return navController
}
  1. 在Coordinator类中添加dismissSheet方法:
@objc func dismissSheet() {
    parent.presentationMode.wrappedValue.dismiss()
}

修改后,Sheet弹出的字体选择器会拥有原生样式的标题、Cancel按钮,且搜索栏固定在顶部。


问题3:额外问题解答

子问题1:让UIButton自适应内容尺寸

原因

手动设置frame会固定按钮大小,无法根据标题内容自动调整,需要依赖Auto Layout实现自适应。

解决方案

关闭按钮的自动约束转换,添加Auto Layout约束:

override func viewDidLoad() {
    super.viewDidLoad()
    fontPicker.delegate = self
    let button = UIButton(type: .system)
    button.titleLabel?.font = .systemFont(ofSize: 17)
    button.setTitle("Choose font", for: .normal)
    button.addTarget(self, action: #selector(showFontPicker(sender:)), for: .touchUpInside)
    view.addSubview(button)
    
    // 启用Auto Layout
    button.translatesAutoresizingMaskIntoConstraints = false
    // 添加居中约束(可根据需求调整)
    NSLayoutConstraint.activate([
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
}

按钮会根据标题内容自动计算并适配尺寸。

子问题2:仅修改文本字号而不改变字体族

原因

使用.font(.caption)会覆盖继承的字体族,系统会默认使用caption样式的字体,需要基于选中字体单独调整字号。

解决方案

基于选中的UIFont创建仅修改字号的新字体:

Text(selectedFont.fontName)
    .font(Font(UIFont(descriptor: selectedFont.fontDescriptor, size: UIFont.preferredFont(forTextStyle: .caption1).pointSize)))

iOS 16+可使用更简洁的withSize方法:

Text(selectedFont.fontName)
    .font(Font(selectedFont).withSize(UIFont.preferredFont(forTextStyle: .caption1).pointSize))

这样文本会保留选中的字体族,仅应用caption样式的字号。

内容的提问来源于stack exchange,提问作者BPDev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:42:32