To add to the other, link-only answers, here is how this is done.
- Create a new subclass of UIPopoverBackgroundView
Declare the following in your interface:
+(UIEdgeInsets)contentViewInsets;
+(CGFloat)arrowHeight;
+(CGFloat)arrowBase;
@property(nonatomic,readwrite) CGFloat arrowOffset;
@property(nonatomic,readwrite) UIPopoverArrowDirection arrowDirection;
The class methods are straightforward: contentViewInsets
returns the width of your borders all the way round (not including the arrow), arrowHeight
is the height of your arrow, arrowBase
is the base of your arrow.
- Implement the two property setters, making sure to call
[self setNeedsLayout]
.
- In your initialisation method, create two image views, one holding your arrow (which should be the size of the arrow dimensions in your class methods) and one holding your background image (which must be a resizable image) and add these as subviews. It doesn't matter where you put the subviews at this point, as you don't have an arrow direction or offset. You should make sure the arrow image view is above the background image view so it blends in properly.
- Implement
layoutSubviews
. In here, according to the arrowDirection
and arrowOffset
properties, you have to adjust the frames of your background view and arrow view.
- The frame of your background view should be
self.bounds
, inset by arrowHeight
on whatever edge the arrow is on
- The frame of the arrow view should be aligned so that the centre is
arrowOffset
away from the centre of self
(correct according to the axis). You have to change the image orientation if the arrow direction is not up, but my popover would only be up so I didn't do that.
Here is the layoutSubviews
method for my Up-only subclass:
-(void)layoutSubviews
{
if (self.arrowDirection == UIPopoverArrowDirectionUp)
{
CGFloat height = [[self class] arrowHeight];
CGFloat base = [[self class] arrowBase];
self.background.frame = CGRectMake(0, height, self.frame.size.width, self.frame.size.height - height);
self.arrow.frame = CGRectMake(self.frame.size.width * 0.5 + self.arrowOffset - base * 0.5, 1.0, base, height);
[self bringSubviewToFront:self.arrow];
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…