Ios 当屏幕上显示popover时,UIBarButtonItem未脱色/禁用

Ios 当屏幕上显示popover时,UIBarButtonItem未脱色/禁用,ios,swift,uipopovercontroller,uipopoverpresentationcontroller,Ios,Swift,Uipopovercontroller,Uipopoverpresentationcontroller,我的导航控制器上有两个uibarbuttonims: segmentControl = UISegmentedControl(items: ["Up", "Down"]) infoItem = UIBarButtonItem(image: infoImage, style: .plain, target: self,

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

    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
}
即使我将
passthroughview
设置为
nil
两次,但在弹出式按钮显示在屏幕上时,
UISegmentedControl
不会脱色并保持可点击状态

如果在
UISegmentedControl
上显示任何其他POP,则其行为正常:脱色且不可点击


我在这里遗漏了什么?

看看你的代码,一切似乎都很好。似乎操作系统中有一个bug

我已经找到了一个快速修复方法,除非他们在下一个iOS版本中检查并修复它

  • 定义barButtonItems和变量,以便在ViewController中全局保存现有的着色颜色

    var infoItem: UIBarButtonItem!
    var segmentItem: UIBarButtonItem!
    var savedTintColour: UIColor? = nil
    
  • 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]
    
  • 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)
    }
    
  • 实施委托方法
    prepareforpoverpresentation
    并将色调颜色设置为darkGray,并将以前可用的色调颜色保存为一个变量,以便在启用时可以重用该变量

    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
    }
    
  • 执行委托方法
    popoverPresentationControllerDidDismissPopover
    ,以重置segmentControl的颜色并启用segmentedItem

    func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) {
    self.segmentItem.isEnabled = true
    self.segmentedControl.tintColor = savedTintColour!
    }
    
  • 希望能有所帮助。

    正如所建议的,模仿iOS操作是一种有效的解决方法。他的回答很接近,但遗漏了一些细节:

    • 调用
      PopOverpresentationControllerdDismissPopover
      太晚,导致分段控件在所有其他UI元素之后再次变为蓝色。需要改用
      PopOverpresentationControllersAddIsmissPopOver
    • 颜色变化需要设置动画,就像在iOS中一样
    • segmentedControl
      isEnabled
      也必须保存
    • 在禁用状态下处理较浅颜色
    以下是我所做的,希望找到更好的解决方案:

    private var segmentedControlTintColor: UIColor?
    private var segmentedControlIsEnabled: Bool = true
    
    // Due to, what seems to be, an iOS issue, the segmented control is not decolorized when the info popover is
    // on screen.  The two functions below mimick iOS behavior until a better solution is found.
    func decolorizeSegmentedControl()
    {
        segmentedControlIsEnabled = segmentedControl.isEnabled
        segmentedControl.isEnabled = false
        segmentedControlTintColor = segmentedControl.tintColor
        UIView.animate(withDuration: 0.333)
        {
            self.segmentedControl.tintColor = self.segmentedControlIsEnabled ? .darkGray : .lightGray
        }
    }
    
    func colorizeSegmentedControl()
    {
        segmentedControl.isEnabled = segmentedControlIsEnabled
        UIView.animate(withDuration: 0.333)
        {
            self.segmentedControl.tintColor = self.segmentedControlTintColor
        }
    }
    
    func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController)
    {
        popoverPresentationController.permittedArrowDirections = .any
        popoverPresentationController.barButtonItem = infoItem
    
        decolorizeSegmentedControl()
    }
    
    func popoverPresentationControllerShouldDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) -> Bool
    {
        colorizeSegmentedControl()
    
        return true
    }
    

    我知道如何假装这种行为,但这正是我现在要寻找的。是的,但没有其他选择来克服这个问题。你可以假装这种行为,也可以联系苹果来解决这个问题。如果您的情况允许修改UI,您可以通过将segment控件设置为LeftBarButtonim来做更多的事情。:)正如你所说,目前还没有其他答案(我想如果没有更好的/真正的解决方案出现的话)。