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