这是通过触摸导航栏中间的按钮来显示视图并通过触摸其他任何地方将其删除的好方法吗?

Posted

技术标签:

【中文标题】这是通过触摸导航栏中间的按钮来显示视图并通过触摸其他任何地方将其删除的好方法吗?【英文标题】:Is this a good way to show a view by touch a button at the middle of the navigation bar and remove it by touch anywhere else? 【发布时间】:2017-06-20 14:08:56 【问题描述】:

我试图在导航栏的中间放置一个按钮,当我触摸它时它会显示一个列表(我在这里添加了一个纯 UIView 而不是 UITabeView 只是为了使代码更简单)。然后当我触摸其他任何地方时,附加视图将被删除。所以我添加了一个与屏幕大小相同的背景视图来响应我的触摸。虽然它还在导航栏的后面。 这是我的问题: 这是一个好的实现吗?

class ViewController: UIViewController 
    var optionView: UIView!
    var backgroundView: UIView!

    override func viewDidLoad() 
        super.viewDidLoad()

        let button = UIButton(type: .system)
        button.addTarget(self, action: #selector(ViewController.titleButtonTapped), for: .touchUpInside)
        button.frame = CGRect(x: 0, y: 0, width: 20, height: 30)
        button.backgroundColor = .red
        navigationItem.titleView = button
    

    func titleButtonTapped() 
        backgroundView = UIView(frame: UIScreen.main.bounds)
        backgroundView.backgroundColor = .clear
        let gesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleGesture)) // add this gesture to response my touch
        backgroundView.addGestureRecognizer(gesture)
        view.addSubview(maskView)

        optionView = UIView(frame: CGRect(x: -40, y: 30, width: 100, height: 100)) // x = button.wdith / 2  - optionView.width / 2 
        optionView.backgroundColor = .red
        navigationItem.titleView?.addSubview(alertView)
    
    func handleGesture() 
        optionView.removeFromSuperview()
        backgroundView.removeFromSuperview()
    
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    



现在它看起来像下面这样。

编辑:

以下是我对弹出视图的实现。

func buttonTapped() 
    let popoverViewController = UIViewController()
    popoverViewController.preferredContentSize = CGSize(width: 300, height: 300)
    popoverViewController.modalPresentationStyle = .popover

    let presentationController = popoverViewController.popoverPresentationController!
    presentationController.delegate = self
    presentationController.sourceView = view
    presentationController.sourceRect = CGRect(x: 100, y: 100 , width: 100, height: 100)
    present(popoverViewController, animated: true, completion: nil)


// delegate
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle 
    return .none

它与 Apple 文档略有不同。他们建议我们最好在调用 present(:animated: completion:) 方法后配置演示控制器。但是如果我在演示之前不配置它就行不通。也许,因为我设置了委托。

在调用 present(_:animated:completion:) 之后配置 popover 演示控制器可能看起来违反直觉,但 UIKit 在您启动演示之前不会创建演示控制器。此外,UIKit 必须等到下一个更新周期才能在屏幕上显示新内容。该延迟使您有时间为弹出框配置演示控制器。

【问题讨论】:

【参考方案1】:

是否使用弹出框取决于此弹出视图的目的。如果它有很多信息,最好将其分离到另一个视图控制器并在按钮单击时对其进行segue。这将为用户提供全屏查看它是什么。 对我来说,在导航栏的中心添加一个按钮并不常见。你必须通知我,我才能点击它。

结论:

如果你想要一个弹出视图来告诉用户提示或向他们展示一些东西,最好使用UIPopoverPresentationController,这样你就不需要关心样式了。

如果您希望另一个视图显示数据、图片列表等,最好使用分段控件或另一个视图控制器

【讨论】:

UIpopoverPresentationController 完美!上面的编辑部分是新代码。谢谢。【参考方案2】:
var optionView: UIView!
var backgroundView: UIView!

override func viewDidLoad()

    super.viewDidLoad()
    self.view.backgroundColor = UIColor.white
    let button = UIButton(type: .system)
    button.addTarget(self, action: #selector(ViewController.titleButtonTapped), for: .touchUpInside)
    button.frame = CGRect(x: 0, y: 0, width: 20, height: 30)
    button.backgroundColor = .red
    navigationItem.titleView = button


func titleButtonTapped()

    if backgroundView == nil
    
        backgroundView = UIView(frame: UIScreen.main.bounds)
        backgroundView.backgroundColor = .clear
        let gesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleGesture)) // add this gesture to response my touch
        backgroundView.addGestureRecognizer(gesture)
        view.addSubview(backgroundView)
    
    if optionView == nil
    
        optionView = UIView(frame: CGRect(x: -40, y: 30, width: 100, height: 100)) // x = button.wdith / 2  - optionView.width / 2
        optionView.backgroundColor = .red
        navigationItem.titleView?.addSubview(optionView)
    


func handleGesture()

    if optionView != nil
    
        optionView.removeFromSuperview()
        optionView = nil
    
    if backgroundView != nil
    
        backgroundView.removeFromSuperview()
        backgroundView = nil
    


override func didReceiveMemoryWarning()

    super.didReceiveMemoryWarning()

【讨论】:

以上是关于这是通过触摸导航栏中间的按钮来显示视图并通过触摸其他任何地方将其删除的好方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

导航栏按钮单击事件在单击其下方区域时触发。

按钮不可触摸

ViewController 不响应触摸

如何检测iCarouselButtonDemo的触摸点?

向后滑动时嵌套推送动画可能导致导航栏损坏

触摸时禁用其他栏按钮项:导航栏