UINavigationBar 中的雪佛龙在显示弹出窗口时不会变暗
Chevron in UINavigationBar not dimmed when showing popover
当我显示弹出框时,我希望弹出框外的所有视图都变暗。当我通过 IB 创建弹出窗口时,效果很好。当我以编程方式创建弹出窗口并通过 UIBarButtonItem 调用它时,这不太有效:导航栏中的后 V 形没有变暗。相反,它保持蓝色:
代码:
class GreenViewController: UIViewController {
private var barButtonItem: UIBarButtonItem!
func barButtonItemAction() {
let blueViewController = BlueViewController()
let navigationController = UINavigationController(rootViewController: blueViewController)
navigationController.modalPresentationStyle = .popover
navigationController.popoverPresentationController?.barButtonItem = self.barButtonItem
self.present(navigationController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.barButtonItem = UIBarButtonItem(title: "Show blue popover", style: .plain, target: self, action: #selector(barButtonItemAction))
self.navigationItem.rightBarButtonItem = barButtonItem
}
}
为什么会这样?
Github 上的测试项目:
https://github.com/bvankuik/TestNavigationBarChevronTint/
我认为当 popovercontroller 使用 UIBarButtonItem 作为锚点时,视图层次结构中可能有问题。在 InterfaceBuilder 中,UIButton 是呈现的弹出窗口的锚点,并且由于 UIButton 位于呈现视图控制器的视图层次结构中,因此似乎可以正常工作。
所以我尝试通过如下设置 popoverPresentationController
上的 sourceRect
和 sourceView
属性来重现一些类似的情况,并且成功了。
class GreenViewController: UIViewController, UIPopoverPresentationControllerDelegate {
private var barButtonItem: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
barButtonItem = UIBarButtonItem(title: "Show blue popover", style: .plain,
target: self, action: #selector(barButtonItemAction))
navigationItem.rightBarButtonItem = barButtonItem
}
// Defined constants for solution readability
private let sourceRectHeight : CGFloat = 44.0 // NavigationBar Height?
private let sourceRectWidth : CGFloat = 160.0 // UIBarButtonItem Width?
private let sourceRectRightMargin : CGFloat = 20.0 // Right Margin
// This returns the source rect to align our popoverPresentationController
// against, this is pretty much my imaginary frame of the UIBarButtonItem
private var sourceRect : CGRect
{
var rect = navigationController!.navigationBar.frame
rect.origin.x = view.bounds.width - sourceRectWidth - sourceRectRightMargin
rect.origin.y = sourceRectHeight / 2.0
rect.size.width = sourceRectWidth
return rect
}
func barButtonItemAction() {
let blueViewController = BlueViewController()
let navigationController = UINavigationController(rootViewController: blueViewController)
navigationController.modalPresentationStyle = .popover
// Instead of setting the barButtonItem on the popoverPresentationController
// set the srouce view as the root view of the presenting controller
navigationController.popoverPresentationController?.sourceView = view
// Set the source rec to present from, which is calclated relative to the width
// of the current device orientation
navigationController.popoverPresentationController?.sourceRect = sourceRect
// Set self as the delegate for the popoverPresentationController because
// we need to provide a relaculated rect when the device changes orientation
navigationController.popoverPresentationController?.delegate = self
// Present the view controller, and voila :)
self.present(navigationController, animated: true, completion: nil)
}
// UIPopoverPresentationControllerDelegate method that allows us to update
// the source rect of the popover after an orientation change has occurred,
// which calculated relative to with in the sourceRect property above
public func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController,
willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>,
in view: AutoreleasingUnsafeMutablePointer<UIView>)
{
rect.initialize(to: sourceRect)
}
}
希望这对您有所帮助:)
当我显示弹出框时,我希望弹出框外的所有视图都变暗。当我通过 IB 创建弹出窗口时,效果很好。当我以编程方式创建弹出窗口并通过 UIBarButtonItem 调用它时,这不太有效:导航栏中的后 V 形没有变暗。相反,它保持蓝色:
代码:
class GreenViewController: UIViewController {
private var barButtonItem: UIBarButtonItem!
func barButtonItemAction() {
let blueViewController = BlueViewController()
let navigationController = UINavigationController(rootViewController: blueViewController)
navigationController.modalPresentationStyle = .popover
navigationController.popoverPresentationController?.barButtonItem = self.barButtonItem
self.present(navigationController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.barButtonItem = UIBarButtonItem(title: "Show blue popover", style: .plain, target: self, action: #selector(barButtonItemAction))
self.navigationItem.rightBarButtonItem = barButtonItem
}
}
为什么会这样?
Github 上的测试项目: https://github.com/bvankuik/TestNavigationBarChevronTint/
我认为当 popovercontroller 使用 UIBarButtonItem 作为锚点时,视图层次结构中可能有问题。在 InterfaceBuilder 中,UIButton 是呈现的弹出窗口的锚点,并且由于 UIButton 位于呈现视图控制器的视图层次结构中,因此似乎可以正常工作。
所以我尝试通过如下设置 popoverPresentationController
上的 sourceRect
和 sourceView
属性来重现一些类似的情况,并且成功了。
class GreenViewController: UIViewController, UIPopoverPresentationControllerDelegate {
private var barButtonItem: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
barButtonItem = UIBarButtonItem(title: "Show blue popover", style: .plain,
target: self, action: #selector(barButtonItemAction))
navigationItem.rightBarButtonItem = barButtonItem
}
// Defined constants for solution readability
private let sourceRectHeight : CGFloat = 44.0 // NavigationBar Height?
private let sourceRectWidth : CGFloat = 160.0 // UIBarButtonItem Width?
private let sourceRectRightMargin : CGFloat = 20.0 // Right Margin
// This returns the source rect to align our popoverPresentationController
// against, this is pretty much my imaginary frame of the UIBarButtonItem
private var sourceRect : CGRect
{
var rect = navigationController!.navigationBar.frame
rect.origin.x = view.bounds.width - sourceRectWidth - sourceRectRightMargin
rect.origin.y = sourceRectHeight / 2.0
rect.size.width = sourceRectWidth
return rect
}
func barButtonItemAction() {
let blueViewController = BlueViewController()
let navigationController = UINavigationController(rootViewController: blueViewController)
navigationController.modalPresentationStyle = .popover
// Instead of setting the barButtonItem on the popoverPresentationController
// set the srouce view as the root view of the presenting controller
navigationController.popoverPresentationController?.sourceView = view
// Set the source rec to present from, which is calclated relative to the width
// of the current device orientation
navigationController.popoverPresentationController?.sourceRect = sourceRect
// Set self as the delegate for the popoverPresentationController because
// we need to provide a relaculated rect when the device changes orientation
navigationController.popoverPresentationController?.delegate = self
// Present the view controller, and voila :)
self.present(navigationController, animated: true, completion: nil)
}
// UIPopoverPresentationControllerDelegate method that allows us to update
// the source rect of the popover after an orientation change has occurred,
// which calculated relative to with in the sourceRect property above
public func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController,
willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>,
in view: AutoreleasingUnsafeMutablePointer<UIView>)
{
rect.initialize(to: sourceRect)
}
}
希望这对您有所帮助:)