Custom background color tint for UIPopover

Starting at 5.0 iOS supports background tinting, but a custom class implementation of UIPopoverBackgroundView is needed for that to work. Apple doesn't currently provide one.

After you've implemented your custom, here is how to do use it:

 

UIPopoverController * samplePopoverController;

samplePopoverController.popoverBackgroundViewClass = [SamplePopoverBackgroundView class];

 

 

 

 

//

//  SamplePopoverBackgroundView.h

//  poc

//

//  Created by Andrew Kolesnikov on 11/22/11.

//  Copyright (c) 2011 Isobar. All rights reserved.

//

 

#import <UIKit/UIKit.h>

#import <UIKit/UIPopoverBackgroundView.h>

 

@interface SamplePopoverBackgroundView : UIPopoverBackgroundView {

  UIImageView *_imageView;

  UIImageView *_arrowView;

}

/* The arrow offset represents how far from the center of the view the center of the arrow should appear. For `UIPopoverArrowDirectionUp` and `UIPopoverArrowDirectionDown`, this is a left-to-right offset; negative is to the left. For `UIPopoverArrowDirectionLeft` and `UIPopoverArrowDirectionRight`, this is a top-to-bottom offset; negative to toward the top.This method is called inside an animation block managed by the `UIPopoverController`.

  */

@property (nonatomic, readwrite) CGFloat arrowOffset;

/* `arrowDirection` manages which direction the popover arrow is pointing. You may be required to change the direction of the arrow while the popover is still visible on-screen.

 */

@property (nonatomic, readwrite) UIPopoverArrowDirection arrowDirection;

 

/* These methods must be overridden and the values they return may not be changed during use of the `UIPopoverBackgroundView`. `arrowHeight` represents the height of the arrow in points from its base to its tip. `arrowBase` represents the the length of the base of the arrow’s triangle in points. `contentViewInset` describes the distance between each edge of the background view and the corresponding edge of its content view (i.e. if it were strictly a rectangle). `arrowHeight` and `arrowBase` are also used for the drawing of the standard popover shadow.

 */

+ (CGFloat)arrowHeight;

+ (CGFloat)arrowBase;

+ (UIEdgeInsets)contentViewInsets;

 

@end

 

//

//  SamplePopoverBackgroundView.m

//  poc

//

//  Created by Andrew Kolesnikov on 11/22/11.

//  Copyright (c) 2011 Isobar. All rights reserved.

//

 

#import "SamplePopoverBackgroundView.h"

 

@implementation SamplePopoverBackgroundView

 

@synthesize arrowOffset, arrowDirection;

 

-(id)initWithFrame:(CGRect)frame{

  if (self = [super initWithFrame:frame]) {

    _imageView = [[[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"bg-popover.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(40.0, 10.0, 30.0, 10.0)]] autorelease];

    _arrowView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bg-popover-arrow.png"]] autorelease];

 

    self.backgroundColor =  _arrowView.backgroundColor =  _imageView.backgroundColor = [UIColor clearColor];

 

    [self addSubview:_imageView];

    [self addSubview:_arrowView];

  }

  return self;

}

 

- (void)drawRect:(CGRect)rect {

 

}

 

-(void)layoutSubviews{

 

  if (arrowDirection == UIPopoverArrowDirectionUp) {  

  _imageView.frame = CGRectMake(0, [SamplePopoverBackgroundView arrowHeight], self.superview.frame.size.width, self.superview.frame.size.height - [SamplePopoverBackgroundView arrowHeight]);

 

  _arrowView.frame = CGRectMake(self.superview.frame.size.width / 2 + arrowOffset - [SamplePopoverBackgroundView arrowBase] / 2, 2, [SamplePopoverBackgroundView arrowBase], [SamplePopoverBackgroundView arrowHeight]);

  }

 

  if (arrowDirection == UIPopoverArrowDirectionRight) {  

 

    _imageView.frame = CGRectMake(0, 0, self.superview.frame.size.width - [SamplePopoverBackgroundView arrowHeight], self.superview.frame.size.height);

 

    _arrowView.image = [[UIImage alloc] initWithCGImage: _arrowView.image.CGImage

                                                         scale: 1.0

                                                   orientation: UIImageOrientationRight];

 

 

    _arrowView.frame = CGRectMake(self.superview.frame.size.width - [SamplePopoverBackgroundView arrowHeight] - 1, self.superview.frame.size.height / 2 + arrowOffset - [SamplePopoverBackgroundView arrowBase] / 2, [SamplePopoverBackgroundView arrowHeight], [SamplePopoverBackgroundView arrowBase]);

  }

}

 

+(UIEdgeInsets)contentViewInsets{

  return UIEdgeInsetsMake(5, 5, 5, 5);

}

 

+(CGFloat)arrowHeight{

  return 21.0;

}

 

+(CGFloat)arrowBase{

  return 35.0;

}

 

@end