如何在 iOS 5 中设置最小 UIPopoverController 大小?

发布于 2024-12-14 11:31:25 字数 4302 浏览 3 评论 0原文

我正在使用 UIPopoverController 来显示我的 ContentItems 的属性。使用presentPopoverFromRect 在iOS 4.3 中一切正常。一些 ContentItem 矩形相当大,在 iOS 5 中,弹出窗口会调整自身大小以适合矩形边缘和屏幕边框之间的边距。在最坏的情况下,弹出窗口的高度低于 50 像素并覆盖导航栏。显然对用户不友好。

我重新编写了代码(下面是最新的尝试)来检测问题情况,并在 ContentItem 的中心点为弹出窗口提供一个 1 像素的矩形。尽管我仍在对某些边界情况的行为进行逆向工程,但这在大多数情况下都有效。

但我觉得我一定错过了一些东西。在 iOS 5 Beta 期间,有一些讨论需要指定弹出窗口管理的视图的大小调整蒙版 - 但我发现很难相信我所看到的行为是 Apple 的错误而不是我的错误。感谢您的建议。

- (IBAction)handleDoubleTap:(UIGestureRecognizer *)sender
{
    int subViewTag = sender.view.tag;
    DLog(@":tag = %d", subViewTag);

    NSString* key = [NSString stringWithFormat:@"%d", subViewTag];
    ContentItemView* contentItemView = [self.contentItemViewDict objectForKey:key];
    ContentItem* theContentItem = [contentItemView contentItem];

    ContentItemPropertiesViewController* contentPopover = [[[ContentItemPropertiesViewController alloc] initWithNibName:@"ContentItemPropertiesViewController"
                                                                                                             bundle:[NSBundle mainBundle]] autorelease];
    contentPopover.delegate             = self;
    contentPopover.theItem              = theContentItem;
    contentPopover.theView              = sender.view;
    [contentPopover setContentSizeForViewInPopover:/*k_contentItemPopoverSize*/ CGSizeMake(320, 344.0f)];
    UIPopoverController* popover        = [[UIPopoverController alloc] initWithContentViewController:contentPopover];
    popover.delegate                    = self;
    self.contentPopoverViewController   = popover;
    [popover setPopoverContentSize:CGSizeMake(320, 344.0f)];
    [popover release];

    // Check to see if there's room for the popover around the edges of the object
    CGRect popoverRect = [self rectForPopover:sender.view.frame];
    if (popoverRect.origin.x   == 0 && popoverRect.origin.y    == 0 &&
        popoverRect.size.width == 0 && popoverRect.size.height == 0) {
        popoverRect = sender.view.bounds;
    }
    CGRect theRect = [sender.view convertRect:popoverRect
                                   toView:self.view];
    DLog(@"popoverRect %f, %f, %f, %f", theRect.origin.x, theRect.origin.y, theRect.size.width, theRect.size.height);
    [self.contentPopoverViewController presentPopoverFromRect:theRect 
                                                   inView:self.view  
                                 permittedArrowDirections:UIPopoverArrowDirectionAny
                                                 animated:YES];    
}

- (CGRect)rectForPopover:(CGRect)viewRect
{
#define k_popoverPad            30.0f          // a little extra room for the popover     borders and arrow
    DLog();
    // Get the width and height the popover controller needs to fully display itself
    CGSize popoverSize      = k_contentItemPopoverSize;
    CGFloat popoverWidth    = popoverSize.width;
    CGFloat popoverHeight   = popoverSize.height;

    // Get the edges of the object's rect translated to sceneView's coordinates
    CGFloat leftEdge        = self.sceneView.frame.origin.x + viewRect.origin.x - k_popoverPad;
    CGFloat rightEdge       = leftEdge + viewRect.size.width + k_popoverPad;
    CGFloat topEdge         = self.sceneView.frame.origin.y + viewRect.origin.y - k_popoverPad;
    CGFloat bottomEdge      = topEdge + viewRect.size.height + k_popoverPad;

    // Get the bounds of the view
    CGFloat viewRightBound  = self.view.bounds.origin.x + self.view.bounds.size.width;
    CGFloat viewBottomBound = self.view.bounds.origin.y + self.view.bounds.size.height;

    // Compare the "margin" between the screen bounds and object's edges
    //  to see if the popover will fit somewhere
    if (leftEdge > popoverWidth                     ||  // room on the left
        topEdge  > popoverHeight                    ||  // room at the top
        viewRightBound - rightEdge > popoverWidth   ||  // room to the right
        viewBottomBound - bottomEdge > popoverHeight) { // room at the bottom
        return CGRectZero;
    } else {
        // return a rect that is (essentially) the centerpoint of the object
        CGRect newRect = CGRectMake((rightEdge - leftEdge) / 2.0f, (bottomEdge - topEdge) / 2.0f, 1.0f, 1.0f);
        return newRect;
    }
}

I am using a UIPopoverController to display properties of my ContentItems. All worked fine in iOS 4.3 using presentPopoverFromRect. Some of the ContentItem rect's are fairly large, and in iOS 5, the popover re-sizes itself to fit in the margin between the rect's edges and the screen borders. In the worst cases the popover is less than 50 pixels tall and overlays the NavigationBar. Obviously not user friendly.

I've re-written the code (latest attempt below) to detect the problem cases and give the popover a 1 pixel rect at the center point of the ContentItem. This works most of the time although I'm still reverse-engineering the behavior for some boundary cases.

However I feel I must be missing something. During the iOS 5 Beta there was some discussion of the need to specify resizing masks of the Views the popover managed - but I just find it hard to believe the behavior I'm seeing is Apple fault and not mine. Advice is appreciated.

- (IBAction)handleDoubleTap:(UIGestureRecognizer *)sender
{
    int subViewTag = sender.view.tag;
    DLog(@":tag = %d", subViewTag);

    NSString* key = [NSString stringWithFormat:@"%d", subViewTag];
    ContentItemView* contentItemView = [self.contentItemViewDict objectForKey:key];
    ContentItem* theContentItem = [contentItemView contentItem];

    ContentItemPropertiesViewController* contentPopover = [[[ContentItemPropertiesViewController alloc] initWithNibName:@"ContentItemPropertiesViewController"
                                                                                                             bundle:[NSBundle mainBundle]] autorelease];
    contentPopover.delegate             = self;
    contentPopover.theItem              = theContentItem;
    contentPopover.theView              = sender.view;
    [contentPopover setContentSizeForViewInPopover:/*k_contentItemPopoverSize*/ CGSizeMake(320, 344.0f)];
    UIPopoverController* popover        = [[UIPopoverController alloc] initWithContentViewController:contentPopover];
    popover.delegate                    = self;
    self.contentPopoverViewController   = popover;
    [popover setPopoverContentSize:CGSizeMake(320, 344.0f)];
    [popover release];

    // Check to see if there's room for the popover around the edges of the object
    CGRect popoverRect = [self rectForPopover:sender.view.frame];
    if (popoverRect.origin.x   == 0 && popoverRect.origin.y    == 0 &&
        popoverRect.size.width == 0 && popoverRect.size.height == 0) {
        popoverRect = sender.view.bounds;
    }
    CGRect theRect = [sender.view convertRect:popoverRect
                                   toView:self.view];
    DLog(@"popoverRect %f, %f, %f, %f", theRect.origin.x, theRect.origin.y, theRect.size.width, theRect.size.height);
    [self.contentPopoverViewController presentPopoverFromRect:theRect 
                                                   inView:self.view  
                                 permittedArrowDirections:UIPopoverArrowDirectionAny
                                                 animated:YES];    
}

- (CGRect)rectForPopover:(CGRect)viewRect
{
#define k_popoverPad            30.0f          // a little extra room for the popover     borders and arrow
    DLog();
    // Get the width and height the popover controller needs to fully display itself
    CGSize popoverSize      = k_contentItemPopoverSize;
    CGFloat popoverWidth    = popoverSize.width;
    CGFloat popoverHeight   = popoverSize.height;

    // Get the edges of the object's rect translated to sceneView's coordinates
    CGFloat leftEdge        = self.sceneView.frame.origin.x + viewRect.origin.x - k_popoverPad;
    CGFloat rightEdge       = leftEdge + viewRect.size.width + k_popoverPad;
    CGFloat topEdge         = self.sceneView.frame.origin.y + viewRect.origin.y - k_popoverPad;
    CGFloat bottomEdge      = topEdge + viewRect.size.height + k_popoverPad;

    // Get the bounds of the view
    CGFloat viewRightBound  = self.view.bounds.origin.x + self.view.bounds.size.width;
    CGFloat viewBottomBound = self.view.bounds.origin.y + self.view.bounds.size.height;

    // Compare the "margin" between the screen bounds and object's edges
    //  to see if the popover will fit somewhere
    if (leftEdge > popoverWidth                     ||  // room on the left
        topEdge  > popoverHeight                    ||  // room at the top
        viewRightBound - rightEdge > popoverWidth   ||  // room to the right
        viewBottomBound - bottomEdge > popoverHeight) { // room at the bottom
        return CGRectZero;
    } else {
        // return a rect that is (essentially) the centerpoint of the object
        CGRect newRect = CGRectMake((rightEdge - leftEdge) / 2.0f, (bottomEdge - topEdge) / 2.0f, 1.0f, 1.0f);
        return newRect;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文