如何实现无模糊效果的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
相关产品推荐
相关产品推荐

