#import <UIKit/UIKit.h>
@protocol CustomIOS7AlertViewDelegate
- (void)customIOS7dialogButtonTouchUpInside:(id)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
@end
@interface CustomIOS7AlertView :UIView<CustomIOS7AlertViewDelegate>
@property (nonatomic,retain) UIView *parentView; // The parent view this 'dialog' is attached to
@property (nonatomic,retain) UIView *dialogView; // Dialog's container view
@property (nonatomic,retain) UIView *containerView;// Container within the dialog (place your ui elements here)
@property (nonatomic,retain) UIView *buttonView; // Buttons on the bottom of the dialog
@property (nonatomic,assign) id<CustomIOS7AlertViewDelegate> delegate;
@property (nonatomic,retain) NSArray *buttonTitles;
@property (nonatomic,assign) BOOL useMotionEffects;
@property (copy)void (^onButtonTouchUpInside)(CustomIOS7AlertView *alertView,int buttonIndex) ;
- (id)init;
/*!
DEPRECATED: Use the [CustomIOS7AlertView init] method without passing a parent view.
*/
- (id)initWithParentView: (UIView *)_parentView __attribute__ ((deprecated));
- (void)show;
- (void)close;
- (IBAction)customIOS7dialogButtonTouchUpInside:(id)sender;
- (void)setOnButtonTouchUpInside:(void (^)(CustomIOS7AlertView *alertView,int buttonIndex))onButtonTouchUpInside;
- (void)deviceOrientationDidChange: (NSNotification *)notification;
- (void)dealloc;
@end
#import "CustomIOS7AlertView.h"
#import <QuartzCore/QuartzCore.h>
conststatic CGFloat kCustomIOS7AlertViewDefaultButtonHeight =50;
conststatic CGFloat kCustomIOS7AlertViewDefaultButtonSpacerHeight =1;
conststatic CGFloat kCustomIOS7AlertViewCornerRadius =7;
conststatic CGFloat kCustomIOS7MotionEffectExtent =10.0;
@implementation CustomIOS7AlertView
CGFloat buttonHeight =0;
CGFloat buttonSpacerHeight =0;
@synthesize parentView, containerView, dialogView, buttonView, onButtonTouchUpInside;
@synthesize delegate;
@synthesize buttonTitles;
@synthesize useMotionEffects;
- (id)initWithParentView: (UIView *)_parentView
{
self = [selfinit];
if (_parentView) {
self.frame = _parentView.frame;
self.parentView = _parentView;
}
return self;
}
- (id)init
{
self = [superinit];
if (self) {
self.frame =CGRectMake(0,0, [UIScreenmainScreen].bounds.size.width, [UIScreenmainScreen].bounds.size.height);
delegate = self;
useMotionEffects =false;
buttonTitles = @[];// @[@"关闭"];
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(deviceOrientationDidChange:)name:UIDeviceOrientationDidChangeNotificationobject:nil];
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(keyboardWillShow:)name:UIKeyboardWillShowNotificationobject:nil];
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(keyboardWillHide:)name:UIKeyboardWillHideNotificationobject:nil];
}
return self;
}
// Create the dialog view, and animate opening the dialog
- (void)show
{
dialogView = [selfcreateContainerView];
dialogView.layer.shouldRasterize =YES;
dialogView.layer.rasterizationScale = [[UIScreenmainScreen]scale];
self.layer.shouldRasterize =YES;
self.layer.rasterizationScale = [[UIScreenmainScreen]scale];
#if (defined(__IPHONE_7_0))
if (useMotionEffects) {
[selfapplyMotionEffects];
}
#endif
dialogView.layer.opacity =0.5f;
dialogView.layer.transform = CATransform3DMakeScale(1.3f,1.3f, 1.0);
self.backgroundColor = [UIColorcolorWithRed:0green:0blue:0alpha:0];
[selfaddSubview:dialogView];
// Can be attached to a view or to the top most window
// Attached to a view:
if (parentView !=NULL) {
[parentViewaddSubview:self];
// Attached to the top most window (make sure we are using the right orientation):
}else {
UIInterfaceOrientation interfaceOrientation = [[UIApplicationsharedApplication] statusBarOrientation];
switch (interfaceOrientation) {
caseUIInterfaceOrientationLandscapeLeft:
self.transform =CGAffineTransformMakeRotation(M_PI *270.0 / 180.0);
break;
caseUIInterfaceOrientationLandscapeRight:
self.transform =CGAffineTransformMakeRotation(M_PI *90.0 / 180.0);
break;
caseUIInterfaceOrientationPortraitUpsideDown:
self.transform =CGAffineTransformMakeRotation(M_PI *180.0 / 180.0);
break;
default:
break;
}
[selfsetFrame:CGRectMake(0,0, self.frame.size.width,self.frame.size.height)];
[[[[UIApplicationsharedApplication] windows]firstObject] addSubview:self];
}
[UIViewanimateWithDuration:0.2fdelay:0.0options:UIViewAnimationOptionCurveEaseInOut
animations:^{
self.backgroundColor = [UIColorcolorWithRed:0green:0blue:0alpha:0.4f];
dialogView.layer.opacity =1.0f;
dialogView.layer.transform =CATransform3DMakeScale(1,1, 1);
}
completion:NULL
];
}
// Button has been touched
- (IBAction)customIOS7dialogButtonTouchUpInside:(id)sender
{
if (delegate !=NULL) {
[delegatecustomIOS7dialogButtonTouchUpInside:selfclickedButtonAtIndex:[sender tag]];
}
if (onButtonTouchUpInside !=NULL) {
onButtonTouchUpInside(self, [sendertag]);
}
}
// Default button behaviour
- (void)customIOS7dialogButtonTouchUpInside: (CustomIOS7AlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(@"Button Clicked! %d, %d", buttonIndex, [alertViewtag]);
[selfclose];
}
// Dialog close animation then cleaning and removing the view from the parent
- (void)close
{
CATransform3D currentTransform = dialogView.layer.transform;
CGFloat startRotation = [[dialogViewvalueForKeyPath:@"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;
[UIViewanimateWithDuration:0.2fdelay:0.0options:UIViewAnimationOptionTransitionNone
animations:^{
self.backgroundColor = [UIColorcolorWithRed:0.0fgreen:0.0fblue:0.0falpha:0.0f];
dialogView.layer.transform =CATransform3DConcat(currentTransform, CATransform3DMakeScale(0.6f, 0.6f, 1.0));
dialogView.layer.opacity =0.0f;
}
completion:^(BOOL finished) {
for (UIView *vin [self subviews]) {
[vremoveFromSuperview];
}
[selfremoveFromSuperview];
}
];
}
- (void)setSubView: (UIView *)subView
{
containerView = subView;
}
// Creates the container view here: create the dialog, then add the custom content and buttons
- (UIView *)createContainerView
{
if (containerView ==NULL) {
containerView = [[UIViewalloc] initWithFrame:CGRectMake(0,0, 300,150)];
}
CGSize screenSize = [selfcountScreenSize];
CGSize dialogSize = [selfcountDialogSize];
// For the black background
[selfsetFrame:CGRectMake(0,0, screenSize.width, screenSize.height)];
// This is the dialog's container; we attach the custom content and the buttons to this one
UIView *dialogContainer = [[UIViewalloc] initWithFrame:CGRectMake((screenSize.width - dialogSize.width) /2, (screenSize.height - dialogSize.height) /2, dialogSize.width, dialogSize.height)];
// First, we style the dialog to match the iOS7 UIAlertView >>>
CAGradientLayer *gradient = [CAGradientLayerlayer];
gradient.frame = dialogContainer.bounds;
gradient.colors = [NSArrayarrayWithObjects:
(id)[[UIColorcolorWithRed:218.0/255.0green:218.0/255.0blue:218.0/255.0alpha:1.0f]CGColor],
(id)[[UIColorcolorWithRed:233.0/255.0green:233.0/255.0blue:233.0/255.0alpha:1.0f]CGColor],
(id)[[UIColorcolorWithRed:218.0/255.0green:218.0/255.0blue:218.0/255.0alpha:1.0f]CGColor],
nil];
CGFloat cornerRadius =kCustomIOS7AlertViewCornerRadius;
gradient.cornerRadius = cornerRadius;
[dialogContainer.layerinsertSublayer:gradient atIndex:0];
dialogContainer.layer.cornerRadius = cornerRadius;
dialogContainer.layer.borderColor = [[UIColorcolorWithRed:198.0/255.0green:198.0/255.0blue:198.0/255.0alpha:1.0f]CGColor];
dialogContainer.layer.borderWidth =1;
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 = [UIColorblackColor].CGColor;
dialogContainer.layer.shadowPath = [UIBezierPathbezierPathWithRoundedRect:dialogContainer.boundscornerRadius:dialogContainer.layer.cornerRadius].CGPath;
// There is a line above the button
UIView *lineView = [[UIViewalloc] initWithFrame:CGRectMake(0, dialogContainer.bounds.size.height - buttonHeight - buttonSpacerHeight, dialogContainer.bounds.size.width,buttonSpacerHeight)];
lineView.backgroundColor = [UIColorcolorWithRed:198.0/255.0green:198.0/255.0blue:198.0/255.0alpha:1.0f];
[dialogContaineraddSubview:lineView];
// ^^^
// Add the custom container if there is any
[dialogContaineraddSubview:containerView];
// Add the buttons too
[selfaddButtonsToView:dialogContainer];
return dialogContainer;
}
// Helper function: add buttons to container
- (void)addButtonsToView: (UIView *)container
{
if (buttonTitles==NULL) {return; }
CGFloat buttonWidth = container.bounds.size.width / [buttonTitlescount];
for (int i=0; i<[buttonTitlescount]; i++) {
UIButton *closeButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
[closeButtonsetFrame:CGRectMake(i * buttonWidth, container.bounds.size.height -buttonHeight, buttonWidth, buttonHeight)];
[closeButtonaddTarget:selfaction:@selector(customIOS7dialogButtonTouchUpInside:)forControlEvents:UIControlEventTouchUpInside];
[closeButtonsetTag:i];
[closeButton setTitle:[buttonTitlesobjectAtIndex:i] forState:UIControlStateNormal];
[closeButton setTitleColor:[UIColorcolorWithRed:0.0fgreen:0.5fblue:1.0falpha:1.0f]forState:UIControlStateNormal];
[closeButton setTitleColor:[UIColorcolorWithRed:0.2fgreen:0.2fblue:0.2falpha:0.5f]forState:UIControlStateHighlighted];
[closeButton.titleLabelsetFont:[UIFontboldSystemFontOfSize:18.0f]];
[closeButton.layersetCornerRadius:kCustomIOS7AlertViewCornerRadius];
[containeraddSubview:closeButton];
}
}
// Helper function: count and return the dialog's size
- (CGSize)countDialogSize
{
CGFloat dialogWidth = containerView.frame.size.width;
CGFloat dialogHeight =containerView.frame.size.height + buttonHeight + buttonSpacerHeight;
return CGSizeMake(dialogWidth, dialogHeight);
}
// Helper function: count and return the screen's size
- (CGSize)countScreenSize
{
if (buttonTitles!=NULL && [buttonTitlescount] > 0) {
buttonHeight =kCustomIOS7AlertViewDefaultButtonHeight;
buttonSpacerHeight =kCustomIOS7AlertViewDefaultButtonSpacerHeight;
}else {
buttonHeight = 0;
buttonSpacerHeight =0;
}
CGFloat screenWidth = [UIScreenmainScreen].bounds.size.width;
CGFloat screenHeight = [UIScreenmainScreen].bounds.size.height;
UIInterfaceOrientation interfaceOrientation = [[UIApplicationsharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
CGFloat tmp = screenWidth;
screenWidth = screenHeight;
screenHeight = tmp;
}
return CGSizeMake(screenWidth, screenHeight);
}
#if (defined(__IPHONE_7_0))
// Add motion effects
- (void)applyMotionEffects {
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
return;
}
UIInterpolatingMotionEffect *horizontalEffect = [[UIInterpolatingMotionEffectalloc] initWithKeyPath:@"center.x"
type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
horizontalEffect.minimumRelativeValue =@(-kCustomIOS7MotionEffectExtent);
horizontalEffect.maximumRelativeValue =@( kCustomIOS7MotionEffectExtent);
UIInterpolatingMotionEffect *verticalEffect = [[UIInterpolatingMotionEffectalloc] initWithKeyPath:@"center.y"
type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
verticalEffect.minimumRelativeValue =@(-kCustomIOS7MotionEffectExtent);
verticalEffect.maximumRelativeValue =@( kCustomIOS7MotionEffectExtent);
UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroupalloc] init];
motionEffectGroup.motionEffects =@[horizontalEffect, verticalEffect];
[dialogViewaddMotionEffect:motionEffectGroup];
}
#endif
- (void)dealloc
{
[[NSNotificationCenterdefaultCenter]removeObserver:selfname:UIDeviceOrientationDidChangeNotificationobject:nil];
[[NSNotificationCenterdefaultCenter]removeObserver:selfname:UIKeyboardWillHideNotificationobject:nil];
[[NSNotificationCenterdefaultCenter]removeObserver:selfname:UIKeyboardWillShowNotificationobject:nil];
}
// Handle device orientation changes
- (void)deviceOrientationDidChange: (NSNotification *)notification
{
// If dialog is attached to the parent view, it probably wants to handle the orientation change itself
if (parentView !=NULL) {
return;
}
UIInterfaceOrientation interfaceOrientation = [[UIApplicationsharedApplication] statusBarOrientation];
CGFloat startRotation = [[selfvalueForKeyPath:@"layer.transform.rotation.z"]floatValue];
CGAffineTransform rotation;
switch (interfaceOrientation) {
caseUIInterfaceOrientationLandscapeLeft:
rotation =CGAffineTransformMakeRotation(-startRotation +M_PI * 270.0 /180.0);
break;
caseUIInterfaceOrientationLandscapeRight:
rotation =CGAffineTransformMakeRotation(-startRotation +M_PI * 90.0 /180.0);
break;
caseUIInterfaceOrientationPortraitUpsideDown:
rotation =CGAffineTransformMakeRotation(-startRotation +M_PI * 180.0 /180.0);
break;
default:
rotation =CGAffineTransformMakeRotation(-startRotation +0.0);
break;
}
[UIViewanimateWithDuration:0.2fdelay:0.0options:UIViewAnimationOptionTransitionNone
animations:^{
dialogView.transform = rotation;
}
completion:^(BOOL finished){
// fix errors caused by being rotated one too many times
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
UIInterfaceOrientation endInterfaceOrientation = [[UIApplicationsharedApplication] statusBarOrientation];
if (interfaceOrientation != endInterfaceOrientation) {
// TODO user moved phone again before than animation ended: rotation animation can introduce errors here
}
});
}
];
}
// Handle keyboard show/hide changes
- (void)keyboardWillShow: (NSNotification *)notification
{
CGSize screenSize = [selfcountScreenSize];
CGSize dialogSize = [selfcountDialogSize];
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey]CGRectValue].size;
UIInterfaceOrientation interfaceOrientation = [[UIApplicationsharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
CGFloat tmp = keyboardSize.height;
keyboardSize.height = keyboardSize.width;
keyboardSize.width = tmp;
}
[UIViewanimateWithDuration:0.2fdelay:0.0options: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 = [selfcountScreenSize];
CGSize dialogSize = [selfcountDialogSize];
[UIViewanimateWithDuration:0.2fdelay:0.0options:UIViewAnimationOptionTransitionNone
animations:^{
dialogView.frame =CGRectMake((screenSize.width - dialogSize.width) /2, (screenSize.height - dialogSize.height) /2, dialogSize.width, dialogSize.height);
}
completion:nil
];
}
@end