概述

由于讨厌系统自带的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. [转][Android] ListView中getView的原理+如何在ListView中放置多个item

      ListView 和 Adapter 的基础 工作原理: ListView 针对List中每个item,要求 adapter “给我一个视图” (getView). 一个新的视图被返回并显示 如果 ...

  2. Codeforces Beta Round #10 A. Power Consumption Calculation 水题

    A. Power Consumption Calculation 题目连接: http://www.codeforces.com/contest/10/problem/A Description To ...

  3. CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 二分+拓扑排序

    D. Robot Rapping Results Report 题目连接: http://www.codeforces.com/contest/655/problem/D Description Wh ...

  4. div中内容超出自动换行

    下面以table中td的内容超出为例说明: 首先: td { display: block; } 然后:给td设置css样式: 1.  td { word-wrap: break-word; } 2. ...

  5. URAL 1099. Work Scheduling (一般图匹配带花树)

    1099. Work Scheduling Time limit: 0.5 secondMemory limit: 64 MB There is certain amount of night gua ...

  6. Inverted bipolar transistor doubles as a signal clamp

    A number of circuits, such as level detectors and AM demodulators, benefit from a rectifier with a l ...

  7. JavaScript中typeof详解

    [范围]typeof返回值范围: typeof返回值对应 类型 结果 String "string" Number "number" Boolean " ...

  8. jdk1.8 foreach

    lambda 表达式效率非常低,测试代码可以看到大概3~5倍的差距 遍历Map的方式有很多,通常场景下我们需要的是遍历Map中的Key和Value,那么推荐使用的: public static voi ...

  9. 配置Android-Annotation (github20大开源:http://www.eoeandroid.com/thread-278980-1-1.html)

    1. 把androidannotations-X.X.X-api.jar 放在libs文件夹 2. 把androidannotations-X.X.X.jar 放在文件夹compile-libs,1与 ...

  10. H.264远程视频监控系统

    由usb摄像头驱动,h264编码库,采集read_video,传输,客户端显示组成 读取摄像头数据缓冲区是否有帧数据收到,有数据收到就读取数据并进行H264编码,把数据发送到socket发送到客户端. ...