Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIPopoverController backgroundColor causing flash when shown

I'm using the new (in iOS 7) UIPopoverController.backgroundColor setting in my app to change the color of my popovers as needed, but I'm finding that using this setting is causing a "flash" of color change whenever I open my popovers -- in about half a second it starts from the default of translucent white and fades to the color I choose. This is not desired; it should just be the color I set it to when I open it.

The documentation states:

Use this property to customize the background color of your popover. Changing the value of this property while the popover is visible triggers an animated changeover to the new color. The default value of this property is nil, which corresponds to the default background color.

However, even if I set it when my app opens and don't set it again, it will still flash each time I open any of the popovers.

I'm open to using UIPopoverBackgroundView, but I'm not sure that it allows me to change the background color on-the-fly since it seems to be a static solution for just changing the style of all popovers in an app. Thanks in advance for any suggestions.

Edit (The Code):

When my main view controller is loaded and preparing the rest of the UI (this is one of many popover inits):

fileOptionsController = [[FileOptionsViewController alloc] initWithNibName:@"FileOptionsViewController" bundle:nil];
fileOptionsController.delegate = self;

self.fileOptionsPopoverController = [[UIPopoverController alloc] initWithContentViewController:fileOptionsController];
[popoverControllers addObject:self.fileOptionsPopoverController];

After my popovers are initialized, I'm running this (still in the main init code) for the purpose of testing with a long delay between setting backgroundColor and the interaction (note: changing the alpha has no effect, still happens when set to 1):

for (UIPopoverController *po in popoverControllers) {
    [po setBackgroundColor:[UIColor colorWithWhite:0.3f alpha:0.90f]];
}

Then, this is called when the user taps a button to show the popover:

- (void)showPopover:(UIPopoverController *)popover from:(UIButton *)btn {
    [popover presentPopoverFromRect:CGRectMake(btn.frame.origin.x + 5.0f, btn.frame.origin.y - 1.0f, btn.frame.size.width, btn.frame.size.height) inView:btn.superview permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}

Pretty straight forward. These are the only relevant places where this or any popover is accessed, except where to dismiss it if it's already showing.

like image 605
Mark Avatar asked Sep 22 '13 17:09

Mark


2 Answers

I solved this issue dismissing the popover before changing the backgroundColor and then presenting it again:

[popover dismissPopoverAnimated:NO];

if ([popover respondsToSelector:@selector(backgroundColor)]) {
    popover.backgroundColor = [UIColor someColor];         
}

[popover setContentViewController:viewController animated:NO];
[popover setPopoverContentSize:CGSizeMake(320.0f, 480.0f) animated:NO];

[popover presentPopoverFromRect:popoverRect
                         inView:self.view
       permittedArrowDirections:UIPopoverArrowDirectionRight
                       animated:NO];

Doing so the popover is shown again and you won't see any unwanted transition effect.

like image 144
Giuseppe Garassino Avatar answered Oct 16 '22 10:10

Giuseppe Garassino


Since the documentation says that the backgroundColor will animate it your color so this seems be causing this flash/animation (Apple should have given setBackgroundColor with/without animation).

If you can afford to present the popover without animation, I would suggest you could try to turn off animation when you present it. Like one of these two -

Option 1 -

// last parameter as 'NO'
[popover presentPopoverFromRect:CGRectMake(btn.frame.origin.x + 5.0f, btn.frame.origin.y - 1.0f, btn.frame.size.width, btn.frame.size.height) inView:btn.superview permittedArrowDirections:UIPopoverArrowDirectionLeft animated:NO]; // Don't animate to present

Option 2 - (use setAnimationsEnabled method of UIView to turn off animation temporarily)

- (void)showPopover:(UIPopoverController *)popover from:(UIButton *)btn {
    [UIView setAnimationsEnabled:NO];   // Turn off animation

    [popover presentPopoverFromRect:CGRectMake(btn.frame.origin.x + 5.0f, btn.frame.origin.y - 1.0f, btn.frame.size.width, btn.frame.size.height) inView:btn.superview permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];

    [UIView setAnimationsEnabled:YES];   // Turn back on
}

Logically this should work unless Apple is further hacking this property inside it's sdk.

like image 42
Ashok Avatar answered Oct 16 '22 08:10

Ashok