【问题标题】:Insert a floating action button on UITableView in Swift在 Swift 中的 UITableView 上插入一个浮动操作按钮
【发布时间】:2026-01-05 01:05:02
【问题描述】:

我正在尝试添加一个浮动操作按钮(不是浮动菜单按钮),只需单击一下即可将我导航到下一个视图控制器。我没有得到正确的浮动按钮。我已经尝试了下面的代码,它没有在表格视图上显示适当的按钮,因为它与表格一起滚动。有什么方法可以将按钮粘贴在同一个位置而不随表格一起滚动?

func floatingButton(){
    let btn = UIButton(type: .custom)
    btn.frame = CGRect(x: 285, y: 485, width: 100, height: 100)
    btn.setTitle("All Defects", for: .normal)
    btn.backgroundColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)
    btn.clipsToBounds = true
    btn.layer.cornerRadius = 50
    btn.layer.borderColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    btn.layer.borderWidth = 3.0
    btn.addTarget(self,action: #selector(DestinationVC.buttonTapped), for: UIControlEvent.touchUpInside)
    view.addSubview(btn)
}

【问题讨论】:

  • *.com/questions/37073935/… ?您的按钮不应与 tableView 一起滚动,除非在 view.addSubview(btn) 中的代码中,view 是 tableView。还是您的UIViewControllerUITableViewController
  • 我已经检查了那个问题。不过感谢分享。我的表格视图是一个 xib 文件..不知道如何设置浮动按钮
  • 您分享的链接讲述了浮动菜单按钮..我不想实现浮动菜单按钮..而是屏幕截图所示的单个浮动操作按钮

标签: ios swift uitableview uibutton


【解决方案1】:

添加到UITableView 的所有子视图都会自动滚动。

你可以做的是将按钮添加到应用程序窗口,只要记住在 ViewController 消失时将其移除即可。

var btn = UIButton(type: .custom)
func floatingButton(){
    btn.frame = CGRect(x: 285, y: 485, width: 100, height: 100)
    btn.setTitle("All Defects", for: .normal)
    btn.backgroundColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)
    btn.clipsToBounds = true
    btn.layer.cornerRadius = 50
    btn.layer.borderColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
    btn.layer.borderWidth = 3.0
    btn.addTarget(self,action: #selector(DestinationVC.buttonTapped), for: UIControlEvent.touchUpInside)
    if let window = UIApplication.shared.keyWindow {
        window.addSubview(btn)
    }
}

viewWillDisappear:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    btn.removeFromSuperview()
}

对于 iOS 13 及更高版本,您可以使用此扩展程序检查密钥窗口:

extension UIWindow {
    static var key: UIWindow? {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
        } else {
            return UIApplication.shared.keyWindow
        }
    }
}

【讨论】:

  • 在哪里添加上述功能
  • @Saurabh viewDidLoad 或 viewWillAppear
  • @ahbou 几件事。在这条线上UIApplication.shared.keyWindow 显示这个错误'keyWindow' was deprecated in iOS 13.0 你知道我该如何替换那条线吗?让工作成为 iOS 13 的解决方案?
  • 在 iOS 13 上,一个应用可以有多个窗口。请参阅此答案以获取解决方案:*.com/a/58031897/3698961
【解决方案2】:

这是一个使用 Swift 4.2 的 XCode 10 的工作示例。

请注意,当视图消失时,FAB 按钮会消失,并在再次加载控制器时重新出现。

import UIKit

class ViewController: UITableViewController {

lazy var faButton: UIButton = {
    let button = UIButton(frame: .zero)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.backgroundColor = .blue
    button.addTarget(self, action: #selector(fabTapped(_:)), for: .touchUpInside)
    return button
}()

override func viewDidLoad() {
    super.viewDidLoad()
    setupTableView()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    if let view = UIApplication.shared.keyWindow {
        view.addSubview(faButton)
        setupButton()
    }
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if let view = UIApplication.shared.keyWindow, faButton.isDescendant(of: view) {
        faButton.removeFromSuperview()
    }
}

func setupTableView() {
    tableView.backgroundColor = .darkGray
}

func setupButton() {
    NSLayoutConstraint.activate([
        faButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -36),
        faButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -36),
        faButton.heightAnchor.constraint(equalToConstant: 80),
        faButton.widthAnchor.constraint(equalToConstant: 80)
        ])
    faButton.layer.cornerRadius = 40
    faButton.layer.masksToBounds = true
    faButton.layer.borderColor = UIColor.lightGray.cgColor
    faButton.layer.borderWidth = 4
}

@objc func fabTapped(_ button: UIButton) {
    print("button tapped")
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 5
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return UITableViewCell()
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 64
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 32
}

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return UIView()
}
}

【讨论】:

    【解决方案3】:

    如果你当前使用的是 tableViewController ,那么你必须继承 UIViewController 添加 UItableView 和你的浮动按钮

    或者您可以覆盖 scollviewDidScroll 并根据 tableview 当前偏移量更改按钮 y

    将滚动视图拖动为 IBOutlet 并将其设置为 viewController

       func scrollViewDidScroll(_ scrollView: UIScrollView) {
    
           let  off = scrollView.contentOffset.y
    
           btn.frame = CGRect(x: 285, y:   off + 485, width: btn.frame.size.width, height: btn.frame.size.height)
    }
    

    代码快照

    在行动

    看实际

    【讨论】:

    • 为什么不起作用? tableViewController 不是内部带有 tableView 的 UIViewController 的子类吗?那么 tableViewController.tableView.addSubview 应该工作吗?
    • 其实table view是一个xib文件。所以我在表格视图类本身中插入了上述函数
    • @josha 如果没有实现 scrollviewDidScroll 委托和 tableViewController 内部的任何内容,任何内容都会滚动
    • 你使用 tableViewController 或子类 uiviewcontroller
    • 我不能使用 tableviewcontroller,因为我在视图控制器上使用 uiscrollview 并水平滚动滚动视图。我在滚动视图的每个滚动上都有视图控制器 xibs 文件。其中之一是我必须在其上添加浮动按钮的表格视图
    【解决方案4】:

    有一种方法对我有用。在我的表格视图控制器中,先定义一个按钮,然后重写函数scrollViewDidScroll(),像这样:

    import UIKit
    
    class MyTableViewController: UITableViewController {
    
        private let button = UIButton(type: UIButton.ButtonType.custom) as UIButton
    
        override func viewDidLoad() {
            let bottomImage = UIImage(named: "yourImage.png")
            let yPst = self.view.frame.size.height - 55 - 20
            button.frame = CGRect(x: 12, y: yPst, width: 55, height: 55)
            button.setImage(bottomImage, for: .normal)
            button.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin]
            button.addTarget(self, action: #selector(buttonClicked(_:)), for:.touchUpInside)
            button.layer.shadowRadius = 3
            button.layer.shadowColor = UIColor.lightGray.cgColor
            button.layer.shadowOpacity = 0.9
            button.layer.shadowOffset = CGSize.zero
            button.layer.zPosition = 1
            view.addSubview(button)
        }
    
        override func scrollViewDidScroll(_ scrollView: UIScrollView) {
            let off = self.tableView.contentOffset.y
            let yPst = self.view.frame.size.height
            button.frame = CGRect(x: 12, y:off + yPst, width: button.frame.size.width, height: button.frame.size.height)
        }
    
        @objc private func buttonClicked(_ notification: NSNotification) {
            // do something when you tapped the button
        }
    }
    

    【讨论】: