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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:23:01