Swift: 在Storyboard上使用悬浮加号按钮覆盖TableView

16

如何使用storyboard添加浮动按钮,类似Facebook的App Rooms?

我只知道在tableview上拖动UIView,但现在无法这样做。

输入图片说明 输入图片说明


这是一个旧问题,但这里有一个很棒的Swift库 - https://github.com/yoavlt/LiquidFloatingActionButton - Anjan Biswas
6个回答

20

以下是按钮代码:

  • 添加阴影
  • 将按钮变圆
  • 添加动画以引起注意

Swift 4.2:完成视图控制器实现

import Foundation

public class FloatingButtonViewController: UIViewController {
    private var floatingButton: UIButton?
    // TODO: Replace image name with your own image:
    private let floatingButtonImageName = "NAME OF YOUR IMAGE"
    private static let buttonHeight: CGFloat = 75.0
    private static let buttonWidth: CGFloat = 75.0
    private let roundValue = FloatingButtonViewController.buttonHeight/2
    private let trailingValue: CGFloat = 15.0
    private let leadingValue: CGFloat = 15.0
    private let shadowRadius: CGFloat = 2.0
    private let shadowOpacity: Float = 0.5
    private let shadowOffset = CGSize(width: 0.0, height: 5.0)
    private let scaleKeyPath = "scale"
    private let animationKeyPath = "transform.scale"
    private let animationDuration: CFTimeInterval = 0.4
    private let animateFromValue: CGFloat = 1.00
    private let animateToValue: CGFloat = 1.05

    public override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        createFloatingButton()
    }

    public override func viewWillDisappear(_ animated: Bool) {
        guard floatingButton?.superview != nil else {  return }
        DispatchQueue.main.async {
            self.floatingButton?.removeFromSuperview()
            self.floatingButton = nil
        }
        super.viewWillDisappear(animated)
    }

    private func createFloatingButton() {
        floatingButton = UIButton(type: .custom)
        floatingButton?.translatesAutoresizingMaskIntoConstraints = false
        floatingButton?.backgroundColor = .white
        floatingButton?.setImage(UIImage(named: floatingButtonImageName), for: .normal)
        floatingButton?.addTarget(self, action: #selector(doThisWhenButtonIsTapped(_:)), for: .touchUpInside)
        constrainFloatingButtonToWindow()
        makeFloatingButtonRound()
        addShadowToFloatingButton()
        addScaleAnimationToFloatingButton()
    }

    // TODO: Add some logic for when the button is tapped.
    @IBAction private func doThisWhenButtonIsTapped(_ sender: Any) {
        print("Button Tapped")
    }

    private func constrainFloatingButtonToWindow() {
        DispatchQueue.main.async {
            guard let keyWindow = UIApplication.shared.keyWindow,
                let floatingButton = self.floatingButton else { return }
            keyWindow.addSubview(floatingButton)
            keyWindow.trailingAnchor.constraint(equalTo: floatingButton.trailingAnchor,
                                                constant: self.trailingValue).isActive = true
            keyWindow.bottomAnchor.constraint(equalTo: floatingButton.bottomAnchor,
                                              constant: self.leadingValue).isActive = true
            floatingButton.widthAnchor.constraint(equalToConstant:
                FloatingButtonViewController.buttonWidth).isActive = true
            floatingButton.heightAnchor.constraint(equalToConstant:
                FloatingButtonViewController.buttonHeight).isActive = true
        }
    }

    private func makeFloatingButtonRound() {
        floatingButton?.layer.cornerRadius = roundValue
    }

    private func addShadowToFloatingButton() {
        floatingButton?.layer.shadowColor = UIColor.black.cgColor
        floatingButton?.layer.shadowOffset = shadowOffset
        floatingButton?.layer.masksToBounds = false
        floatingButton?.layer.shadowRadius = shadowRadius
        floatingButton?.layer.shadowOpacity = shadowOpacity
    }

    private func addScaleAnimationToFloatingButton() {
        // Add a pulsing animation to draw attention to button:
        DispatchQueue.main.async {
            let scaleAnimation: CABasicAnimation = CABasicAnimation(keyPath: self.animationKeyPath)
            scaleAnimation.duration = self.animationDuration
            scaleAnimation.repeatCount = .greatestFiniteMagnitude
            scaleAnimation.autoreverses = true
            scaleAnimation.fromValue = self.animateFromValue
            scaleAnimation.toValue = self.animateToValue
            self.floatingButton?.layer.add(scaleAnimation, forKey: self.scaleKeyPath)
        }
    }
}

1
除了在viewWillDisappear中删除按钮之外,这个程序运行得很好。无法将按钮设置为nil,并且removeFromSuperview()没有被调用。移除了DispatchQueue并将按钮设置为nil。现在按预期工作。 - Matthew Bradshaw
你的圆形按钮需要是一个变量,而不是一个常量。 - Joshua Hart
1
返回已完整实现的翻译文本: - Joshua Hart
1
@JoshuaHart 感谢您的代码更新!我认为在 viewWillDisappear(_:) 中,您想使用的是 super.viewWillDisappear(animated) 而不是 super.viewWillAppear(animated)?此外,对于脉动动画,我需要将代码放在 DispatchQueue.main.async { ... } 中,以便脉动对我起作用。再次感谢! - bvh
有人能展示一下我如何使用这段代码吗?在viewDidLoad中,我做了以下操作: let operationButton:FloatingButtonViewController = self.storyboard!.instantiateViewController(withIdentifier: "FloatingButtonViewController") as! FloatingButtonViewController operationButton.view.frame = self.view.bounds; operationButton.willMove(toParent: self) self.view.addSubview(operationButton.view) self.addChild(operationButton) operationButton.didMove(toParent: self)但是在UITableViewController上,当填充数据时,原型单元格变得不可见。 - Marco
显示剩余7条评论

15

有点晚了,但希望能帮到某些人。您可以通过编程轻松地完成此操作。只需创建按钮的实例,设置所需的属性即可。最好使用约束而不是框架,因为它会在每个屏幕大小上以相同的位置呈现按钮。我将发布使按钮变圆的代码。尝试使用约束值来更改按钮的位置和大小。

Swift 3

var roundButton = UIButton()
override func viewDidLoad() {
    super.viewDidLoad()
    self.roundButton = UIButton(type: .custom)
    self.roundButton.setTitleColor(UIColor.orange, for: .normal)
    self.roundButton.addTarget(self, action: #selector(ButtonClick(_:)), for: UIControlEvents.touchUpInside)
    self.view.addSubview(roundButton)
}

override func viewWillLayoutSubviews() {

    roundButton.layer.cornerRadius = roundButton.layer.frame.size.width/2
    roundButton.backgroundColor = UIColor.lightGray
    roundButton.clipsToBounds = true
    roundButton.setImage(UIImage(named:"your-image"), for: .normal)
    roundButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        roundButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -3),  
    roundButton.bottomAnchor.constraint  
    (equalTo: self.view.bottomAnchor, constant: -53), 
    roundButton.widthAnchor.constraint(equalToConstant: 50),
    roundButton.heightAnchor.constraint(equalToConstant: 50)])
}

/** Action Handler for button **/

@IBAction func ButtonClick(_ sender: UIButton){

 /** Do whatever you wanna do on button click**/

}

7
将表格视图放置在视图控制器中。然后您应该能够在表格视图顶部添加按钮。
请参考以下截图:Storyboard

1
这是关于编程的内容,请将后面的制作方法放到前面。 - user3662992
1
否则,它将位于表行内。 - user3662992
1
如果我自动拖动一个按钮,它会自动排列在行中! - user3662992
1
将其拖到场景中,并确保它的顺序是按钮位于表视图下方(但不在其中) - litso
1
@user3662992,您能否尝试以上内容? - litso
显示剩余2条评论

4

以下是@Kunal Kumar的回答,它适用于UIScrollViewUIView,但不适用于UITableView。我发现只需要添加一行代码就可以让它在UITableView上工作。非常感谢@Kunal Kumar。

viewDidLoad中,将self.view.addSubview(roundButton)更改为self.navigationController?.view.addSubview(roundButton)即可。

顺便说一下,在viewWillLayoutSubviews()方法中,我认为我们需要添加super.viewWillLayoutSubviews()

以下是所有代码:

Swift 3

// MARK: Floating Button

var roundButton = UIButton()
func createFloatingButton() {
    self.roundButton = UIButton(type: .custom)
    self.roundButton.setTitleColor(UIColor.orange, for: .normal)
    self.roundButton.addTarget(self, action: #selector(ButtonClick(_:)), for: UIControlEvents.touchUpInside)
    //change view to navigationController?.view, if you have a navigationController in this tableview
    self.navigationController?.view.addSubview(roundButton)
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    roundButton.layer.cornerRadius = roundButton.layer.frame.size.width/2
    roundButton.backgroundColor = UIColor.lightGray
    roundButton.clipsToBounds = true
    roundButton.setImage(UIImage(named:"ic_wb_sunny_48pt"), for: .normal)
    roundButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        roundButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -3),
        roundButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -53),
        roundButton.widthAnchor.constraint(equalToConstant: 50),
        roundButton.heightAnchor.constraint(equalToConstant: 50)])
}

2

这是因为您的UIButton位于UITableView下方,将其移动到故事板树中,使其显示如下:

最初的回答:

只是因为您的UIButton位于UITableView下方,请将其移动到故事板树中,以便它显示在UITableView上方。

| View
|-- Table View
|-- Button

0
Swift 5,改进@litso的回答:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接