UIBarButtonItem не обесцвечивается / отключается, когда всплывающее окно на экране - PullRequest
0 голосов
/ 20 октября 2018

У меня есть два 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 голосов
/ 21 октября 2018

Как предполагает Бхаван Кансагара , имитация поведения iOS - это верный обходной путь.Его ответ был близким, но он упустил несколько деталей:

  • popoverPresentationControllerDidDismissPopover вызывается слишком поздно, в результате чего сегментированный элемент управления снова становится синим после всех других элементов пользовательского интерфейса.Вместо этого нужно использовать popoverPresentationControllerShouldDismissPopover.
  • Изменения цвета должны быть анимированными, как в 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
}
0 голосов
/ 20 октября 2018

Глядя на ваш код, кажется, все в порядке.Кажется, в ОС есть ошибка.

Я нашел быстрое решение для этой проблемы, если только они не проверят и не исправят ее в следующем выпуске 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, чтобы сбросить цвет вашегоgroControl и Включить segmentedItem.

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

Надеюсь, это поможет.

...