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

如何实现无模糊效果的Action Sheet或类Action Sheet UI?

实现无模糊效果的Action Sheet或类Action Sheet UI

你当前使用AlertController的.actionSheet样式,即使设置blurEffect = nil仍存在轻微模糊效果,想要实现无模糊的弹窗以支持字体选择的实时预览,可参考以下几种方案:

方案一:自定义底部弹窗控制器(推荐)

系统Action Sheet的模糊效果可能有底层默认实现,难以完全清除,自定义控制器可以完全掌控UI样式,稳定性更高,也能完美适配实时预览需求。

代码示例:

// 自定义底部弹窗控制器
class FontPickerBottomSheet: UIViewController {
    // 定义回调,用于通知主控制器更新字体
    var fontSelectedHandler: ((UIFont) -> Void)?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置无模糊背景
        view.backgroundColor = .systemBackground
        // 添加圆角(可选,模拟Action Sheet原生样式)
        view.layer.cornerRadius = 16
        view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        
        // 添加字体选择列表
        let tableView = UITableView(frame: view.bounds)
        tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        tableView.dataSource = self
        tableView.delegate = self
        view.addSubview(tableView)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 实现底部弹出动画
        let screenHeight = UIScreen.main.bounds.height
        let sheetHeight: CGFloat = 400
        view.frame = CGRect(x: 0, y: screenHeight, width: view.bounds.width, height: sheetHeight)
        
        UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut) {
            self.view.frame = CGRect(x: 0, y: screenHeight - sheetHeight, width: self.view.bounds.width, height: sheetHeight)
        }
    }
}

// 实现列表数据源与代理
extension FontPickerBottomSheet: UITableViewDataSource, UITableViewDelegate {
    // 模拟字体列表
    private let fontNames = ["PingFang SC", "Helvetica Neue", "Arial", "Times New Roman"]
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return fontNames.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
        let fontName = fontNames[indexPath.row]
        cell.textLabel?.text = fontName
        // 单元格内实时预览字体样式
        cell.textLabel?.font = UIFont(name: fontName, size: 17)
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let selectedFont = UIFont(name: fontNames[indexPath.row], size: 17)!
        // 通知主控制器更新界面字体,实现实时预览
        fontSelectedHandler?(selectedFont)
        // 关闭弹窗
        dismiss(animated: true)
    }
}

// 弹出自定义弹窗的调用方式
let bottomSheet = FontPickerBottomSheet()
bottomSheet.modalPresentationStyle = .overFullScreen // 保留背景界面可见
bottomSheet.fontSelectedHandler = { [weak self] selectedFont in
    // 在这里更新主界面的字体
    self?.updatePreviewFont(selectedFont)
}
present(bottomSheet, animated: false)

方案二:移除系统Action Sheet的模糊视图

通过遍历AlertController的子视图,找到模糊效果的UIVisualEffectView并隐藏。注意:该方法依赖系统视图结构,iOS版本更新可能失效,仅作临时应急方案。

代码示例:

let alertAlertController = AlertController(title: nil, message: nil, preferredStyle: .actionSheet)
self.alertAlertController = alertAlertController

let alertVisualStyle = AlertVisualStyle(alertStyle: .actionSheet)
alertVisualStyle.blurEffect = nil
alertVisualStyle.backgroundColor = .systemBackground
alertAlertController.visualStyle = alertVisualStyle

// 先完成布局,再遍历移除模糊视图
alertAlertController.view.layoutIfNeeded()
func removeBlurViews(from view: UIView) {
    for subview in view.subviews {
        if subview is UIVisualEffectView {
            subview.isHidden = true
        } else {
            removeBlurViews(from: subview)
        }
    }
}
removeBlurViews(from: alertAlertController.view)

present(alertAlertController, animated: true)

方案三:使用自定义底部弹窗组件

可以选择成熟的底部弹窗组件,这类组件通常支持完全自定义样式,只需配置背景色为非模糊的纯色即可轻松实现需求。


内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:57:05