ios - 如何隐藏 View 的 subview ( float 操作按钮)以防止点击两个不同的区域

标签 ios swift uitableview floating-action-button

我创建了一个 float 操作按钮,当用户在 FAB 打开时点击它,或者当用户点击屏幕上的任意位置并且 FAB 打开时,我想关闭所有操作按钮。同样重要的是要注意 FAB 显示在 tableview 上,我想保留选择 tableview 单元格的能力。

在我的 FAB 实现中,我向 FAB 按钮添加了一个目标,我用它来打开和关闭 FAB,我还在 viewController 上使用 tableview 实现了一个 tapGesture,这样当调用一个点击手势时,我可以关闭如果打开 FAB。

为了完成这项工作,我做了一些研究,发现我必须设置

tap.cancelsTouchesInView = false

以便 tableView 事件继续工作。然而,副作用是,当我点击 fab 关闭它时,会触发两个事件,一个是从 FAB 的 tapGesture 触发,另一个是从按钮目标触发,这导致 FAB 在打开时点击它时不会关闭。

有没有一种更优雅的方法可以让 FAB 在打开时被点击关闭,并且当它打开并且用户点击屏幕上的任意位置时,viewController 上的点击手势也可以关闭 fab。

这是我的一些代码:

View Controller :

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let tap = UITapGestureRecognizer(target: self,
                                         action: #selector(self.dismissActionButtons(_:)))
        self.view.addGestureRecognizer(tap)
        
        tap.cancelsTouchesInView = false
        self.floatingActionButton.isHidden = true
    }

    @objc func dismissActionButtons(_ sender: UIButton) {
        if !floatingActionButton.actionButtonsCarousel.isHidden {
            self.floatingActionButton.animateActionButtonsDisappering()
        }
    }

自定义 FAB View :

    
    override init(frame: CGRect) {
        super.init(frame: .zero)
        
        actionButtonsCarousel.isHidden = true
        self.translatesAutoresizingMaskIntoConstraints = false
        
        self.mainButton.addTarget(self,
                                   action: #selector(ACTFAB.fabButtonAction(_:)),
                                   for: .touchUpInside)
        
    }
    @objc func fabButtonAction(_ sender: UIButton) {
        
        if self.actionButtonsCarousel.isHidden {
            self.animateActionButtonsAppering()
        } else {
            self.animateActionButtonsDisappering()
        }
    }
    
    func animateActionButtonsAppering() {
        self.actionButtonsCarousel.alpha = 0.0
        self.actionButtonsCarousel.isHidden = false
        
        UIView.transition(with: self, duration: 0.5, options: .preferredFramesPerSecond60, animations: {
            self.actionButtonsCarousel.alpha = 1.0
        })
        self.mainButton.setImage(UIImage(named: "fab-open-icon"), for: .normal)
    }
    
    func animateActionButtonsDisappering() {
        self.actionButtonsCarousel.alpha = 1.0
        self.actionButtonsCarousel.isHidden = true
        
        UIView.transition(with: self, duration: 0.3, options: .transitionCrossDissolve, animations: {
            self.actionButtonsCarousel.alpha = 0.0
        })
        self.mainButton.setImage(UIImage(named: "fab-closed-icon"), for: .normal)
    }

两个有效场景:

1 FAB is open -> click FAB -> FAB closes

2 FAB is open -> click anywhere other than FAB -> FAB closes

场景 1 因我当前的代码而失败。

最佳答案

如果我正确理解你的问题,问题是点击 FAB 会导致按钮的 Action 被触发,而且当你将事件传递给底层 viewController 时,gestureRecogniser 也会触发。

我假设按钮操作是主要事件,并且当它触发时您需要停止 gestureRecogniser。 gestureRecogniser 有一个 .location(in:) 方法,它允许您根据任何 View 获取第一个点击位置(对于 tapGestureRecogniser),而 UIView 有一个.point(inside: with:) 方法检查 CGPoint(根据它自己的坐标空间)是否在它的边界内。因此你应该能够做这样的事情(从内存而不是编译,所以可能需要一些调整但希望它能让你开始):

@objc func dismissActionButtons(_ sender: UIButton) {
  let tapPoint = sender.location(in: customFABview)
  if customFABview.point(inside: tapPoint, with: nil) && 
    !floatingActionButton.actionButtonsCarousel.isHidden {
            self.floatingActionButton.animateActionButtonsDisappering()
  }
}

关于ios - 如何隐藏 View 的 subview ( float 操作按钮)以防止点击两个不同的区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58798105/

相关文章:

ios - Jenkins : Invalid gitTool selection Git

ios - 设置 UIButton 框架并维护约束

ios - 有没有一种方法可以通过其中一个单元格中的按钮刷新整个 UITableView?

ios - 第二次加载 View Controller 时,UITableView reloadData 不起作用

ios - 在 UISearchController 中搜索时无法在 tableView 中滚动

ios - 如何替换 coreData iOS 中的 abort() 函数

ios - AVPlayerLayer 未将大小更改为单元格边界

iphone - 如何使用 MPMoviePlayerController 或 AVPlayer 在 iOS 上播放没有文件扩展名的电影文件?

ios - 使用 phimagemanager 将图像保存到自定义相册?

Swift firestore updateData 不创建新文档