簡體   English   中英

當彈出窗口在屏幕上時,UIBarButtonItem 不會脫色/禁用

[英]UIBarButtonItem not decolorized/disabled when popover is on screen

我的導航控制器上有兩個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行為正常:脫色且不可點擊。

我在這里缺少什么?

查看您的代碼,一切似乎都很好。 操作系統中似乎存在錯誤。

我找到了一個快速解決方案,除非他們在下一個 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 ,以重置popoverPresentationControllerDidDismissPopover的顏色並啟用 segmentedItem。

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

希望能幫助到你。

正如Bhavin Kansagara所說,模仿 iOS 行為是一種有效的解決方法。 他的回答很接近,但遺漏了一些細節:

  • popoverPresentationControllerDidDismissPopover調用太晚導致分段控件在所有其他 UI 元素之后再次popoverPresentationControllerDidDismissPopover藍色。 需要使用popoverPresentationControllerShouldDismissPopover代替。
  • 顏色變化需要動畫化,就像在 iOS 中一樣。
  • segmentedControlisEnabled也必須保存。
  • 在禁用狀態下處理較淺的顏色。

這是我所做的,希望有更好的解決方案:

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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM