123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- //
- // TYAlertController.m
- // TYAlertControllerDemo
- //
- // Created by tanyang on 15/9/1.
- // Copyright (c) 2015年 tanyang. All rights reserved.
- //
- #import "TYAlertController.h"
- #import "UIView+TYAutoLayout.h"
- @interface TYAlertController ()
- @property (nonatomic, strong) UIView *alertView;
- @property (nonatomic, assign) TYAlertControllerStyle preferredStyle;
- @property (nonatomic, assign) TYAlertTransitionAnimation transitionAnimation;
- @property (nonatomic, assign) Class transitionAnimationClass;
- @property (nonatomic, weak) UITapGestureRecognizer *singleTap;
- @property (nonatomic, strong) NSLayoutConstraint *alertViewCenterYConstraint;
- @property (nonatomic, assign) CGFloat alertViewCenterYOffset;
- @end
- @implementation TYAlertController
- #pragma mark - init
- - (instancetype)init
- {
- if (self = [super init]) {
- [self configureController];
- }
- return self;
- }
- - (id)initWithCoder:(NSCoder *)aDecoder
- {
- if (self = [super initWithCoder:aDecoder]) {
- [self configureController];
- }
- return self;
- }
- - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
- [self configureController];
- }
- return self;
- }
- - (instancetype)initWithAlertView:(UIView *)alertView preferredStyle:(TYAlertControllerStyle)preferredStyle transitionAnimation:(TYAlertTransitionAnimation)transitionAnimation transitionAnimationClass:(Class)transitionAnimationClass
- {
- if (self = [self initWithNibName:nil bundle:nil]) {
- _alertView = alertView;
- _preferredStyle = preferredStyle;
- _transitionAnimation = transitionAnimation;
- _transitionAnimationClass = transitionAnimationClass;
- }
- return self;
- }
- + (instancetype)alertControllerWithAlertView:(UIView *)alertView
- {
- return [[self alloc]initWithAlertView:alertView
- preferredStyle:TYAlertControllerStyleAlert
- transitionAnimation:TYAlertTransitionAnimationFade
- transitionAnimationClass:nil];
- }
- + (instancetype)alertControllerWithAlertView:(UIView *)alertView preferredStyle:(TYAlertControllerStyle)preferredStyle
- {
- return [[self alloc]initWithAlertView:alertView
- preferredStyle:preferredStyle
- transitionAnimation:TYAlertTransitionAnimationFade
- transitionAnimationClass:nil];
- }
- + (instancetype)alertControllerWithAlertView:(UIView *)alertView preferredStyle:(TYAlertControllerStyle)preferredStyle transitionAnimation:(TYAlertTransitionAnimation)transitionAnimation
- {
- return [[self alloc]initWithAlertView:alertView
- preferredStyle:preferredStyle
- transitionAnimation:transitionAnimation
- transitionAnimationClass:nil];
- }
- + (instancetype)alertControllerWithAlertView:(UIView *)alertView preferredStyle:(TYAlertControllerStyle)preferredStyle transitionAnimationClass:(Class)transitionAnimationClass
- {
- return [[self alloc]initWithAlertView:alertView
- preferredStyle:preferredStyle
- transitionAnimation:TYAlertTransitionAnimationCustom
- transitionAnimationClass:transitionAnimationClass];
- }
- #pragma mark - life cycle
- - (void)viewDidLoad {
- [super viewDidLoad];
- // Do any additional setup after loading the view.
- self.view.backgroundColor = [UIColor clearColor];
-
- [self addBackgroundView];
-
- [self addSingleTapGesture];
-
- [self configureAlertView];
-
- [self.view layoutIfNeeded];
-
- if (_preferredStyle == TYAlertControllerStyleAlert) {
- // UIKeyboard Notification
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
- }
-
- }
- - (void)viewWillAppear:(BOOL)animated
- {
- [super viewWillAppear:animated];
-
- if (_viewWillShowHandler) {
- _viewWillShowHandler(_alertView);
- }
- }
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
-
- if (_viewDidShowHandler) {
- _viewDidShowHandler(_alertView);
- }
- }
- - (void)viewWillDisappear:(BOOL)animated
- {
- [super viewWillDisappear:animated];
-
- if (_viewWillHideHandler) {
- _viewWillHideHandler(_alertView);
- }
- }
- - (void)viewDidDisappear:(BOOL)animated
- {
- [super viewDidDisappear:animated];
-
- if (_viewDidHideHandler) {
- _viewDidHideHandler(_alertView);
- }
- }
- - (void)addBackgroundView
- {
- if (_backgroundView == nil) {
- UIView *backgroundView = [[UIView alloc]init];
- backgroundView.backgroundColor = _backgroundColor;
- _backgroundView = backgroundView;
- }
- _backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
- [self.view insertSubview:_backgroundView atIndex:0];
- [self.view addConstraintToView:_backgroundView edgeInset:UIEdgeInsetsZero];
- }
- - (void)setBackgroundView:(UIView *)backgroundView
- {
- if (_backgroundView == nil) {
- _backgroundView = backgroundView;
- } else if (_backgroundView != backgroundView) {
- backgroundView.translatesAutoresizingMaskIntoConstraints = NO;
- [self.view insertSubview:backgroundView aboveSubview:_backgroundView];
- [self.view addConstraintToView:backgroundView edgeInset:UIEdgeInsetsZero];
- backgroundView.alpha = 0;
- [UIView animateWithDuration:0.3 animations:^{
- backgroundView.alpha = 1;
- } completion:^(BOOL finished) {
- [_backgroundView removeFromSuperview];
- _backgroundView = backgroundView;
- [self addSingleTapGesture];
- }];
- }
- }
- - (void)addSingleTapGesture
- {
- self.view.userInteractionEnabled = YES;
- _backgroundView.userInteractionEnabled = YES;
- UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
- singleTap.enabled = _backgoundTapDismissEnable;
-
- [_backgroundView addGestureRecognizer:singleTap];
- _singleTap = singleTap;
- }
- - (void)setBackgoundTapDismissEnable:(BOOL)backgoundTapDismissEnable
- {
- _backgoundTapDismissEnable = backgoundTapDismissEnable;
- _singleTap.enabled = backgoundTapDismissEnable;
- }
- #pragma mark - configure
- - (void)configureController
- {
- self.providesPresentationContextTransitionStyle = YES;
- self.definesPresentationContext = YES;
- self.modalPresentationStyle = UIModalPresentationCustom;
- self.transitioningDelegate = self;
-
- _backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4];
- _backgoundTapDismissEnable = NO;
- _alertStyleEdging = 15;
- _actionSheetStyleEdging = 0;
- }
- - (void)configureAlertView
- {
- if (_alertView == nil) {
- NSLog(@"%@: alertView is nil",NSStringFromClass([self class]));
- return;
- }
- _alertView.userInteractionEnabled = YES;
- [self.view addSubview:_alertView];
- _alertView.translatesAutoresizingMaskIntoConstraints = NO;
- switch (_preferredStyle) {
- case TYAlertControllerStyleActionSheet:
- [self layoutActionSheetStyleView];
- break;
- case TYAlertControllerStyleAlert:
- [self layoutAlertStyleView];
- break;
- default:
- break;
- }
- }
- - (void)configureAlertViewWidth
- {
- // width, height
- if (!CGSizeEqualToSize(_alertView.frame.size,CGSizeZero)) {
- [_alertView addConstraintWidth:CGRectGetWidth(_alertView.frame) height:CGRectGetHeight(_alertView.frame)];
-
- }else {
- BOOL findAlertViewWidthConstraint = NO;
- for (NSLayoutConstraint *constraint in _alertView.constraints) {
- if (constraint.firstAttribute == NSLayoutAttributeWidth) {
- findAlertViewWidthConstraint = YES;
- break;
- }
- }
-
- if (!findAlertViewWidthConstraint) {
- [_alertView addConstraintWidth:CGRectGetWidth(self.view.frame)-2*_alertStyleEdging height:0];
- }
- }
- }
- #pragma mark - layout
- - (void)layoutAlertStyleView
- {
- // center X
- [self.view addConstraintCenterXToView:_alertView centerYToView:nil];
-
- [self configureAlertViewWidth];
-
- // top Y
- _alertViewCenterYConstraint = [self.view addConstraintCenterYToView:_alertView constant:0];
-
- if (_alertViewOriginY > 0) {
- [_alertView layoutIfNeeded];
- _alertViewCenterYOffset = _alertViewOriginY - (CGRectGetHeight(self.view.frame) - CGRectGetHeight(_alertView.frame))/2;
- _alertViewCenterYConstraint.constant = _alertViewCenterYOffset;
- }else{
- _alertViewCenterYOffset = 0;
- }
- }
- - (void)layoutActionSheetStyleView
- {
- // remove width constaint
- for (NSLayoutConstraint *constraint in _alertView.constraints) {
- if (constraint.firstAttribute == NSLayoutAttributeWidth) {
- [_alertView removeConstraint: constraint];
- break;
- }
- }
-
- // add edge constraint
- [self.view addConstraintWithView:_alertView topView:nil leftView:self.view bottomView:self.view rightView:self.view edgeInset:UIEdgeInsetsMake(0, _actionSheetStyleEdging, 0, -_actionSheetStyleEdging)];
-
- if (CGRectGetHeight(_alertView.frame) > 0) {
- // height
- [_alertView addConstraintWidth:0 height:CGRectGetHeight(_alertView.frame)];
- }
- }
- - (void)dismissViewControllerAnimated:(BOOL)animated
- {
- [self dismissViewControllerAnimated:YES completion:self.dismissComplete];
- }
- #pragma mark - action
- - (void)singleTap:(UITapGestureRecognizer *)sender
- {
- [self dismissViewControllerAnimated:YES];
- }
- #pragma mark - notification
- - (void)keyboardWillShow:(NSNotification*)notification
- {
- CGRect keyboardRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
-
- CGFloat alertViewBottomEdge = (CGRectGetHeight(self.view.frame) - CGRectGetHeight(_alertView.frame))/2 - _alertViewCenterYOffset;
-
- //当开启热点时,向下偏移20px
- //修复键盘遮挡问题
- CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
- CGFloat differ = CGRectGetHeight(keyboardRect) - alertViewBottomEdge;
- //修复:输入框获取焦点时,会重复刷新,导致输入框文章偏移一下
- if (_alertViewCenterYConstraint.constant == -differ -statusBarHeight) {
- return;
- }
-
- if (differ >= 0) {
- _alertViewCenterYConstraint.constant = _alertViewCenterYOffset - differ - statusBarHeight;
- [UIView animateWithDuration:0.25 animations:^{
- [self.view layoutIfNeeded];
- }];
- }
- }
- - (void)keyboardWillHide:(NSNotification*)notification
- {
- _alertViewCenterYConstraint.constant = _alertViewCenterYOffset;
- [UIView animateWithDuration:0.25 animations:^{
- [self.view layoutIfNeeded];
- }];
- }
- - (void)didReceiveMemoryWarning {
- [super didReceiveMemoryWarning];
- // Dispose of any resources that can be recreated.
- }
- - (void)dealloc
- {
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
- }
- @end
|