自定义UIAlertView


转自:http://www.haogongju.net/art/1000322

软件开发中,我们有时要很特别UIalertView,我知道的有两种方式去实现,这里要介绍的就是第二种,在网上看到的,自己整理了一下,源工程的svn地址是:httbydialog.googlecode.com/svn/trunk/,你可以在终端输入:“svn export httbydialog.googlecode.com/svn/trunk/”将他们导出来,一般会自动的存放在home文件夹下(也就是桌面的上一层)。

第一种,修改系统的那个东西。

  在uialertView的一个delegate方法“- (void)willPresentAlertView:(UIAlertView *)alertView;”中,我们已经得到就要显示的UIalertView,然后我们想怎么改就怎么改,其实改了心里有点不踏实,我也不知道为什么,感觉总是不踏实。

第二种,先上代码:

  CAlertView.h

#import <UIKit/UIKit.h>
@class CAlertView;
@protocol CAlertViewDelegate <NSObject>
@optional
-(void)didRotationToInterfaceOrientation:(BOOL)Landscape view:(UIView*)view alertView:(CAlertView*)aletView;
@end

@interface CAlertView : UIView{
@private
    BOOL   _beShow;
    UIInterfaceOrientation _orientation;
    BOOL   _bePresented;
}
@property(nonatomic,retain)UIView*  backGroundView;
@property(nonatomic,retain)UIView*  contentView;
@property(nonatomic, readonly)BOOL  visible;
@property(nonatomic,assign)id<CAlertViewDelegate> delegate;

- (id)initWithView:(UIView*)view;
-(void)show;
-(void)dismissAlertViewWithAnimated:(BOOL)animated;

@end

CAlertView.m

#import "CAlertView.h"


#define BE_IPAD (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad)

static CGFloat kTransitionDuration = 0.3f;
static NSMutableArray*  gAlertViewStack = nil;
static UIWindow* gPreviouseKeyWindow = nil;
static UIWindow* gMaskWindow = nil;

@interface CAlertView(priveteMethods)

-(BOOL)_shouldRotateToOrientation:(UIDeviceOrientation)orientation;
-(void)_registerObservers;
-(void)_removeObservers;
-(void)_orientationDidChange:(NSNotification*)notify;
-(void)_sizeToFitOrientation:(BOOL)transform;
-(CGAffineTransform)_transformForOrientation;

+(CAlertView*)_getStackTopAlertView;
+(void)_pushAlertViewInStack:(CAlertView*)alertView;
+ (void)_popAlertViewFromStack;

+(void)_presentMaskWindow;
+(void)_dismissMaskWindow;

+(void)_addAlertViewOnMaskWindow:(CAlertView *)alertView;
+(void)_removeAlertViewFormMaskWindow:(CAlertView*)alertView;

-(void)_bounce0Animation;
-(void)_bounce1AnimationDidStop;
-(void)_bounce2AnimationDidStop;
-(void)_bounceDidStop;

-(void)_dismissAlertView;
@end



@implementation CAlertView



@synthesize contentView = _contentView;
@synthesize backGroundView = _backGroundView;
@synthesize delegate = _delegate;
@dynamic visible;

- (BOOL)visible{
    return self.superview && !self.hidden;
}

-(UIView*)backGroundView{
    return _backGroundView;
}

-(void)setBackGroundView:(UIView *)backGroundView{
    if (nil != _backGroundView) {
        [_backGroundView removeFromSuperview];
        [_backGroundView release];
    }
    _backGroundView = [backGroundView retain];
}

-(UIView*)contentView{
 
    if (!_contentView) {
        _contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
        [_contentView setBackgroundColor:[UIColor blueColor]];
    }
    return _contentView;

}

-(void)loadContentView{
    [[NSBundle mainBundle] loadNibNamed:@"TestDialogContentView" 
                                  owner:self
                                options:nil];
}



-(id)initWithView:(UIView *)view {
    if (self = [super initWithFrame:CGRectZero]){
        _contentView = [view retain];
        self.contentView.autoresizesSubviews = YES;
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin |\
        UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
        [self addSubview:self.contentView];
    }
    return self;
}



-(void)show{
    if (_beShow) {
        return;
    }
    _beShow = YES;
    
    [self retain];
    [self _registerObservers];//添加消息,在设备发生旋转时会有相应的处理
    [self _sizeToFitOrientation:NO];
    

    //如果栈中没有alertview,就表示maskWindow没有弹出,所以弹出maskWindow
    if (![CAlertView _getStackTopAlertView]) {
        [CAlertView _presentMaskWindow];
    }
    
    
    if (nil != self.backGroundView && ![[gMaskWindow subviews] containsObject:self.backGroundView]) {
        [gMaskWindow addSubview:self.backGroundView];
    }
    //将alertView显示在window上
    [CAlertView _addAlertViewOnMaskWindow:self];
    
    //alertView弹出动画
    [self _bounce0Animation];
}


//要让alertView消失时调用此方法
-(void)dismissAlertViewWithAnimated:(BOOL)animated{
    if (!_beShow) {
        return;
    }
    _beShow = NO;
    
    if (animated) {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:kTransitionDuration];
        [UIView setAnimationDelegate:self];
        [UIView setAnimationDidStopSelector:@selector(_dismissAlertView)];
        self.alpha = 0;
        [UIView commitAnimations];
    } else {
        [self _dismissAlertView];
    }
    
    if (nil != self.backGroundView && [[gMaskWindow subviews] containsObject:self.backGroundView]) {
        [self.backGroundView removeFromSuperview];
    }
}


-(CGSize)sizeThatFits:(CGSize)size{
    return self.contentView.frame.size;
}

@end




@implementation CAlertView(priveteMethods)

-(BOOL)_shouldRotateToOrientation:(UIDeviceOrientation)orientation{
    BOOL result = NO;
    if (_orientation != orientation) {
        result = (orientation == UIDeviceOrientationPortrait ||
                  orientation == UIDeviceOrientationPortraitUpsideDown ||
                  orientation == UIDeviceOrientationLandscapeLeft ||
                  orientation == UIDeviceOrientationLandscapeRight);
    }
    
    return result;
}

-(void)_registerObservers{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_orientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
}

-(void)_removeObservers{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

-(void)_orientationDidChange:(NSNotification*)notify
{
    
    UIDeviceOrientation orientation = (UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation;
    if ([self _shouldRotateToOrientation:orientation]) {
        if ([_delegate respondsToSelector:@selector(didRotationToInterfaceOrientation:view:alertView:)]) {
            [_delegate didRotationToInterfaceOrientation:UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) view:_contentView alertView:self];
        }
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.25f];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [self _sizeToFitOrientation:YES];
        [UIView commitAnimations];
    } 
}

- (void)_sizeToFitOrientation:(BOOL)transform{
    
    if (transform) {
        self.transform = CGAffineTransformIdentity;
    }
    _orientation = [UIApplication sharedApplication].statusBarOrientation;        
    [self sizeToFit];
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    [self setCenter:CGPointMake(screenSize.width/2, screenSize.height/2)];
    if (transform) {
        self.transform = [self _transformForOrientation];
    }
}

-(CGAffineTransform)_transformForOrientation{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (orientation == UIInterfaceOrientationLandscapeLeft) {
        return CGAffineTransformMakeRotation(M_PI*1.5f);
    } else if (orientation == UIInterfaceOrientationLandscapeRight) {
        return CGAffineTransformMakeRotation(M_PI/2.0f);
    } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
        return CGAffineTransformMakeRotation(-M_PI);
    } else {
        return CGAffineTransformIdentity;
    }
}


+(void)_presentMaskWindow{
    
    if (!gMaskWindow) {
        gMaskWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        gMaskWindow.windowLevel = UIWindowLevelStatusBar + 1;
        gMaskWindow.backgroundColor = [UIColor clearColor];
        gMaskWindow.hidden = YES;
        
        [gMaskWindow setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.65f]];
        
        // FIXME: window at index 0 is not awalys previous key window.
        gPreviouseKeyWindow = [[UIApplication sharedApplication].windows objectAtIndex:0];
        [gMaskWindow makeKeyAndVisible];
        
        // Fade in background 
        gMaskWindow.alpha = 0;
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        gMaskWindow.alpha = 1;
        [UIView commitAnimations];
    }
}

+(void)_dismissMaskWindow{
    // make previouse window the key again
    if (gMaskWindow) {
        [gPreviouseKeyWindow makeKeyAndVisible];
        gPreviouseKeyWindow = nil;
        
        [gMaskWindow release];
        gMaskWindow = nil;
    }
}

+(CAlertView*)_getStackTopAlertView{
    CAlertView* topItem = nil;
    if (0 != [gAlertViewStack count]) {
        topItem = [gAlertViewStack lastObject];
    }
    
    return topItem;
}

+ (void)_addAlertViewOnMaskWindow:(CAlertView *)alertView{
    if (!gMaskWindow ||[gMaskWindow.subviews containsObject:alertView]) {
        return;
    }
    
    [gMaskWindow addSubview:alertView];
    alertView.hidden = NO;
    
    CAlertView* previousAlertView = [CAlertView _getStackTopAlertView];
    if (previousAlertView) {
        previousAlertView.hidden = YES;
    }
    [CAlertView _pushAlertViewInStack:alertView];
}

+(void)_removeAlertViewFormMaskWindow:(CAlertView*)alertView{
    if (!gMaskWindow || ![gMaskWindow.subviews containsObject:alertView]) {
        return;
    }
    
    [alertView removeFromSuperview];
    alertView.hidden = YES;
    
    [CAlertView _popAlertViewFromStack];
    CAlertView *previousAlertView = [CAlertView _getStackTopAlertView];
    if (previousAlertView) {
        previousAlertView.hidden = NO;
        [previousAlertView _bounce0Animation];
    }
}

+(void)_pushAlertViewInStack:(CAlertView*)alertView{
    if (!gAlertViewStack) {
        gAlertViewStack = [[NSMutableArray alloc] init];
    }
    [gAlertViewStack addObject:alertView];
}


+(void)_popAlertViewFromStack{
    if (![gAlertViewStack count]) {
        return;
    }
    [gAlertViewStack removeLastObject];
    
    if ([gAlertViewStack count] == 0) {
        [gAlertViewStack release];
        gAlertViewStack = nil;
    }
}

-(void)_bounce0Animation{
    self.transform = CGAffineTransformScale([self _transformForOrientation], 0.001f, 0.001f);
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:kTransitionDuration/1.5f];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(_bounce1AnimationDidStop)];
    self.transform = CGAffineTransformScale([self _transformForOrientation], 1.1f, 1.1f);
    [UIView commitAnimations];
}

-(void)_bounce1AnimationDidStop{  
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:kTransitionDuration/2];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(_bounce2AnimationDidStop)];
    self.transform = CGAffineTransformScale([self _transformForOrientation], 0.9f, 0.9f);
    [UIView commitAnimations];
}
-(void)_bounce2AnimationDidStop{
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:kTransitionDuration/2];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(_bounceDidStop)];
    self.transform = [self _transformForOrientation];
    [UIView commitAnimations];
}

-(void)_bounceDidStop{
    if (!_bePresented) {
        _bePresented = YES;
    }
}

-(void)_dismissAlertView{
    [CAlertView _removeAlertViewFormMaskWindow:self];
    
    // If there are no dialogs visible, dissmiss mask window too.
    if (![CAlertView _getStackTopAlertView]) {
        [CAlertView _dismissMaskWindow];
    }
    
    [self _removeObservers];
    [self release];
}



@end


使用举例:

  UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
  [view setBackgroundColor:[UIColor blueColor]];
   
    UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setBackgroundColor:[UIColor grayColor]];
    [button setFrame:CGRectMake(0, 0, 80, 20)];
    [button setTitle:@"消失" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(alertDismiss) forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:button];
    
    
    UIView* viewbg = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 400)];
    [viewbg setBackgroundColor:[UIColor redColor]];
    
    
    alert = [[CAlertView alloc] initWithView:view];
    [alert setBackGroundView:viewbg];
    [viewbg release];
    viewbg = nil;
    alert.delegate = self;
    [view release];
    view = nil;
    [alert show];

最后要消失

-(void)alertDismiss{
    [alert dismissAlertViewWithAnimated:YES];
    [alert release];
    alert  = nil;
}

 

如果有必要处理旋转,实现delegate

-(void)didRotationToInterfaceOrientation:(BOOL)Landscape view:(UIView*)view alertView:(CAlertView*)aletView{
    if (Landscape) {
        [view setFrame:CGRectMake(0, 0, 300, 200)];
        [aletView.backGroundView setBackgroundColor:[UIColor whiteColor]];
    }else{
        [view setFrame:CGRectMake(0, 0, 200, 200)];
        [aletView.backGroundView setBackgroundColor:[UIColor greenColor]];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值