屏幕上显示弹出框时,UIBarButtonItem不会脱色/禁用

时间:2018-10-20 10:56:30

标签: ios swift uipopovercontroller uipopoverpresentationcontroller

我的导航控制器上有两个UIBarButtonItems

    segmentControl = UISegmentedControl(items: ["Up", "Down"])
    infoItem = UIBarButtonItem(image: infoImage,
                               style: .plain, 
                               target: self,
                               action: #selector(infoAction))
    navigationItem.rightBarButtonItems = [infoItem, UIBarButtonItem(customView: segmentControl)]

点击infoItem时,我会这样做:

@objc func infoAction()
{
    let popoverContentController = InfoViewController()

    popoverContentController.preferredContentSize = CGSize(width: 300, height: 300)
    popoverContentController.modalPresentationStyle = .popover
    popoverContentController.popoverPresentationController?.delegate = self
    popoverContentController.popoverPresentationController?.passthroughViews = nil

    self.present(popoverContentController, animated: true, completion: nil)
}

然后调用UIPopoverPresentationControllerDelegate函数:

func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController)
{
    popoverPresentationController.permittedArrowDirections = .any
    popoverPresentationController.barButtonItem = infoItem
    popoverPresentationController.passthroughViews = nil
}

func adaptivePresentationStyle(for controller: UIPresentationController,
                               traitCollection: UITraitCollection) -> UIModalPresentationStyle
{
    return .none
}

即使我将passthroughViews设置为nil两次,UISegmentedControl也不会脱色,并且在屏幕上显示弹出窗口时仍然可以点击。

如果显示其他弹出窗口,则UISegmentedControl的行为正常:已脱色且不可轻敲。

我在这里想念什么?

2 个答案:

答案 0 :(得分:1)

查看您的代码,一切似乎都很好。似乎操作系统中存在错误。

除非他们在iOS的下一版本中对其进行检查和修复,否则我已经找到了快速解决方案。

  1. 定义barButtonItems和变量以在ViewController中全局保存现有的色调颜色。

    var infoItem: UIBarButtonItem!
    var segmentItem: UIBarButtonItem!
    var savedTintColour: UIColor? = nil
    
  2. 在您的ViewDidLoad()中对其进行初始化

    segmentedControl = UISegmentedControl(items: ["Up", "Down"])
    infoItem = UIBarButtonItem(image: UIImage(named: "setting_mobile"),
                               style: .plain,
                               target: self,
                               action: #selector(infoAction))
    segmentItem = UIBarButtonItem(customView: segmentedControl)
    navigationItem.rightBarButtonItems = [infoItem, segmentItem]
    
  3. InfoAction的代码将保持不变。

    @objc func infoAction() {
        let popoverContentController = InfoViewController()
    
        popoverContentController.preferredContentSize = CGSize(width: 300, height: 300)
        popoverContentController.modalPresentationStyle = .popover
        popoverContentController.popoverPresentationController?.delegate = self
        popoverContentController.popoverPresentationController?.passthroughViews = nil
    
        self.present(popoverContentController, animated: true, completion: nil)
    }
    
  4. 实施委托方法prepareForPopoverPresentation,然后将颜色设置为darkGray,并将以前可用的tintColour保存为变量,以便在启用时可以重复使用。

    func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController) {
    popoverPresentationController.permittedArrowDirections = .any
    popoverPresentationController.barButtonItem = infoItem
    popoverPresentationController.passthroughViews = nil
    
    self.segmentItem.isEnabled = false
    if savedTintColour == nil {
        savedTintColour = self.segmentedControl.tintColor
    }
    self.segmentedControl.tintColor = .darkGray
    }
    
  5. 实施委托方法popoverPresentationControllerDidDismissPopover,以重置segmentControl的颜色并启用segmentedItem。

    func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) {
    self.segmentItem.isEnabled = true
    self.segmentedControl.tintColor = savedTintColour!
    }
    

希望有帮助。

答案 1 :(得分:0)

正如Bhavin Kansagara所建议的那样,模仿iOS行为是一种有效的解决方法。他的回答很接近,但是错过了一些细节:

  • popoverPresentationControllerDidDismissPopover被调用为时已晚,导致分段控件在所有其他UI元素之后再次变为蓝色。需要改用popoverPresentationControllerShouldDismissPopover
  • 需要对颜色变化进行动画处理,就像在iOS中一样。
  • segmentedControl的{​​{1}}也必须保存。
  • 在禁用状态下处理较浅的颜色。

这是我所做的,希望有更好的解决方案:

isEnabled