写在之前
系统的弹框虽然很好看,但是有时候无法完全满足UI设计的需求,比如说中间要显示一个输入框,或者要放置一张图片,这里介绍一个很早之前的自定义弹框库,这个自定义弹框sdk写的很细致,定制性很强,几乎可以做到完全改写,附下载链接
与系统弹框不同的是这个库支持以下功能:
1. 仿原生弹框样式
2. 可自定义下方按钮颜色字体个数,可自定义title文字、message文字样式
3. 可自定义弹框大小高度,中间支持大图滑动
4. 支持按钮上方横线隐藏显示
5. 可传入自定义contentView进去
6. 可以定义自己控制alert消失时间
7. 可以同时管理多个弹框,最后面调用的
先展示一下支持的弹框样式:
代码解析:
整个一个alert由三大块组成,顶部一个滚动视图放title,中间一个滚动视图contentScrollView放contentView,下面一个滚动视图bottomScrollView放按钮
视图结构如下:
CXAlertButtonContainerView继承UIScrollView 组成部分:
CXAlertButtonItem继承自UIButton成员结构如下:
类名 | 属性类型 | 属性名称 |
---|---|---|
NSString | title | |
CXAlertButtonItem | CXAlertViewButtonType | type |
CXAlertButtonHandler | action | |
BOOL | defaultRightLineVisible |
CXAlertViewController 用来进行弹框的controller
下面介绍一下整个sdk从创建到show的代码逻辑:
1、创建逻辑:
- 走initialize方法初始化一些固定常规信息,这边不调用各属性的set方法-主要是不怎么改变的信息
- 首先判断传入的是message就创建一个Label传入作为contentView
- 走initWithTitle:contentView:cancelButtonTitle:方法初始化一些自定义信息
- 创建三个滚动视图
- 有add按钮就去添加按钮
- 调用show方法
- 调用各种属性set信息,这个之后各种变量才会有值,之前都是没有值的
- 调用layoutSubviews
2、show逻辑:
假如一次性弹多个弹框ABC,他会先显示A然后隐藏A,显示B隐藏B,显示C,dismissC再去显示B,Bdismiss之后显示A,其实这边可以考虑参考系统的每次只让显示一个Alert,后面弹出的无效
变量介绍:
- _containerView用来放整个视图的
- __cx_pending_alert_queue:NSMutableArray 存放本alert是否被添加
- __cx_alert_animating:BOOL 是否动画中
- __cx_alert_current_view: CXAlertView 记录当前被弹出的alert
- __cx_alert_background_window: 做半透明背景色渐变的window
- isVisible: 当前弹框是否可见
- layoutDirty: 防止validateLayout被多次调用
- willShowHandler 各种时机的block回调
函数调用中逻辑
- __cx_alert_background_window背景色0.4纯黑色,0.3秒
alpha
在内从0->1 - 创建新window 根视图为CXAlertViewController,细化为下面测操作
- 直接切换当前为新window
- __cx_alert_background_window背景色0.4纯黑色,0.3秒
CXAlertViewController内部进行如下操作:
1. self.view = self.alertView
1. self.alertView 调用setup
1. setup内部操作:
(1、初始化弹框的背景视图_containerView
2、检测初始化内部三块滚动视图初始化情况,未初始化就初始化
3、设置各块视图的位置大小,
4、动画展示alert)
3、dismiss逻辑:
- __cx_pending_alert_queue 移除self
- _containerView 0.25秒内
alpha
从 1->0 - __cx_alert_background_window 0.3秒内
alpha
从 1->0 - 执行dismissComplete,由于可以显示多个弹框,检测有没有之前的弹框重新show出来
tips
由于这个新的alert类应用于项目中还没有很长时间,所以应该会有缺陷,以后会渐渐改进
现在的alert支持多弹框,在考虑要不要改成系统类似只能弹出一个框
现在的点击事件是在按钮被点击的时候直接回调block,考虑改成消失之后再去调用