在旋转屏幕后,我无法使弹出窗口保持相同的位置。有没有好的方法来做到这一点,因为仅仅设置一些frame对于弹出窗口在旋转后的效果很差。popover.frame = CGRectMake(someFrame);
在屏幕中心的位置弹出窗口看起来还不错。
在旋转屏幕后,我无法使弹出窗口保持相同的位置。有没有好的方法来做到这一点,因为仅仅设置一些frame对于弹出窗口在旋转后的效果很差。popover.frame = CGRectMake(someFrame);
在屏幕中心的位置弹出窗口看起来还不错。
苹果公司就此问题进行了问答,您可以在此处找到详细信息:
Technical Q&A QA1694 Handling Popover Controllers During Orientation Changes
基本上,该技术解释了在您的视图控制器的didRotateFromInterfaceOrientation
方法中,您将再次呈现弹出窗口的方法:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[aPopover presentPopoverFromRect:targetRect.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
想了解更多信息,请阅读上面的文章以及UIPopoverController类参考:
如果用户在弹出窗口可见时旋转设备,则弹出窗口控制器会隐藏弹出窗口,然后在旋转结束时再次显示它。弹出窗口控制器尝试为您适当地定位弹出窗口,但在某些情况下,您可能需要重新呈现它或完全隐藏它。例如,当从一个栏按钮项中显示时,弹出窗口控制器会自动调整弹出窗口的位置(以及可能的大小),以考虑栏按钮项位置的更改。但是,如果您在旋转期间删除了栏按钮项,或者如果您从视图中的目标矩形呈现了弹出窗口,则弹出窗口控制器不会尝试重新定位弹出窗口。在这些情况下,您必须手动隐藏弹出窗口或从一个适当的新位置再次呈现它。您可以在用于呈现弹出窗口的视图控制器的didRotateFromInterfaceOrientation:方法中执行此操作。
iOS 8.0.2版本之后,willRotateToInterfaceOrientation将不再起作用。正如mhrrt所提到的,您需要使用委托方法:
- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
例如,如果您希望您的弹出窗口直接出现在按下的按钮下方,则可以使用以下代码:
- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
{
CGRect rectInView = [self.theButton convertRect:self.theButton.frame toView:self.view];
*rect = CGRectMake(CGRectGetMidX(rectInView), CGRectGetMaxY(rectInView), 1, 1);
*view = self.view;
}
- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
方法来重新定位你的UIPopoverController视图,在界面方向改变时。UIPopoverControllerDelegate
文档。您可以在显示弹出窗口的视图控制器的didRotateFromInterfaceOrientation:
方法中完成此操作。
使用setPopoverContentSize:animated:
方法设置弹出窗口的大小。
针对 Swift:
func popoverPresentationController(_ popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverTo rect: UnsafeMutablePointer<CGRect>, in view: AutoreleasingUnsafeMutablePointer<UIView>)
{
rect.pointee = CGRect(x: self.view.frame.size.width, y: 0, width: 1, height: 1) // Set new rect here
}
UIPopoverController
在iOS9中被弃用,推荐使用iOS8中引入的UIPopoverPresentationController。(我也曾经从UIActionSheet
过渡到UIAlertController
。)你有两个选择(下面是obj-C示例):
A. 实现下面的UIViewController
方法(UIKit在改变呈现视图控制器视图大小之前调用此方法)。
- (void)viewWillTransitionToSize:(CGSize)size
withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:nil
completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
// Fix up popover placement if necessary, *after* the transition.
// Be careful here if a subclass also overrides this method.
if (self.presentedViewController) {
UIPopoverPresentationController *presentationController =
[self.presentedViewController popoverPresentationController];
UIView *selectedView = /** YOUR VIEW */;
presentationController.sourceView = selectedView.superview;
presentationController.sourceRect = selectedView.frame;
}
}];
}
B. 或者,当配置你的UIPopoverPresentationController
进行演示时,还可以设置它的代理。例如,您的展示VC可以实现UIPopoverPresentationControllerDelegate
并将自己分配为代理。然后实现代理方法:
- (void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView * _Nonnull *)view {
UIView *selectedView = /** YOUR VIEW */;
// Update where the arrow pops out of in the view you selected.
*view = selectedView;
*rect = selectedView.bounds;
}
我尝试过仅设置新矩形(rect.initialize(...)),它可以工作。
func popoverPresentationController(popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverToRect rect: UnsafeMutablePointer<CGRect>, inView view: AutoreleasingUnsafeMutablePointer<UIView?>) {
if popoverPresentationController.presentedViewController.view.tag == Globals.PopoverTempTag
{
rect.initialize(getForPopupSourceRect())
}
}
我有类似的问题,我通过这种方式解决了它。
[myPop presentPopoverFromRect:myfield.frame inView:myscrollview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
其中myfield
是您想要显示弹出窗口的框架,而myscrollview
是您将弹出窗口作为子视图添加到其中的容器视图(在我的情况下,它是我的滚动视图,而不是将inView:self.view
放入其中,我使用inView:myscrollview
)。
Initialize PopOver Controller
var popoverContent: PopoverContentViewController?
Write Defination for PopOver Controller
popoverContent = self.storyboard?.instantiateViewController(withIdentifier: "PopoverContentViewController") as? PopoverContentViewController
popoverContent?.modalPresentationStyle = .popover
let popover = popoverContent?.popoverPresentationController!
popover?.delegate = self
popoverContent?.preQuestionInfoPopUpViewDelegateObject = self
popover?.permittedArrowDirections = UIPopoverArrowDirection()
popover?.sourceView = self.view
popover?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 330, height: 330)
Present PopOver Controller
self.present(popoverContent, animated: true, completion:nil)
Write below method and assign new size to popover:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { let popover = popoverContent?.popoverPresentationController! popover?.sourceRect = CGRect(x: size.width/2, y: size.height/2, width: 0, height: 0) }
我有一个popoverPresentationController,我在一个带有“假”导航栏的视图上呈现它。因此,我无法将popoverPresentationController附加到barButtonItem上。我的弹出窗口出现在正确的位置,但在屏幕旋转时不会出现。
因此,由于某种原因,popoverPresentationController(_ popoverPresentationController:UIPopoverPresentationController,willRepositionPopoverTo rect:UnsafeMutablePointer<CGRect>,in view:AutoreleasingUnsafeMutablePointer<UIView>)
没有为我调用。
为了解决这个问题(iOS 12,Swift 4.2),我在调用present时添加了弹出窗口完成闭包中的约束。现在我的弹出窗口停留在我期望的位置。
present(viewController, animated: true) { [weak self] in
DDLogDebug(String(describing: viewController.view.frame))
if let containerView = viewController.popoverPresentationController?.containerView,
let presentedView = viewController.popoverPresentationController?.presentedView,
let imageView = self?.headerView.settingsButton {
withExtendedLifetime(self) {
let deltaY:CGFloat = presentedView.frame.origin.y - imageView.frame.maxY
let topConstraint = NSLayoutConstraint.init(item: presentedView, attribute: .top, relatedBy: .equal, toItem: imageView.imageView, attribute: .bottom, multiplier: 1, constant: deltaY)
topConstraint?.priority = UILayoutPriority(rawValue: 999)
topConstraint?.isActive = true
let heightContraint = NSLayoutConstraint.init(item: presentedView, attribute: .height, relatedBy: .equal, toItem: containerView, attribute: .height, multiplier: 0.75, constant: -deltaY)
heightContraint?.isActive = true
let leftConstraint = NSLayoutConstraint.init(item: presentedView, attribute: .left, relatedBy: .equal, toItem: containerView, attribute: .left, multiplier: 1, constant: presentedView.frame.origin.x)
leftConstraint.isActive = true
let widthConstraint = NSLayoutConstraint.init(item: presentedView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: presentedView.frame.width)
widthConstraint.isActive = true
presentedView.translatesAutoresizingMaskIntoConstraints = false
}
}
}