iOS9 弹出框总是指向锚点的左上角
iOS9 popover always points to top-left corner of anchor
我正在使用将视图控制器呈现为弹出窗口的故事板转场。 seque 有一个自定义 UIView
作为它的锚点。在 iOS9 之前,弹出窗口将正确指向自定义 UIView
的中心底部(显示在 UIView 下方)。在 iOS9 上它指向 UIView
.
的左上角
我确实尝试跟踪对自定义 UIView
的所有选择器调用,以查明是否有任何我可能需要在我的自定义 UIView
中实现以提供 'hotspot'弹出窗口但找不到任何内容
有什么想法..?谢谢
感谢@Igor Camilo 的回复 - 如果它对某些人有用,这就是我在代码中修复此问题的方法:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIPopoverPresentationController* possiblePopOver = segue.destinationViewController.popoverPresentationController;
if (possiblePopOver != nil) {
//
// iOS9 -- ensure correct sourceRect
//
possiblePopOver.sourceRect = possiblePopOver.sourceView.bounds;
}
...
}
示例: 'Short'按钮触发弹窗,弹窗指向'Sort'控件的左上角
我遇到了完全相同的问题。我只是通过在 prepareForSegue:
中设置 sourceRect 来解决它
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segue.identifier {
case "Popover Identifier"?:
if #available(iOS 9.0, *) {
segue.destinationViewController?.popoverPresentationController?.sourceRect = anchorView.bounds
}
default:
break
}
}
这是 Objective-C 中 Igor Camilo 的片段示例。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// If the sender is a UIView, we might have to correct the sourceRect of
// a potential popover being presented due to an iOS 9 bug. See:
// https://openradar.appspot.com/22095792 and
if ([sender isKindOfClass:UIView.class]) {
// Fetch the destination view controller
UIViewController *destinationViewController = [segue destinationViewController];
// If there is indeed a UIPopoverPresentationController involved
if ([destinationViewController respondsToSelector:@selector(popoverPresentationController)]) {
// Fetch the popover presentation controller
UIPopoverPresentationController *popoverPresentationController =
destinationViewController.popoverPresentationController;
// Set the correct sourceRect given the sender's bounds
popoverPresentationController.sourceRect = ((UIView *)sender).bounds;
}
}
}
有同样的问题,但我的应用程序有大量弹出窗口,所以我创建了一个集中函数来修复(但仍然必须在每个有弹出窗口的视图控制器上使用它)。
// Fix for IOS 9 pop-over arrow anchor bug
// ---------------------------------------
// - IOS9 points pop-over arrows on the top left corner of the anchor view
// - It seems that the popover controller's sourceRect is not being set
// so, if it is empty CGRect(0,0,0,0), we simply set it to the source view's bounds
// which produces the same result as the IOS8 behaviour.
// - This method is to be called in the prepareForSegue method override of all
// view controllers that use a PopOver segue
//
// example use:
//
// override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
// {
// fixIOS9PopOverAnchor(segue)
// }
//
extension UIViewController
{
func fixIOS9PopOverAnchor(segue:UIStoryboardSegue?)
{
guard #available(iOS 9.0, *) else { return }
if let popOver = segue?.destinationViewController.popoverPresentationController,
let anchor = popOver.sourceView
where popOver.sourceRect == CGRect()
&& segue!.sourceViewController === self
{ popOver.sourceRect = anchor.bounds }
}
}
这是我的解决方案,在 prepareForSegue
:
segue.destinationViewController.popoverPresentationController?.sourceRect = CGRectMake(anchorView.frame.size.width/2, anchorView.frame.size.height, 0, 0)
这会将指针移动到锚视图的底部中间
如果您在主 UIViewController
中引用弹出窗口 UIViewController
,您可以调整 sourceRect
属性 以抵消弹出窗口。例如,给定 popover popoverVC
你可以这样做:
float xOffset = 10.0;
float yOffset = 5.0;
popoverVC.popoverPresentationController.sourceRect = CGMakeRect(xOffset, yOffset, 0.0, 0.0);
我也遇到了这个问题,但现在当我将它添加到我的 PrepareForSegue 函数时它可以正常工作了。鉴于我的 Segue ID 包含字符串 Popover
if ([[segue identifier] containsString:@"Popover"]) {
[segue destinationViewController].popoverPresentationController.sourceRect = self.navigationItem.titleView.bounds;
}
尝试设置源矩形(UIView 或 UIBarButtonItem)的宽度和高度锚点并将其设置为活动状态。在初始化 UIView 或 UIBarButtonItem 时设置它。
UIBarButtonItem
[[youruibarbuttonitem.customView.widthAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.width] setActive:YES];
[[youruibarbuttonitem.customView.heightAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.height] setActive:YES];
UIView
[[uiview.widthAnchor constraintEqualToConstant:uiview.bounds.size.width] setActive:YES];
[[uiview.heightAnchor constraintEqualToConstant:uiview.bounds.size.height] setActive:YES];
Swift 3 的一些更新的答案!原谅所有选角
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popSegue" {
let popoverViewController = segue.destination
popoverViewController.popoverPresentationController?.delegate = self
segue.destination.popoverPresentationController?.sourceRect = ((sender as? UIButton)?.bounds)!
}
}
只是更新到一个实际的示例,其中包含适用于任何 UIView 的工作代码
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "PopoverSegueId"?:
if #available(iOS 9.0, *) {
segue.destination.popoverPresentationController?.sourceRect = (segue.destination.popoverPresentationController?.sourceView?.bounds)!
}
default:
break
}
}
我正在使用将视图控制器呈现为弹出窗口的故事板转场。 seque 有一个自定义 UIView
作为它的锚点。在 iOS9 之前,弹出窗口将正确指向自定义 UIView
的中心底部(显示在 UIView 下方)。在 iOS9 上它指向 UIView
.
我确实尝试跟踪对自定义 UIView
的所有选择器调用,以查明是否有任何我可能需要在我的自定义 UIView
中实现以提供 'hotspot'弹出窗口但找不到任何内容
有什么想法..?谢谢
感谢@Igor Camilo 的回复 - 如果它对某些人有用,这就是我在代码中修复此问题的方法:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIPopoverPresentationController* possiblePopOver = segue.destinationViewController.popoverPresentationController;
if (possiblePopOver != nil) {
//
// iOS9 -- ensure correct sourceRect
//
possiblePopOver.sourceRect = possiblePopOver.sourceView.bounds;
}
...
}
示例: 'Short'按钮触发弹窗,弹窗指向'Sort'控件的左上角
我遇到了完全相同的问题。我只是通过在 prepareForSegue:
中设置 sourceRect 来解决它override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segue.identifier {
case "Popover Identifier"?:
if #available(iOS 9.0, *) {
segue.destinationViewController?.popoverPresentationController?.sourceRect = anchorView.bounds
}
default:
break
}
}
这是 Objective-C 中 Igor Camilo 的片段示例。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// If the sender is a UIView, we might have to correct the sourceRect of
// a potential popover being presented due to an iOS 9 bug. See:
// https://openradar.appspot.com/22095792 and
if ([sender isKindOfClass:UIView.class]) {
// Fetch the destination view controller
UIViewController *destinationViewController = [segue destinationViewController];
// If there is indeed a UIPopoverPresentationController involved
if ([destinationViewController respondsToSelector:@selector(popoverPresentationController)]) {
// Fetch the popover presentation controller
UIPopoverPresentationController *popoverPresentationController =
destinationViewController.popoverPresentationController;
// Set the correct sourceRect given the sender's bounds
popoverPresentationController.sourceRect = ((UIView *)sender).bounds;
}
}
}
有同样的问题,但我的应用程序有大量弹出窗口,所以我创建了一个集中函数来修复(但仍然必须在每个有弹出窗口的视图控制器上使用它)。
// Fix for IOS 9 pop-over arrow anchor bug
// ---------------------------------------
// - IOS9 points pop-over arrows on the top left corner of the anchor view
// - It seems that the popover controller's sourceRect is not being set
// so, if it is empty CGRect(0,0,0,0), we simply set it to the source view's bounds
// which produces the same result as the IOS8 behaviour.
// - This method is to be called in the prepareForSegue method override of all
// view controllers that use a PopOver segue
//
// example use:
//
// override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
// {
// fixIOS9PopOverAnchor(segue)
// }
//
extension UIViewController
{
func fixIOS9PopOverAnchor(segue:UIStoryboardSegue?)
{
guard #available(iOS 9.0, *) else { return }
if let popOver = segue?.destinationViewController.popoverPresentationController,
let anchor = popOver.sourceView
where popOver.sourceRect == CGRect()
&& segue!.sourceViewController === self
{ popOver.sourceRect = anchor.bounds }
}
}
这是我的解决方案,在 prepareForSegue
:
segue.destinationViewController.popoverPresentationController?.sourceRect = CGRectMake(anchorView.frame.size.width/2, anchorView.frame.size.height, 0, 0)
这会将指针移动到锚视图的底部中间
如果您在主 UIViewController
中引用弹出窗口 UIViewController
,您可以调整 sourceRect
属性 以抵消弹出窗口。例如,给定 popover popoverVC
你可以这样做:
float xOffset = 10.0;
float yOffset = 5.0;
popoverVC.popoverPresentationController.sourceRect = CGMakeRect(xOffset, yOffset, 0.0, 0.0);
我也遇到了这个问题,但现在当我将它添加到我的 PrepareForSegue 函数时它可以正常工作了。鉴于我的 Segue ID 包含字符串 Popover
if ([[segue identifier] containsString:@"Popover"]) {
[segue destinationViewController].popoverPresentationController.sourceRect = self.navigationItem.titleView.bounds;
}
尝试设置源矩形(UIView 或 UIBarButtonItem)的宽度和高度锚点并将其设置为活动状态。在初始化 UIView 或 UIBarButtonItem 时设置它。
UIBarButtonItem
[[youruibarbuttonitem.customView.widthAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.width] setActive:YES];
[[youruibarbuttonitem.customView.heightAnchor constraintEqualToConstant:youruibarbuttonitem.customView.bounds.size.height] setActive:YES];
UIView
[[uiview.widthAnchor constraintEqualToConstant:uiview.bounds.size.width] setActive:YES];
[[uiview.heightAnchor constraintEqualToConstant:uiview.bounds.size.height] setActive:YES];
Swift 3 的一些更新的答案!原谅所有选角
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popSegue" {
let popoverViewController = segue.destination
popoverViewController.popoverPresentationController?.delegate = self
segue.destination.popoverPresentationController?.sourceRect = ((sender as? UIButton)?.bounds)!
}
}
只是更新到一个实际的示例,其中包含适用于任何 UIView 的工作代码
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier {
case "PopoverSegueId"?:
if #available(iOS 9.0, *) {
segue.destination.popoverPresentationController?.sourceRect = (segue.destination.popoverPresentationController?.sourceView?.bounds)!
}
default:
break
}
}