Using UIPopoverBackgroundView class

泪湿孤枕 提交于 2019-11-29 03:59:15

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];

    }
}

Another link only answer, but customising UIPopoverBackgroundView is more work than you might realise given the limited documentation available and this github project has a complete working example which saved me a lot of time: https://github.com/GiK/GIKPopoverBackgroundView

It's fairly straightforward to drop into your own project. The most fiddly part is adapting the cap insets for whatever custom images you're using. I'd recommend doing your customisations in-situ in the project and as it's easy to verify all the popover orientation/direction use cases display correctly in the simulator before migrating it into your own project.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!