UIKit实现底部带按钮容器顶部边缘模糊,使表格视图内容在其上方模糊显示的问题
UIKit实现底部带按钮容器顶部边缘模糊,使表格视图内容在其上方模糊显示的问题
我完全懂你想要的效果——底部带按钮的容器顶部边缘呈现渐变模糊,当表格滚动到底部时,最后几行内容能透过这个模糊区域自然过渡显示。看了你的代码,问题主要出在两个地方:表格内容没有延伸到底部容器下方,以及缺少“仅顶部边缘模糊”的遮罩设置。下面是一步步的修正方案:
一、核心问题修复:让表格内容能滚到底部容器下方
你当前代码里设置了tableView.contentInset.bottom = 100和tableView.scrollIndicatorInsets.bottom = 100,这会强制表格内容和底部保持100pt的空白距离,导致表格最后几行永远不会出现在模糊视图的下方,自然看不到模糊效果。所以首先要删掉这两行:
// 删掉这两行代码 // tableView.contentInset.bottom = 100 // tableView.scrollIndicatorInsets.bottom = 100
现在表格内容可以正常滚动到屏幕最底部,也就是模糊视图的下方,这样模糊视图就能捕捉到下面的表格内容了。
二、实现“仅底部容器顶部边缘模糊”的效果
如果你想要的是容器顶部边缘渐变模糊,按钮所在区域清晰的效果,需要给模糊视图添加一个渐变遮罩层,只让顶部区域显示模糊效果,下方区域则挡住模糊,突出按钮。修改你的blurView初始化代码:
private lazy var blurView: UIVisualEffectView = { let blurEffect = UIBlurEffect(style: .systemThinMaterial) let blurView = UIVisualEffectView(effect: blurEffect) blurView.clipsToBounds = true // 添加渐变遮罩:从顶部完全透明(显示模糊)过渡到不透明(挡住模糊) let gradientMask = CAGradientLayer() gradientMask.colors = [UIColor.clear.cgColor, UIColor.black.cgColor] gradientMask.startPoint = CGPoint(x: 0.5, y: 0) // 渐变从顶部中心开始 gradientMask.endPoint = CGPoint(x: 0.5, y: 1) // 渐变到底部中心结束 // 调整locations参数可以控制模糊区域的高度,比如这里前20%的高度是完全模糊 gradientMask.locations = [0, 0.2] // 初始化遮罩的尺寸,后续会自动跟随模糊视图的frame变化 gradientMask.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100) blurView.layer.mask = gradientMask // 按钮的原有设置不变 blurView.contentView.addSubview(actionButton) actionButton.snp.makeConstraints { make in make.leading.trailing.top.equalToSuperview().inset(16) make.bottom.equalToSuperview().inset(32) } return blurView }()
三、可选:让模糊视图的遮罩自适应尺寸
为了让渐变遮罩能跟随模糊视图的尺寸变化(比如横竖屏切换),可以在viewDidLayoutSubviews里更新遮罩的frame:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if let gradientMask = blurView.layer.mask as? CAGradientLayer { gradientMask.frame = blurView.bounds } }
四、完整修正后的代码
把所有修改整合后,完整代码如下:
import UIKit import SnapKit final class BlurredTableViewController: UIViewController { private let tableView = UITableView() private lazy var blurView: UIVisualEffectView = { let blurEffect = UIBlurEffect(style: .systemThinMaterial) let blurView = UIVisualEffectView(effect: blurEffect) blurView.clipsToBounds = true // 添加渐变遮罩实现顶部边缘模糊 let gradientMask = CAGradientLayer() gradientMask.colors = [UIColor.clear.cgColor, UIColor.black.cgColor] gradientMask.startPoint = CGPoint(x: 0.5, y: 0) gradientMask.endPoint = CGPoint(x: 0.5, y: 1) gradientMask.locations = [0, 0.2] gradientMask.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100) blurView.layer.mask = gradientMask blurView.contentView.addSubview(actionButton) actionButton.snp.makeConstraints { make in make.leading.trailing.top.equalToSuperview().inset(16) make.bottom.equalToSuperview().inset(32) } return blurView }() private lazy var actionButton: UIButton = { let button = UIButton(type: .system) button.setTitle("Tap me", for: .normal) button.titleLabel?.font = .boldSystemFont(ofSize: 18) button.backgroundColor = .systemBlue button.setTitleColor(.white, for: .normal) button.layer.cornerRadius = 12 button.clipsToBounds = true return button }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground setupLayout() } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 更新遮罩尺寸以适配视图布局变化 if let gradientMask = blurView.layer.mask as? CAGradientLayer { gradientMask.frame = blurView.bounds } } private func setupLayout() { view.addSubview(tableView) view.addSubview(blurView) tableView.snp.makeConstraints { make in make.edges.equalToSuperview() } blurView.snp.makeConstraints { make in make.leading.trailing.equalTo(view.safeAreaLayoutGuide) make.bottom.equalToSuperview() make.height.equalTo(100) } tableView.backgroundColor = .clear tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") tableView.dataSource = self } } // MARK: - UITableViewDataSource extension BlurredTableViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "Row \(indexPath.row + 1)" cell.backgroundColor = .clear cell.contentView.backgroundColor = .clear cell.textLabel?.backgroundColor = .clear cell.selectionStyle = .none return cell } }
效果说明
- 现在表格内容可以滚动到模糊视图下方,模糊视图的顶部边缘会显示表格内容的模糊效果
- 渐变遮罩让模糊效果从顶部向下逐渐消失,按钮所在区域保持清晰,不会被模糊干扰
- 如果你想要整个底部容器背景都模糊的效果,只需要去掉渐变遮罩的代码即可
内容来源于stack exchange
相关产品推荐
相关产品推荐

