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