自定义UIView一个弹出菜单

需求

封装一个自定义的弹出菜单,有背景图片,里面也可以放置UIView,点击外部会使菜单消失


头文件设计思路

定义协议和可选的方法,用来传递点击菜单区域以外的事件

初始化方法中,需要一个contentView,放在菜单的内部,菜单的frame由- (void)showInRect:(CGRect)rect;中传递的rect参数决定

在- (id)initWithFrame:(CGRect)frame;中添加2个属性,一个是container是一个UIImageView,默认会带有一个背景图片,cover是接收container以外区域的点击事件的一个UIButton


在外部调用时,可以在contentView中加上特定的点击事件

   // 弹出菜单
    UIButton *button = [UIButton buttonWithType:UIButtonTypeContactAdd];
    [button addTarget:self action:@selector(clickOnButton) forControlEvents:UIControlEventTouchUpInside];
    button.backgroundColor = [UIColor redColor];
    
    HMPopMenu *menu = [[HMPopMenu alloc ] initWithContentView:button];
    menu.delegate = self;
    [menu showInRect:CGRectMake(100, 100, 100, 200)];



#import <UIKit/UIKit.h>

@class HMPopMenu;

@protocol HMPopMenuDelegate <NSObject>

@optional
- (void)popMenuDidDismissed:(HMPopMenu *)popMenu;
@end

@interface HMPopMenu : UIView
@property (nonatomic, weak) id<HMPopMenuDelegate> delegate;

/**
 *  初始化方法
 */
- (instancetype)initWithContentView:(UIView *)contentView;
+ (instancetype)popMenuWithContentView:(UIView *)contentView;

/**
 *  设置菜单的背景图片
 */
- (void)setBackground:(UIImage *)background;

/**
 *  显示菜单
 */
- (void)showInRect:(CGRect)rect;

/**
 *  关闭菜单
 */
- (void)dismiss;
@end



#import "HMPopMenu.h"

@interface HMPopMenu()
@property (nonatomic, strong) UIView *contentView;
/**
 *  最底部的遮盖 :屏蔽除菜单以外控件的事件
 */
@property (nonatomic, weak) UIButton *cover;
/**
 *  容器 :容纳具体要显示的内容contentView
 */
@property (nonatomic, weak) UIImageView *container;
@end

@implementation HMPopMenu
#pragma mark - 初始化方法
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        /** 添加菜单内部的2个子控件 **/
        // 添加一个遮盖按钮
        UIButton *cover = [[UIButton alloc] init];
        cover.backgroundColor = [UIColor clearColor];
        [cover addTarget:self action:@selector(dismiss) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:cover];
        self.cover = cover;
        
        // 添加带箭头的菜单图片
        UIImageView *container = [[UIImageView alloc] init];
        container.userInteractionEnabled = YES;
        container.image = [UIImage resizedImage:@"popover_background"];
        [self addSubview:container];
        self.container = container;
    }
    return self;
}

- (instancetype)initWithContentView:(UIView *)contentView
{
    if (self = [super init]) {
        self.contentView = contentView;
    }
    return self;
}

+ (instancetype)popMenuWithContentView:(UIView *)contentView
{
    return [[self alloc] initWithContentView:contentView];
}


- (void)layoutSubviews
{
    [super layoutSubviews];
    
    self.cover.frame = self.bounds;
}

#pragma mark - 内部方法
- (void)coverClick
{
    [self dismiss];
}

#pragma mark - 公共方法
- (void)setBackground:(UIImage *)background
{
    self.container.image = background;
}

- (void)showInRect:(CGRect)rect
{
    // 添加菜单整体到窗口身上
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    self.frame = window.bounds;
    [window addSubview:self];
    
    // 设置容器的frame
    self.container.frame = rect;
    [self.container addSubview:self.contentView];
    
    // 设置容器里面内容的frame
    CGFloat topMargin = 12;
    CGFloat leftMargin = 5;
    CGFloat rightMargin = 5;
    CGFloat bottomMargin = 8;
    
    self.contentView.y = topMargin;
    self.contentView.x = leftMargin;
    self.contentView.width = self.container.width - leftMargin - rightMargin;
    self.contentView.height = self.container.height - topMargin - bottomMargin;
}

- (void)dismiss
{
    if ([self.delegate respondsToSelector:@selector(popMenuDidDismissed:)]) {
        [self.delegate popMenuDidDismissed:self];
    }
    
    [self removeFromSuperview];
}
@end


你可能感兴趣的:(自定义UIView一个弹出菜单)