在软件开发中,我们有时要很特别的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]];
}
}