16

I've used this good tutorial to create a custom UIPopoverBackgroundView class.

It works well. The only problem is that I am not getting the typical UIPopoverController drop shadow and I want it. I've tried specifying it on the layer of my UIPopoverBackgroundView instance without success. My instance of UIPopoverController doesn't seem to have a public view to manipulate. Adding it to the popover content also doesn't work.

Probably really simple: how do I add a drop shadow when using a custom UIPopoverBackgroundView class?

// UIPopoverBackgroundView.m

-(id)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        _borderImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"bg-popover.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(CAP_INSET,CAP_INSET,CAP_INSET,CAP_INSET)]];

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

        [self addSubview:_borderImageView];
        [self addSubview:_arrowView];

        self.layer.shadowOffset = CGSizeMake(50, 50);
        self.layer.shadowColor = [[UIColor blackColor] CGColor];
    }

    return self;
}
spring
  • 18,009
  • 15
  • 80
  • 160

2 Answers2

19

You don't need to add your own shadows. The base UIPopoverBackgroundView will do it for you. Just make sure to call super in your layoutSubviews implementation.

EDIT: My comment applies to apps targeting iOS 6.

Mike Bernardo
  • 440
  • 5
  • 13
  • +1 True. I came here after being surprised that my custom popover started dropping shadows after running it on iOS 6 – Mazyod Oct 07 '12 at 13:36
  • Thanks for adding the update @ iOS6 - I had gone back to check under iOS5 after seeing your comment and calling super on `layoutSubviews` did not add the shadow. – spring Oct 08 '12 at 05:28
  • I'm in iOS 6 and my UIPopoverBackgroundView is not showing the shadow :( – Natan R. Dec 05 '12 at 08:31
  • I'm in iOS 6 and my UIPopoverBackgroundView is showing the shadow ... though I don't want it to :) – Toncean Cosmin Jun 12 '13 at 16:24
  • Any idea how/where to *remove* the default shadow in a custom `UIPopoverBackgroundView` implementation? – devios1 Sep 03 '13 at 21:34
  • 3
    @chaiguy To remove the default shadow, override `-(void)layoutSubviews` and leave it empty. – Jonathan Dumaine Sep 12 '13 at 18:20
14

Ok, figured it out. I needed to add the drop shadow to the borderImageView, not the view of the popover instance.

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        _borderImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"bg-popover.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(CAP_INSET,CAP_INSET,CAP_INSET,CAP_INSET)]];

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

        [self addSubview:_borderImageView];
        [self addSubview:_arrowView];

        _borderImageView.layer.cornerRadius = 5.0f;
        _borderImageView.layer.masksToBounds = NO;
        _borderImageView.layer.borderWidth = 1.0f;
        _borderImageView.layer.borderColor = [UIColor blackColor].CGColor;

        _borderImageView.layer.shadowColor = [UIColor blackColor].CGColor;
        _borderImageView.layer.shadowOpacity = 0.8;
        _borderImageView.layer.shadowRadius = 50;
        _borderImageView.layer.shadowOffset = CGSizeMake(-10.0f, 10.0f);
    }

    return self;
}
spring
  • 18,009
  • 15
  • 80
  • 160
  • 2
    Just thought I'd add that this worked for me, but I had performance issues. Rasterizing the background layer helped immensely: 'backgroundImageView.layer.shouldRasterize = YES;' – Maurizio Jul 04 '12 at 16:26
  • Interesting - I didn't notice any significant lag (on iPad 2) but good to know. – spring Jul 04 '12 at 16:33
  • 1
    Anyone reading this answer, **Do what @Maurizio said!**. Performance is not just improved, but all the performance issues caused by adding a shadow are diminished when `shouldRasterize` is set to `YES`! – Mazyod Oct 07 '12 at 15:15