转自: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]]; } }