旋轉後,屏幕上的相同位置無法保持彈出狀態。有沒有什麼好的方法可以做到這一點,因爲在旋轉之後,設置一些框架以實現彈出效果非常可怕。 popover.frame = CGRectMake(someFrame);
旋轉彈出窗口只有在屏幕中心時纔會顯示正常。如何使UIPopoverController在旋轉後保持相同的位置?
回答
在這個問題上,Apple有一個Q & A.你可以在這裏找到細節:
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 Class Reference:
如果用戶在彈出窗口是vi時旋轉設備sible,彈出窗口 控制器隱藏彈出窗口,然後在 輪換結束時再次顯示它。彈出窗口控制器嘗試爲您適當地定位彈出窗口 ,但在某些情況下,您可能需要再次顯示或將其隱藏 。例如,當從條形圖按鈕項目 中顯示時,彈出窗口控制器會自動調整彈出窗口的位置 (以及可能的大小),以考慮對條形按鈕項目的位置進行更改( )。但是,如果在旋轉過程中刪除條形圖按鈕項 ,或者在視圖中顯示目標矩形的彈出框 ,則彈窗控制器不會嘗試 重新定位彈出窗口。在這些情況下,您必須手動隱藏彈出窗口或將其從適當的新位置再次顯示。您可以使用 在didRotateFromInterfaceOrientation中執行此操作:您用於呈現彈出窗口的視圖 控制器。
您可以在didRotateFromInterfaceOrientation:
中使用您用來呈現彈出窗口的視圖控制器的方法。
使用setPopoverContentSize:animated:
設置彈出窗口大小的方法。
這個方法是否改變了popover的起源?我不需要改變popover內容的大小,只是爲了保持原點。 – 2012-01-30 14:32:30
我有我這個
[myPop presentPopoverFromRect:myfield.frame inView:myscrollview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
哪裏myfield
是要展示你的酥料餅和myscrollview
框架解決類似的問題,是在你把你的酥料餅作爲子視圖容器視圖(在我的情況下,其我的scrollview,而不是把inView:self.view
我用inView:myscrollview
)。
我有同樣的問題。我不是每次通過跟蹤從中呈現它的源矩形/視圖來執行-presentPopoverFromRect
,而是將其分類爲UIPopoverController
。做完之後,你所要做的就是設置UIBarButtonItem/UIView來自彈出窗口的顯示位置。您甚至可以選擇顯示自定義框架中的彈出窗口,該框架可以作爲NSString值傳入。
CSPopoverController。^ h:
#import <UIKit/UIKit.h>
// The original popover controller would not re-orientate itself when the orientation change occurs. To tackle that issue, this subclass is created
@interface CSPopoverController : UIPopoverController
@property (nonatomic, strong) NSString *popoverDisplaySourceFrame; // Mutually Exclusive. If you want to set custom rect as source, make sure that popOverDisplaySource is nil
@property (nonatomic, strong) id popoverDisplaySource; // Mutually exclusive. If UIBarButtonItem is set to it, popoverDisplaySourceFrame is neglected.
@property (nonatomic, strong) UIView *popoverDisplayView;
@property (nonatomic, assign, getter = shouldAutomaticallyReorientate) BOOL automaticallyReorientate;
-(void)reorientatePopover;
@end
CSPopoverController.m:
#import "CSPopoverController.h"
@implementation CSPopoverController
@synthesize popoverDisplaySourceFrame = popoverDisplaySourceFrame_;
-(NSString*)popoverDisplaySourceFrame
{
if (nil==popoverDisplaySourceFrame_)
{
if (nil!=self.popoverDisplaySource)
{
if ([self.popoverDisplaySource isKindOfClass:[UIView class]])
{
UIView *viewSource = (UIView*)self.popoverDisplaySource;
[self setPopoverDisplaySourceFrame:NSStringFromCGRect(viewSource.frame)];
}
}
}
return popoverDisplaySourceFrame_;
}
-(void)setPopoverDisplaySourceFrame:(NSString *)inPopoverDisplaySourceFrame
{
if (inPopoverDisplaySourceFrame!=popoverDisplaySourceFrame_)
{
popoverDisplaySourceFrame_ = inPopoverDisplaySourceFrame;
[self reorientatePopover];
}
}
@synthesize popoverDisplaySource = popoverDisplaySource_;
-(void)setPopoverDisplaySource:(id)inPopoverDisplaySource
{
if (inPopoverDisplaySource!=popoverDisplaySource_)
{
[self unlistenForFrameChangeInView:popoverDisplaySource_];
popoverDisplaySource_ = inPopoverDisplaySource;
[self reorientatePopover];
if ([popoverDisplaySource_ isKindOfClass:[UIView class]])
{
UIView *viewSource = (UIView*)popoverDisplaySource_;
[self setPopoverDisplaySourceFrame:NSStringFromCGRect(viewSource.frame)];
}
if (self.shouldAutomaticallyReorientate)
{
[self listenForFrameChangeInView:popoverDisplaySource_];
}
}
}
@synthesize popoverDisplayView = popoverDisplayView_;
-(void)setPopoverDisplayView:(UIView *)inPopoverDisplayView
{
if (inPopoverDisplayView!=popoverDisplayView_)
{
popoverDisplayView_ = inPopoverDisplayView;
[self reorientatePopover];
}
}
@synthesize automaticallyReorientate = automaticallyReorientate_;
-(void)setAutomaticallyReorientate:(BOOL)inAutomaticallyReorientate
{
if (inAutomaticallyReorientate!=automaticallyReorientate_)
{
automaticallyReorientate_ = inAutomaticallyReorientate;
if (automaticallyReorientate_)
{
[self listenForAutorotation];
[self listenForFrameChangeInView:self.popoverDisplaySource];
}
else
{
[self unlistenForAutorotation];
[self unlistenForFrameChangeInView:self.popoverDisplaySource];
}
}
}
-(void)listenForAutorotation
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
-(void)unlistenForAutorotation
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
-(void)listenForFrameChangeInView:(id)inView
{
// Let's listen for changes in the view's frame and adjust the popover even if the frame is updated
if ([inView isKindOfClass:[UIView class]])
{
UIView *viewToObserve = (UIView*)inView;
[viewToObserve addObserver:self
forKeyPath:@"frame"
options:NSKeyValueObservingOptionNew
context:nil];
}
}
-(void)unlistenForFrameChangeInView:(id)inView
{
if ([inView isKindOfClass:[UIView class]])
{
UIView *viewToObserve = (UIView*)inView;
[viewToObserve removeObserver:self
forKeyPath:@"frame"];
}
}
// TODO: Dealloc is not called, check why? !!!
- (void)dealloc
{
[self unlistenForFrameChangeInView:self.popoverDisplaySource];
[self unlistenForAutorotation];
DEBUGLog(@"dealloc called for CSPopoverController %@", self);
}
#pragma mark - Designated initializers
-(id)initWithContentViewController:(UIViewController *)viewController
{
self = [super initWithContentViewController:viewController];
if (self)
{
[self popoverCommonInitializations];
}
return self;
}
-(void)popoverCommonInitializations
{
[self setAutomaticallyReorientate:YES];
}
#pragma mark - Frame
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object==self.popoverDisplaySource)
{
[self setPopoverDisplaySourceFrame:nil];
[self reorientatePopover];
}
}
#pragma mark - Orientation
-(void)orientationChanged:(NSNotification *)inNotification
{
[self reorientatePopover];
}
-(void)reorientatePopover
{
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(performReorientatePopover)
object:nil];
// if ([self isPopoverVisible])
{
[self performSelector:@selector(performReorientatePopover)
withObject:nil
afterDelay:0.0];
}
}
-(void)performReorientatePopover
{
if (self.popoverDisplaySourceFrame && self.popoverDisplayView)
{
[self presentPopoverFromRect:CGRectFromString(self.popoverDisplaySourceFrame)
inView:self.popoverDisplayView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
else if (self.popoverDisplaySource && [self.popoverDisplaySource isKindOfClass:[UIBarButtonItem class]])
{
UIBarButtonItem *barButton = (UIBarButtonItem*)self.popoverDisplaySource;
[self presentPopoverFromBarButtonItem:barButton
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
@end
用法:
如果是從正在呈現它的UIBarButtonItem:
CSPopoverController *popOverCont = [[CSPopoverController alloc]initWithContentViewController:navCont];
self.popOver = popOverCont;
[popOverCont setPopoverDisplaySource:self.settingsButtonItem];
如果從正在呈現酥料餅的一個UIView:
CSPopoverController *popOver = [[CSPopoverController alloc] initWithContentViewController:navigation];
self.iPadPopoverController = popOver;
[newDateVC setIPadPopoverController:self.iPadPopoverController];
[popOver setPopoverDisplaySource:inButton];
[popOver setPopoverDisplayView:inView];
在iOS中7,您可以使用- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
重新定位你的UIPopoverController對接口的方向變化視圖。
查看UIPopoverControllerDelegate
documentation。
謝謝,這適用於我在iOS 8 – almas 2015-03-02 19:29:10
從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;
}
對於iOS> 8約翰Strickers答案有幫助,但沒有做我想做的事情。
這是爲我工作的解決方案。 (如果你想下載一個完整的示例項目,它在這裏:https://github.com/appteur/uipopoverExample)
我創建了一個屬性來容納我想呈現的任何彈出窗口,並且還添加了一個屬性來跟蹤sourceRect,另一個用於查看我想要的按鈕彈出箭頭指向。
@property (nonatomic, weak) UIView *activePopoverBtn;
@property (nonatomic, strong) PopoverViewController *popoverVC;
@property (nonatomic, assign) CGRect sourceRect;
觸發我的彈出窗口的按鈕位於UIToolbar中。點擊時,它會運行以下創建並啓動彈出窗口的方法。
-(void) buttonAction:(id)sender event:(UIEvent*)event
{
NSLog(@"ButtonAction");
// when the button is tapped we want to display a popover, so setup all the variables needed and present it here
// get a reference to which button's view was tapped (this is to get
// the frame to update the arrow to later on rotation)
// since UIBarButtonItems don't have a 'frame' property I found this way is easy
UIView *buttonView = [[event.allTouches anyObject] view];
// set our tracker properties for when the orientation changes (handled in the viewWillTransitionToSize method above)
self.activePopoverBtn = buttonView;
self.sourceRect = buttonView.frame;
// get our size, make it adapt based on our view bounds
CGSize viewSize = self.view.bounds.size;
CGSize contentSize = CGSizeMake(viewSize.width, viewSize.height - 100.0);
// set our popover view controller property
self.popoverVC = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"PopoverVC"];
// configure using a convenience method (if you have multiple popovers this makes it faster with less code)
[self setupPopover:self.popoverVC
withSourceView:buttonView.superview // this will be the toolbar
sourceRect:self.sourceRect
contentSize:contentSize];
[self presentViewController:self.popoverVC animated:YES completion:nil];
}
在「setupPopover:withSourceView:sourceRect:contentSize方法是一個簡單的便捷方法,如果你打算顯示多個popovers和希望它們配置的相同設置popoverPresentationController屬性。它的實現如下。
// convenience method in case you want to display multiple popovers
-(void) setupPopover:(UIViewController*)popover withSourceView:(UIView*)sourceView sourceRect:(CGRect)sourceRect contentSize:(CGSize)contentSize
{
NSLog(@"\npopoverPresentationController: %@\n", popover.popoverPresentationController);
popover.modalPresentationStyle = UIModalPresentationPopover;
popover.popoverPresentationController.delegate = self;
popover.popoverPresentationController.sourceView = sourceView;
popover.popoverPresentationController.sourceRect = sourceRect;
popover.preferredContentSize = contentSize;
popover.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionDown;
popover.popoverPresentationController.backgroundColor = [UIColor whiteColor];
}
對於iOS 8及以上的viewWillTransitionToSize:withTransitionCoordinator GET就是所謂的視圖時控制器設備旋轉上。
我在呈現視圖控制器類中實現了此方法,如下所示。
// called when rotating a device
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
NSLog(@"viewWillTransitionToSize [%@]", NSStringFromCGSize(size));
// resizes popover to new size and arrow location on orientation change
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context)
{
if (self.popoverVC)
{
// get the new frame of our button (this is our new source rect)
CGRect viewframe = self.activePopoverBtn ? self.activePopoverBtn.frame : CGRectZero;
// update our popover view controller's sourceRect so the arrow will be pointed in the right place
self.popoverVC.popoverPresentationController.sourceRect = viewframe;
// update the preferred content size if we want to adapt the size of the popover to fit the new bounds
self.popoverVC.preferredContentSize = CGSizeMake(self.view.bounds.size.width -20, self.view.bounds.size.height - 100);
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
// anything you want to do when the transition completes
}];
}
我試過只是設置新的矩形(rect.initialize(...)),它的工作原理。
func popoverPresentationController(popoverPresentationController: UIPopoverPresentationController, willRepositionPopoverToRect rect: UnsafeMutablePointer<CGRect>, inView view: AutoreleasingUnsafeMutablePointer<UIView?>) {
if popoverPresentationController.presentedViewController.view.tag == Globals.PopoverTempTag
{
rect.initialize(getForPopupSourceRect())
}
}
UIPopoverController
被棄用ios9贊成UIPopoverPresentationController在iOS8上推出。 (我通過這個轉變從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;
}
斯威夫特3:
class MyClass: UIViewController, UIPopoverPresentationControllerDelegate {
...
var popover:UIPopoverPresentationController?
...
// Where you want to set the popover...
popover = YourViewController?.popoverPresentationController
popover?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
popover?.delegate = self
...
// override didRotate...
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
popover?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
}
}
'didRotate' [已棄用](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621492-didrotate)。您應該使用我在https://stackoverflow.com/a/41561021/954643中提到的兩種方法之一,例如'popoverPresentationController(_:willRepositionPopoverTo:in:)'([docs](https://developer.apple.com/documentation/uikit/uipopoverpresentationcontrollerdelegate/1622326-popoverpresentationcontroller?preferredLanguage=swift))這部分是因爲您可以更改現在屏幕的佈局不止是旋轉,比如通過ios9 +中的分屏多任務功能 – qix 2017-06-07 17:24:35
對於斯威夫特:
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
}
- 1. UITextView保持旋轉的文本位置
- 2. 如何在保持其位置的同時在pygame中旋轉圖像?
- 3. 旋轉並保持當前位置
- 4. 旋轉屏幕時如何保持相同的間距? (Autolayout)
- 5. 更新後DataGrid保持在相同滾動位置的方法?
- 6. 保持文字相同的位置
- 7. 使用CSS轉換父級移動後保持子位置相同
- 8. 在任何旋轉中都保持位置
- 9. nginx轉發後保持域相同嗎?
- 10. 如何保持2個固定div的相同位置?
- 11. 如何替換matplotlib圖例並保持相同的位置?
- 12. CSS3轉換保持重置旋轉
- 13. 旋轉後在節點上的位置
- 14. 復位位置相對於旋轉
- 15. 保持的CALayer的大小/位置上的UIView旋轉
- 16. 旋轉位並保持其大小
- 17. 旋轉UIView並保持旋轉後的寬高比
- 18. 如何在旋轉後恢復我在CoordinatorLayout中的位置?
- 19. 通過屏幕旋轉保持GridView的滾動位置
- 20. 旋轉ticklabels同時保持信水平
- 21. 在xna中旋轉後保存骨骼位置
- 22. 保持內部div總是在外部div的相同位置
- 23. 保持相對位置在MultiScaleImage
- 24. 如何旋轉MapView,同時保持標籤和標記(疊加層)不旋轉?
- 25. 如何在當前位置旋轉CALayer?
- 26. 如何強制下載的文件保持在陣列中的相同位置?
- 27. 屏幕旋轉時保持圖片位置
- 28. :懸停旋轉CSS保持位置發現
- 29. 自動旋轉UIPopOverController問題
- 30. 旋轉UIView後檢查UIButton的位置
只是檢查這個環節也.. http://stackoverflow.com/ questions/3670981/adjust-uipopovercontroller-position-after-resize – 2012-01-30 14:24:25
Thanks for:presentPopoverFromRect:inView可用於popover可見時 – 2012-01-30 15:56:10