原创Blog,转载请注明出处 
blog.csdn.net/hello_hwc
前言:这个系列的目的是写一些自定义控件的思路,并不是拿来就可以用的控件,想要直接用的控件库,去github上有的是。这个系列希望抛砖引玉,能够让读者学会如何去自定义控件,授之以渔总比授之以鱼强。
本文的内容
希望通过本文,读者能够学到
一 Demo展示 
我的习惯是每讲解一些原理,都会写个demo。这个也不例外。 
demo的gif如下,用代理的方式传递点击OK或者cancel的事件。 
 
二 实现过程
2.1  接口设计 
 这里仅仅声明了一个初始化方法,一个show方法,以及声明了一个代理,用代理来传值。如果想要自己写一个库的话,API要设计的更完善一些,这里仅仅是为了demo,不搞得那么复杂。
@protocol WCALertviewDelegate<NSObject>
@optional
-(void)didClickButtonAtIndex:(NSUInteger)index;
@end
@interface WCAlertview : UIView
@property (weak,nonatomic) id<WCALertviewDelegate> delegate;
-(instancetype)initWithTitle:(NSString *) title Image:(UIImage *)image CancelButton:(NSString *)cancelButton OkButton:(NSString *)okButton;
- (void)show;
@end2.2 思考下如何模态的展示Alertview 
可以把当前的view作为subview添加到keyWindow,并且设计一个backgroundview,让其的背景色为黑色,透明度为0.4,这就形成了模态展示。 
同时,要为backgroundview添加tap手势,让其点击的时候,能够让alertview消失。然后,用一个UIView作为实际展示alertview的实体。所以,层次关系如下 
WCAlertview包括backgroubdview以及alertview实体,alertview实体包括图片,title,button等。 
为了用UIDynamic Animation,要保存一个Animator的属性。 
所以,私有属性应该包括这些
@property (strong,nonatomic)UIDynamicAnimator * animator;
@property (strong,nonatomic)UIView * alertview;
@property (strong,nonatomic)UIView * backgroundview;
@property (strong,nonatomic)NSString * title;
@property (strong,nonatomic)NSString * cancelButtonTitle;
@property (strong,nonatomic)NSString * okButtonTitle;
@property (strong,nonatomic)UIImage * image;backgroundview实现如下
self.backgroundview = [[UIView alloc] initWithFrame:[[UIApplication sharedApplication] keyWindow].frame];
    self.backgroundview.backgroundColor = [UIColor blackColor];
    self.backgroundview.alpha = 0.4;
    [self addSubview:self.backgroundview];
    UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click:)];
    [self.backgroundview addGestureRecognizer:tap];
tap的响应函数
-(void)click:(UITapGestureRecognizer *)sender{
    CGPoint tapLocation = [sender locationInView:self.backgroundview];
    CGRect alertFrame = self.alertview.frame;
    if (!CGRectContainsPoint(alertFrame, tapLocation)) {
        [self dismiss];
    }
}这里的dismiss是让整个WCAlertview消失,注意,要判断点击的点是否在alertview实体内,如果不在,才应该dismiss 
dismiss采用UIView的动画
-(void)dismiss{
    [self.animator removeAllBehaviors];
    [UIView animateWithDuration:0.7 animations:^{
        self.alpha = 0.0;
        CGAffineTransform rotate = CGAffineTransformMakeRotation(0.9 * M_PI);
        CGAffineTransform scale = CGAffineTransformMakeScale(0.1, 0.1);
        self.alertview.transform = CGAffineTransformConcat(rotate, scale);
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
         self.alertview = nil;
    }];
}2.3 设计Alertview的实体 
简单的UI控件堆砌
self.alertview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, alertviewWidth, 250)];
    self.alertview.layer.cornerRadius = 17;
    UIView * keywindow = [[UIApplication sharedApplication] keyWindow];
    self.alertview.center = CGPointMake(CGRectGetMidX(keywindow.frame), -CGRectGetMidY(keywindow.frame));
    self.alertview.backgroundColor = [UIColor whiteColor];
    self.alertview.clipsToBounds = YES;
    [self addSubview:self.alertview];
    UILabel * titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,alertviewWidth,titleHeight)];
    titleLabel.text = self.title;
    titleLabel.textAlignment = NSTextAlignmentCenter;
    [self.alertview addSubview:titleLabel];
    UIImageView * imageview = [[UIImageView alloc] initWithFrame:CGRectMake(0,titleHeight, alertviewWidth,imageviewHeight)];
    imageview.contentMode = UIViewContentModeScaleToFill;
    imageview.image = self.image;
    imageview.layer.borderColor = [UIColor lightGrayColor].CGColor;
    imageview.layer.borderWidth = 0.5;
    [self.alertview addSubview:imageview];
    CGRect cancelButtonFrame = CGRectMake(0, titleHeight + imageviewHeight,alertviewWidth,buttonHeight);
    if (self.okButtonTitle.length != 0 && self.okButtonTitle !=nil) {
        cancelButtonFrame = CGRectMake(alertviewWidth / 2 ,titleHeight + imageviewHeight, alertviewWidth/2,buttonHeight);
        CGRect okButtonFrame = CGRectMake(0,titleHeight + imageviewHeight, alertviewWidth/2,buttonHeight);
        UIButton * okButton = [self createButtonWithFrame:okButtonFrame Title:self.okButtonTitle];
        okButton.tag = 2;
        [self.alertview addSubview:okButton];
    }
    UIButton * cancelButton = [self createButtonWithFrame:cancelButtonFrame Title:self.cancelButtonTitle];
    cancelButton.tag = 1;
    [self.alertview addSubview:cancelButton];讲解几点
-(UIButton *)createButtonWithFrame:(CGRect)frame Title:(NSString *)title
{
    UIButton * button = [[UIButton alloc] initWithFrame:frame];
    button.titleLabel.textAlignment = NSTextAlignmentCenter;
    [button setTitle:title forState:UIControlStateNormal];
    [button setTitleColor:[UIColor blueColor]forState:UIControlStateNormal];
    button.titleLabel.textColor = [UIColor blueColor];
    button.titleLabel.textAlignment = NSTextAlignmentCenter;
    button.layer.borderWidth = 0.5;
    button.layer.borderColor = [UIColor lightGrayColor].CGColor;
    [button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];
    [button setShowsTouchWhenHighlighted:YES];
    return button;
}2.4 API实现
- (void)show {
    UIView * keywindow = [[UIApplication sharedApplication] keyWindow];
    [keywindow addSubview:self];
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
    UISnapBehavior * sanp = [[UISnapBehavior alloc] initWithItem:self.alertview snapToPoint:self.center];
    sanp.damping = 0.7;
    [self.animator addBehavior:sanp];
}
-(instancetype)initWithTitle:(NSString *) title
                       Image:(UIImage *)image
                CancelButton:(NSString *)cancelButton
                    OkButton:(NSString *)okButton{
    if (self = [super initWithFrame:[[UIApplication sharedApplication] keyWindow].frame]) {
        self.title = title;
        self.image = image;
        self.cancelButtonTitle = cancelButton;
        self.okButtonTitle = okButton;
        [self setUp];
    }
    return self;
}2.5 用代理传值
-(void)clickButton:(UIButton *)button{
    if ([self.delegate respondsToSelector:@selector(didClickButtonAtIndex:)]) {
        [self.delegate didClickButtonAtIndex:(button.tag -1)];
    }
    [self dismiss];
}2.6在使用地方
#import "WCAlertview.h"
@interface ViewController ()<WCALertviewDelegate>
@end
@implementation ViewController
- (IBAction)show:(id)sender {
    WCAlertview * alert = [[WCAlertview alloc] initWithTitle:@"Tite"
                                                       Image:[UIImage imageNamed:@"Image1.jpg"]
                                                CancelButton:@"Cancel"
                                                    OkButton:@"OK"];
    alert.delegate = self;
    [alert show];
}
-(void)didClickButtonAtIndex:(NSUInteger)index{
    switch (index) {
        case 0:
            NSLog(@"Click Cancel");
            break;
        case 1:
            NSLog(@"Click OK");
            break;
        default:
            break;
    }
}最后,附上完整的demo下载,不建议直接拿去用。 
CSDN下载链接
原文地址:http://blog.csdn.net/hello_hwc/article/details/43877365