弹出框控件背景颜色奇怪的行为

Posted

技术标签:

【中文标题】弹出框控件背景颜色奇怪的行为【英文标题】:Popover Control Background Color Odd Behavior 【发布时间】:2014-05-12 18:43:11 【问题描述】:

所以在我的应用程序中,我有一个带有嵌入式导航控件的弹出框控件。在导航堆栈的不同部分,我希望弹出框根据用户所在的位置呈现不同的颜色。奇怪的是,有时设置弹出框的背景颜色会使这个看起来很糟糕的框出现在它周围,有时却不会。它看起来像这样:

这是我想要得到的样子:

似乎如果我在显示弹出框之前更改背景颜色,它似乎可以正常工作和过渡,但如果我在显示之前没有设置弹出框颜色,然后在显示后更改它具有框效果.我还注意到它似乎是随机发生的其他情况,但我无法真正解释是什么原因造成的(我的真实应用程序比这个演示复杂得多)。以下是相关代码:

- (IBAction)buttonPressed:(id)sender 
    UIViewController *vc = [[UIViewController alloc] init];
    UIButton *b = [[UIButton alloc] init];
    [b addTarget:self action:@selector(innerButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [b setTitle:@"Button" forState:UIControlStateNormal];
    [b setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [b setFrame:CGRectMake(0,0,100,100)];
    [vc.view addSubview:b];
    _innerNav = [[UINavigationController alloc] initWithRootViewController:vc];
    _popOver = [[UIPopoverController alloc] initWithContentViewController:_innerNav];

    //If this line is here, everything works fine
    _popOver.backgroundColor = [UIColor yellowColor];

    [_popOver presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];

    //If this line is here (and the above line is commented out), the transition will look wrong
    //_popOver.backgroundColor = [UIColor yellowColor];


-(void)innerButtonPressed 
    _controller = [[UIViewController alloc] init];
    UIButton *b = [[UIButton alloc] init];
    [b addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
    [b setTitle:@"Make Purple" forState:UIControlStateNormal];
    [b setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [b setFrame:CGRectMake(0,0,200,200)];
    [_controller.view addSubview:b];
    [_popOver setBackgroundColor:[UIColor orangeColor]];
    [_innerNav pushViewController:_controller animated:YES];


-(void)test
    _popOver.backgroundColor = [UIColor purpleColor];

知道是什么导致了这个问题吗?什么步骤可以安全地更新弹出框的背景颜色而不进入这种状态?我有一个完整的项目来展示这个问题,我认为你可以将项目附加到问题上,但显然你不能。如果有人想要它,我可能可以在某个地方托管它。

【问题讨论】:

您是否在模拟器或设备(或两者)上看到此问题? 我在模拟器和设备上都看到了这个 如果您将项目托管在某个地方,我将下载它并查看是否遇到同样的问题。我没有任何确定的想法,但我当然愿意看看你想要的。 知道最容易发布和链接的地方是什么吗? 我通常使用 GitHub 或 drobbox(带有公共链接)。 【参考方案1】:

在查看了您的示例项目、Apple 的 "Popover Controllers in ios" 示例项目、阅读了 Apple's Documentation 并尝试了一些不同的东西之后,我得出了以下观察结果:

UIPopoverController 只有在没有backgroundColor 属性的有效值的情况下才会出现这种奇怪的行为。由此我猜测,由于UIPopoverControllerbackgroundColor 属性默认为nil,因此它必须使用与backgroundColor 属性有效时不同的绘图代码。 触发某种重绘(例如设置popoverContentSize)将使彩色框覆盖消失(看起来像是剪掉了颜色层)。

结论:目前我会在UIPopoverController 出现之前设置一个backgroundColor,然后根据需要进行更新。如果这不是一个选项,请尝试更新UIPopoverController 使其重绘(注意:我无法让它看起来不错,而且看起来很老套)。最后,我会report it as a bug 给苹果。

我希望这会有所帮助。

【讨论】:

有趣的是,将其设置为 nil 会产生霜玻璃外观,这是我在某些过渡时想要的,并在其他过渡时设置了背景颜色,但可能在更改时调用 LayoutIfNeeded 可能就是我的全部需要做的 我试过layoutIfNeeded,但是没有用。由于UIPopoverController 是NSObject 而不是UIView,它不能调用layoutIfNeeded(或其他类似的视图方法),所以我尝试在_popOver.contentViewController.view 上调用它,自然这不起作用,因为视图不是需要重绘的. 在仔细考虑您的评论后,我意识到您可以 1) 将 backgroundColor 设置为任意颜色,然后 2) 在呈现 UIPopoverController 之后立即将 backgroundColor 设置为 nil .我试过这个,一旦完成,你可以设置和nilbackgroundColor属性你想要的,并且不会发生绘制错误。同样,这不是想法,但在 Apple 修复此错误之前它可以工作。 是的,我注意到我也可以这样做,但它似乎只适用于我的演示项目而不是我的实际项目 =(。我的实际项目试图更改 willShowViewController 中的背景颜色内部导航控制器也有奇怪的结果。【参考方案2】:

UIPopoverController 现已弃用。我在更新它以使用新的 popoverPresentationController 时发现了类似的问题。过去我可以在演示之前设置 UIPopoverController 的backgroundColor。 popover 演示控制器也有一个 backgroundColor 属性,但不像以前那样工作,我可以在演示之前分配它。为了让它工作,由于某种原因,我不得不在它开始呈现后分配它:

contentViewController.modalPresentationStyle = UIModalPresentationPopover;
[[self presentViewController:contentViewController animated:YES completion:^
    // completion code
];
contentViewController.popoverPresentationController.backgroundColor = [UIColor orangeColor];

对于您在演示完成后更改背景颜色的特定场景,我认为您无法仅通过更改 popoverPresentationController 的背景颜色来做到这一点。我能想到的唯一解决方案是在没有动画的情况下关闭并重新呈现弹出框:

[self dismissViewControllerAnimated:NO completion:^

    contentViewController.modalPresentationStyle = UIModalPresentationPopover;

    [[self presentViewController:contentViewController animated:NO completion:^
        // completion code
    ];
    contentViewController.popoverPresentationController.backgroundColor = [UIColor purpleColor];

];

【讨论】:

以上是关于弹出框控件背景颜色奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章

如何使用选择属性更改 TextField 的 MUI 菜单弹出框的背景颜色?

当显示 UIPopoverController 时,如何更改背景后面的控件颜色?

iOS弹出框如何去除阴影

来自 UITabBar 的奇怪行为,其中背景颜色仅显示一个选项卡

弹出窗口出现时如何阻止标签栏项目变灰

在 SWIFT 4 中更改弹出框颜色