系統提供的UIAlertView很好用,簡單美觀,但不夠靈活。
有時候我們希望自定義實現各種各樣的AlertView,在GitHub上找了一個Star比較多又好用的,自己稍作修改並加了注釋,大家可以參考,也可以拿去直接使用。
GitHub原代碼地址:https://github.com/wimagguc/ios-custom-alertview
下面是我自己修改過的
http://files.cnblogs.com/files/fanzhiying/CustomIOSAlertView.zip
CustomIOSAlertView.h
#import <UIKit/UIKit.h> @interface CustomIOSAlertView : UIView //提示視圖 @property (nonatomic, strong) UIView *dialogView; //提示視圖的子視圖(自定義) @property (nonatomic, strong) UIView *containerView; //按鈕標題數組 @property (nonatomic, strong) NSArray *buttonTitles; //按鈕點擊事件 @property (copy) void (^onButtonTouchUpInside)(CustomIOSAlertView *alertView, int buttonIndex) ; //初始化 - (id)init; //顯示 - (void)show; //關閉 - (void)close; //設置子視圖 - (void)setSubView: (UIView *)subView; //設置按鈕點擊事件 - (void)setOnButtonTouchUpInside:(void (^)(CustomIOSAlertView *alertView, int buttonIndex))onButtonTouchUpInside; //設備旋轉,橫向/豎向改變 - (void)deviceOrientationDidChange: (NSNotification *)notification; - (void)dealloc; @end
CustomIOSAlertView.m
#import "CustomIOSAlertView.h" #import <QuartzCore/QuartzCore.h> const static CGFloat kCustomIOSAlertViewDefaultButtonHeight = 50; //按鈕高度 const static CGFloat kCustomIOSAlertViewDefaultButtonSpacerHeight = 1; //分隔線寬度 const static CGFloat kCustomIOSAlertViewCornerRadius = 7; //圓角半徑 @implementation CustomIOSAlertView CGFloat buttonHeight = 0; CGFloat buttonSpacerHeight = 0; @synthesize containerView, dialogView, onButtonTouchUpInside; @synthesize buttonTitles; - (id)init { self = [super init]; if (self) { self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height); buttonTitles = @[@"關閉"]; //必須調用此方法監聽設備旋轉才有效 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; //監聽設備旋轉 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; //監聽鍵盤出現 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; //監聽鍵盤消失 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } return self; } //創建並顯示提示視圖 - (void)show { //創建提示視圖 dialogView = [self createContainerView]; //layer光柵化,提高性能 dialogView.layer.shouldRasterize = YES; dialogView.layer.rasterizationScale = [[UIScreen mainScreen] scale]; self.layer.shouldRasterize = YES; self.layer.rasterizationScale = [[UIScreen mainScreen] scale]; self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0]; [self addSubview:dialogView]; //iOS7, 旋轉方向調整 if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; switch (interfaceOrientation) { case UIInterfaceOrientationLandscapeLeft: self.transform = CGAffineTransformMakeRotation(M_PI * 270.0 / 180.0); break; case UIInterfaceOrientationLandscapeRight: self.transform = CGAffineTransformMakeRotation(M_PI * 90.0 / 180.0); break; case UIInterfaceOrientationPortraitUpsideDown: self.transform = CGAffineTransformMakeRotation(M_PI * 180.0 / 180.0); break; default: break; } [self setFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; //iOS8, 僅把提示視圖居中即可 } else { CGSize screenSize = [self countScreenSize]; CGSize dialogSize = [self countDialogSize]; CGSize keyboardSize = CGSizeMake(0, 0); dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); } [[[[UIApplication sharedApplication] windows] firstObject] addSubview:self]; dialogView.layer.opacity = 0.5f; dialogView.layer.transform = CATransform3DMakeScale(1.3f, 1.3f, 1.0); [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4f]; dialogView.layer.opacity = 1.0f; dialogView.layer.transform = CATransform3DMakeScale(1, 1, 1); } completion:NULL ]; } // Button has been touched - (void)customIOS7dialogButtonTouchUpInside:(id)sender { if (onButtonTouchUpInside != NULL) { onButtonTouchUpInside(self, (int)[sender tag]); } } //提示視圖關閉並移除 - (void)close { CATransform3D currentTransform = dialogView.layer.transform; if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { CGFloat startRotation = [[dialogView valueForKeyPath:@"layer.transform.rotation.z"] floatValue]; CATransform3D rotation = CATransform3DMakeRotation(-startRotation + M_PI * 270.0 / 180.0, 0.0f, 0.0f, 0.0f); dialogView.layer.transform = CATransform3DConcat(rotation, CATransform3DMakeScale(1, 1, 1)); } dialogView.layer.opacity = 1.0f; [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{ self.backgroundColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f]; dialogView.layer.transform = CATransform3DConcat(currentTransform, CATransform3DMakeScale(0.6f, 0.6f, 1.0)); dialogView.layer.opacity = 0.0f; } completion:^(BOOL finished) { for (UIView *v in [self subviews]) { [v removeFromSuperview]; } [self removeFromSuperview]; } ]; } - (void)setSubView: (UIView *)subView { containerView = subView; } //創建提示視圖 - (UIView *)createContainerView { if (containerView == NULL) { containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 150)]; } CGSize screenSize = [self countScreenSize]; CGSize dialogSize = [self countDialogSize]; [self setFrame:CGRectMake(0, 0, screenSize.width, screenSize.height)]; //提示視圖 UIView *dialogContainer = [[UIView alloc] initWithFrame:CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height)]; CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = dialogContainer.bounds; gradient.colors = [NSArray arrayWithObjects: (id)[[UIColor colorWithRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:1.0f] CGColor], (id)[[UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0f] CGColor], (id)[[UIColor colorWithRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:1.0f] CGColor], nil]; CGFloat cornerRadius = kCustomIOSAlertViewCornerRadius; gradient.cornerRadius = cornerRadius; [dialogContainer.layer insertSublayer:gradient atIndex:0]; dialogContainer.layer.cornerRadius = cornerRadius; dialogContainer.layer.shadowRadius = cornerRadius + 5; dialogContainer.layer.shadowOpacity = 0.1f; dialogContainer.layer.shadowOffset = CGSizeMake(0 - (cornerRadius+5)/2, 0 - (cornerRadius+5)/2); dialogContainer.layer.shadowColor = [UIColor blackColor].CGColor; dialogContainer.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:dialogContainer.bounds cornerRadius:dialogContainer.layer.cornerRadius].CGPath; //分隔線 UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, dialogContainer.bounds.size.height - buttonHeight - buttonSpacerHeight, dialogContainer.bounds.size.width, buttonSpacerHeight)]; lineView.backgroundColor = [UIColor colorWithRed:198.0/255.0 green:198.0/255.0 blue:198.0/255.0 alpha:1.0f]; [dialogContainer addSubview:lineView]; //添加子視圖 [dialogContainer addSubview:containerView]; //添加按鈕 [self addButtonsToView:dialogContainer]; return dialogContainer; } //添加按鈕 - (void)addButtonsToView: (UIView *)container { if (buttonTitles==NULL) { return; } CGFloat buttonWidth = container.bounds.size.width / [buttonTitles count]; for (int i=0; i<[buttonTitles count]; i++) { UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [closeButton setFrame:CGRectMake(i * buttonWidth, container.bounds.size.height - buttonHeight, buttonWidth, buttonHeight)]; [closeButton addTarget:self action:@selector(customIOS7dialogButtonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside]; [closeButton setTag:i]; [closeButton setTitle:[buttonTitles objectAtIndex:i] forState:UIControlStateNormal]; [closeButton setTitleColor:[UIColor colorWithRed:0.0f green:0.5f blue:1.0f alpha:1.0f] forState:UIControlStateNormal]; [closeButton setTitleColor:[UIColor colorWithRed:0.2f green:0.2f blue:0.2f alpha:0.5f] forState:UIControlStateHighlighted]; [closeButton.titleLabel setFont:[UIFont boldSystemFontOfSize:14.0f]]; [closeButton.layer setCornerRadius:kCustomIOSAlertViewCornerRadius]; [container addSubview:closeButton]; if (i > 0) { //按鈕分隔線 UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(i * buttonWidth, container.bounds.size.height - buttonHeight, kCustomIOSAlertViewDefaultButtonSpacerHeight, buttonHeight)]; lineView.backgroundColor = [UIColor colorWithRed:198.0/255.0 green:198.0/255.0 blue:198.0/255.0 alpha:1.0f]; [container addSubview:lineView]; } } } //得到提示視圖的size - (CGSize)countDialogSize { CGFloat dialogWidth = containerView.frame.size.width; CGFloat dialogHeight = containerView.frame.size.height + buttonHeight + buttonSpacerHeight; return CGSizeMake(dialogWidth, dialogHeight); } //得到屏幕的size - (CGSize)countScreenSize { if (buttonTitles!=NULL && [buttonTitles count] > 0) { buttonHeight = kCustomIOSAlertViewDefaultButtonHeight; buttonSpacerHeight = kCustomIOSAlertViewDefaultButtonSpacerHeight; } else { buttonHeight = 0; buttonSpacerHeight = 0; } CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; //iOS7, 屏幕的寬高不會隨着方向自動調整 if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) { CGFloat tmp = screenWidth; screenWidth = screenHeight; screenHeight = tmp; } } return CGSizeMake(screenWidth, screenHeight); } //設備旋轉 - (void)deviceOrientationDidChange: (NSNotification *)notification { if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { [self changeOrientationForIOS7]; } else { [self changeOrientationForIOS8:notification]; } } //設備旋轉(iOS7) - (void)changeOrientationForIOS7 { UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; CGFloat startRotation = [[self valueForKeyPath:@"layer.transform.rotation.z"] floatValue]; CGAffineTransform rotation; switch (interfaceOrientation) { case UIInterfaceOrientationLandscapeLeft: rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 270.0 / 180.0); break; case UIInterfaceOrientationLandscapeRight: rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 90.0 / 180.0); break; case UIInterfaceOrientationPortraitUpsideDown: rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 180.0 / 180.0); break; default: rotation = CGAffineTransformMakeRotation(-startRotation + 0.0); break; } [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{ dialogView.transform = rotation; } completion:nil ]; } //設備旋轉(iOS8) - (void)changeOrientationForIOS8: (NSNotification *)notification { CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{ CGSize dialogSize = [self countDialogSize]; CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; self.frame = CGRectMake(0, 0, screenWidth, screenHeight); dialogView.frame = CGRectMake((screenWidth - dialogSize.width) / 2, (screenHeight - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); } completion:nil ]; } //鍵盤出現 - (void)keyboardWillShow: (NSNotification *)notification { CGSize screenSize = [self countScreenSize]; CGSize dialogSize = [self countDialogSize]; CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if (UIInterfaceOrientationIsLandscape(interfaceOrientation) && NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) { CGFloat tmp = keyboardSize.height; keyboardSize.height = keyboardSize.width; keyboardSize.width = tmp; } [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{ dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); } completion:nil ]; } //鍵盤消失 - (void)keyboardWillHide: (NSNotification *)notification { CGSize screenSize = [self countScreenSize]; CGSize dialogSize = [self countDialogSize]; [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone animations:^{ dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); } completion:nil ]; } - (void)dealloc { [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; } @end
使用非常簡單
提示視圖的寬就是子視圖的寬,高就是子視圖的高+按鈕的高+分隔線的線寬
ViewController.m
- (void)viewDidLoad { [super viewDidLoad]; UIButton *testButton = [[UIButton alloc] initWithFrame:CGRectMake(80, 500, self.view.frame.size.width-160, 50)]; testButton.backgroundColor = [UIColor lightGrayColor]; [testButton addTarget:self action:@selector(clickedTestButton) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:testButton]; } - (void)clickedTestButton { CustomIOSAlertView *alertView = [[CustomIOSAlertView alloc] init]; //添加子視圖 [alertView setSubView:[self addSubView]]; //添加按鈕標題數組 [alertView setButtonTitles:[NSMutableArray arrayWithObjects:@"取消", @"確定", nil]]; //添加按鈕點擊方法 [alertView setOnButtonTouchUpInside:^(CustomIOSAlertView *alertView, int buttonIndex) { NSLog(@"Block: Button at position %d is clicked on alertView %d.", buttonIndex, (int)[alertView tag]); //關閉 [alertView close]; }]; //顯示 [alertView show]; } //自定義的子視圖 - (UIView *)addSubView { UILabel *view = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 260, 200)]; view.text = @"我是子視圖"; view.textAlignment = NSTextAlignmentCenter; return view; }