概述

由于讨厌系统自带的alertView只能通过点击按钮才能关闭。你说万一按钮区域都是功能性的操作呢(这可不是我胡思乱想哦,要怪就产品的想法吧,呵呵哒),所以我们还是应该备有一个带有“X”(关闭按钮,为什么是叫X,因为X这个标志很明显嘛~)的alertView。

详细

一、程序实现

1、程序结构

2、实现思路与代码

XBAlertView是作为显示弹出框的入口,在初始化XBAlertView示例时,会将弹出框除了按钮部分全都设置好。而按钮部分采用UICollectionView来实现(因为有可能有多个按钮,这样方便扩展)。

- (void)setupContentView{
//title
self.alertTitleLabel = [[UILabel alloc] init];
self.alertTitleLabel.font = [UIFont boldSystemFontOfSize:17.0f];
self.alertTitleLabel.textAlignment = NSTextAlignmentCenter;
self.alertTitleLabel.frame = CGRectMake(TitleHorizontalOffset, TitleMarginTop, SelfWidth - TitleHorizontalOffset * 2, self.alertTitleLabel.font.lineHeight);
[self addSubview:self.alertTitleLabel]; //content
CGFloat contentLabelWidth = SelfWidth - ContentHorizontalOffset * 2;
CGFloat contentH = [self heightWithContent:_content byWidth:contentLabelWidth andFontSize:13 andLineSpacing:3];
self.alertContentLabel = [[UILabel alloc] initWithFrame:CGRectMake(ContentHorizontalOffset, CGRectGetMaxY(self.alertTitleLabel.frame) + ContentMarginTop, contentLabelWidth, contentH)];
self.alertContentLabel.numberOfLines = 0;
self.alertContentLabel.textAlignment = NSTextAlignmentCenter;
self.alertContentLabel.font = [UIFont systemFontOfSize:13.0f];
[self addSubview:self.alertContentLabel]; //self
CGFloat selfHeight = TitleMarginTop + self.alertTitleLabel.font.lineHeight + ContentMarginTop + contentH + BtnMarginTop + kButtonHeight;
CGFloat selfMarginLeft = (ScreenWidth - SelfWidth) / 2;
self.frame = CGRectMake(selfMarginLeft, (ScreenHeight - selfHeight) / 2, SelfWidth, selfHeight);
self.clipsToBounds = YES;
self.layer.cornerRadius = 10.0;
self.backgroundColor = [UIColor whiteColor]; //collectionView
[self addSubview:self.collectionView];
_collectionView.delegate = self;
_collectionView.dataSource = self;
[_collectionView registerNib:[UINib nibWithNibName:@"XBAlertBtnCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:btnCellOneID];
[_collectionView registerNib:[UINib nibWithNibName:@"XBAlertBtnCellTwo" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:btnCellTwoID]; //X按钮
UIButton *xButton = [UIButton buttonWithType:UIButtonTypeCustom];
[xButton setImage:[UIImage imageNamed:@"btn_close_normal.png"] forState:UIControlStateNormal];
[xButton setImage:[UIImage imageNamed:@"btn_close_selected.png"] forState:UIControlStateHighlighted];
xButton.frame = CGRectMake(self.frame.size.width - 32, 0, 32, 32);
[self addSubview:xButton];
[xButton addTarget:self action:@selector(dismissAlert) forControlEvents:UIControlEventTouchUpInside];
}

为了能够切合原生方式的调用,提供了-(void)addAction:(dispatch_block_t)actionBlock withTitle:(NSString*)title方法,该方法用于向XBAlertView添加按钮以及对应的响应block。

-(void)addAction:(dispatch_block_t)actionBlock withTitle:(NSString*)title{
if(actionBlock && ![self isBlankString:title]){
[self.blockArray addObject:actionBlock];
[self.btnTitleArray addObject:title];
}
}

调用后会先保存到数组当中。

在这之后,调用方调用XBAlertView的show方法进行展示。

- (void)show
{
if(self.btnTitleArray.count == 0 || self.btnTitleArray.count > 2){
//更新view的frame
[self updateFrame];
}
[self.collectionView reloadData];
UIViewController *topVC = [self appRootViewController];
[topVC.view addSubview:self];
}

show方法首先会根据两个数组是否有值来决定是否更新collectionView的frame。之后调用collectionView的reloadData,数据源就是这两个数组。这样加载后collectionView就有了需要展示的按钮。

然后获取[UIApplication sharedApplication].keyWindow.rootViewController,在这个控制器的view上添加上已经布局好的XBAlertView。

但是为了营造阴影效果,在XBAlertView被添加到父view之前,会调用以下方法创建一个遮罩层。这样就能达到显示的要求。

- (void)willMoveToSuperview:(UIView *)newSuperview
{
if (newSuperview == nil) {
return;
}
UIViewController *topVC = [self appRootViewController]; if (!self.backImageView) {
self.backImageView = [[UIView alloc] initWithFrame:topVC.view.bounds];
self.backImageView.backgroundColor = [UIColor blackColor];
self.backImageView.alpha = 0.6f;
self.backImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
}
[topVC.view addSubview:self.backImageView];
CGRect afterFrame = CGRectMake((CGRectGetWidth(topVC.view.bounds) - self.frame.size.width) * 0.5, (CGRectGetHeight(topVC.view.bounds) - self.frame.size.height) * 0.5, self.frame.size.width, self.frame.size.height);
self.frame = afterFrame;
[super willMoveToSuperview:newSuperview];
}

那么接下来就是点击响应了,因为每个按钮就是collectionView的一个cell,所以按钮的点击就转为了cell的didSelectItemAtIndexPath方法。在该方法中根据索引从前面保存好的数组取出相对应的block,并调用

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
dispatch_block_t block = self.blockArray[indexPath.row];
block();
[self dismissAlert];
}

那么为了将隐藏弹出框封装到里面,会主动调用dismissAlert方法隐藏弹出框。

二、运行效果

下载解压后,直接用xcode打开,即可运行

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

带有关闭按钮的alertView的更多相关文章

  1. 自定义带有uitableview的alertview对话框

    #import <UIKit/UIKit.h> typedef void(^MyCompleteHandler) (NSString *selectString); @interface ...

  2. jbox使用总结

    jbox是一个不错的插件 当使用get打开新页面的时候,可以使用h.对像ID来获得对像ID的值 Js代码 js代码: /** * @description: test * @author: BrinP ...

  3. bootstrap学习之二-组件

    一.bootstrap字体图标 以span的形式出现,通常可以用于一个button或者其他元素的内文本, <span class="glyphicon glyphicon-sort-b ...

  4. 转--2014年最新810多套android源码2.46GB免费一次性打包下载

    转载自:http://www.eoeandroid.com/thread-497046-1-1.html 感谢该博客主人无私奉献~~ 下面的源码是从今年3月份开始不断整理源码区和其他网站上的安卓例子源 ...

  5. 2014年最新720多套Android源码2.0GB免费一次性打包下载

    之前发过一个帖子,但是那个帖子有点问题我就重新发一个吧,下面的源码是我从今年3月份开始不断整理源码区和其他网站上的android源码,目前总共有720套左右,根据实现的功能被我分成了100多个类,总共 ...

  6. Bootstrap警告框

    前面的话 在网站中,网页总是需要和用户一起做沟通与交流.特别是当用户操作上下文为用户提供一些有效的警示框,比如说告诉用户操作成功.操作错误.提示或者警告等.在Bootstrap框架有一个独立的组件,实 ...

  7. SCLAlertView-Swift

    SCLAlertView-Swift https://github.com/vikmeup/SCLAlertView-Swift   Animated Alert View written in Sw ...

  8. Bootstrap学习-其它内置组件

    1.缩略图(一) 缩略图在网站中最常用的地方就是产品列表页面,一行显示几张图片,有的在图片底下(左侧或右侧)带有标题.描述等信息.Bootstrap框架将这一部独立成一个模块组件.并通过“thumbn ...

  9. Bootstrap-other内置组件

    1.缩略图 缩略图在网站中最常用的地方就是产品列表页面,一行显示几张图片,有的在图片底下(左侧或右侧)带有标题.描述等信息.Bootstrap框架将这一部独立成一个模块组件.并通过“thumbnail ...

随机推荐

  1. 基础知识(09) -- Spring 概述

    Spring概述-------------------------------------------------------------------------主要内容: 1.Spring是什么 2 ...

  2. CSS的flex布局(转载)

    我们之前已经学过一些布局模型,比如说浮动,绝对定位等等,但是这些布局方式一是不够简洁,而是使用的范围确实是太窄了. flex模型拥有比较多的属性,来设置多样的布局方式,接下来我们就详细介绍各种属性对布 ...

  3. GIT 提交步骤

    1.提交 git add .

  4. HDU 4678 Mine (2013多校8 1003题 博弈)

    Mine Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  5. Wide-range regulator delivers 12V, 3A output from 16 to 100V source

    Synchronous buck regulators offer high efficiency and are popular in applications in which available ...

  6. LwIP buffer management, memory configuration options

    http://www.st.com/st-web-ui/static/active/cn/resource/technical/document/application_note/DM00036052 ...

  7. MySql清空表的方法介绍 : truncate table 表名

    清空某个mysql表中所有内容 delete from 表名; truncate table 表名; 不带where参数的delete语句可以删除mysql表中所有内容,使用truncate tabl ...

  8. windows端口

    端口可分为3大类: 1) 公认端口(Well Known Ports):从0到1023,它们紧密绑定于一些服务.通常这些端口的通讯明确表明了某种服务的协议.例如:80端口实际上总是HTTP通讯. 2) ...

  9. ABC定制视图导航控制器

      ABCustomUINavigationController  ABC定制视图导航控制器   Subclass of UINavigationController for overwriting ...

  10. Python学习(六)模块 —— 标准模块

    Python 标准模块 Python 带有一个标准模块库,并发布有独立的文档(库参考手册).对于程序员而言,标准库与语言本身同样重要,它好比一个百宝箱,能为各种常见的任务提供完美的解决方案. 这边简单 ...