Swift自定义AlertView
今天项目加新需求,添加积分过期提醒功能:
第一反应就用系统的UIAlertViewController,但是message中积分是需要红色显示。
- // let str = "尊敬的顾客,您有1000积分即将过期,请尽快使用"
- // let attributeStr = changeTextChange(regex: "\\d+", text: str, color: UIColor.red)
- // let alertController = UIAlertController(title: "积分即将过期提醒",
- // message: attributeStr.string, preferredStyle: .alert)
- // let cancelAction = UIAlertAction(title: "兑换菜品", style: .cancel, handler: nil)
- // let okAction = UIAlertAction(title: "暂不兑换", style: .default, handler: {
- // action in
- // print("点击了确定")
- // })
- // alertController.addAction(cancelAction)
- // alertController.addAction(okAction)
- // self.present(alertController, animated: true, completion: nil)
//根据正则表达式改变文字颜色
func changeTextChange(regex: String, text: String, color: UIColor) -> NSMutableAttributedString {
let attributeString = NSMutableAttributedString(string: text)
do {
let regexExpression = try NSRegularExpression(pattern: regex, options: NSRegularExpression.Options())
let result = regexExpression.matches(in: text, options: NSRegularExpression.MatchingOptions(), range: NSMakeRange(0, text.characters.count))
for item in result {
attributeString.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: item.range)
}
} catch {
print("Failed with error: \(error)")
}
return attributeString
}
用NSAttributedstring改变属性了的属性字符串,如果再转换成String,之前的属性就没有了,是否可以直接把NSAttributedstring的属性字符串直接添加到AlertViewController中替换掉要改变字体颜色的string呢?
网上说是有解决办法的,但是没找到解决办法,有知道记得告诉思思哈。
http://www.maccocoa.com/forum/archive/index.php/t-130.html
于是只有自定义AlertView,这样怎么都能实现了。
- //
- // CustomAlertView.swift
- // HaidilaoPad
- //
- // Created by 彭思 on 2018/5/3.
- // Copyright © 2018年 HongHuoTai. All rights reserved.
- //
- import UIKit
- let AlertWidth: CGFloat =
- let AlertHeight: CGFloat =
- let AlertPadding: CGFloat =
- let MenuHeight: CGFloat =
- enum ButtonType {
- case button_OK
- case button_CANCEL
- case button_OTHER
- }
- class AlertItem: NSObject {
- var title: String?
- var type: ButtonType?
- var tag: NSInteger?
- var action: ((_ item:AlertItem) -> Void)?
- }
- class CustomAlertView: UIView {
- // MARK: - Lazy
- lazy var coverView: UIView = {
- let coverView = UIView(frame: self.topView().bounds)
- coverView.backgroundColor = UIColor.black
- coverView.alpha =
- coverView.autoresizingMask = UIViewAutoresizing.flexibleHeight
- return coverView
- }()
- lazy var alertView: UIView = {
- let alertView = UIView(frame: CGRect(x: , y: , width: AlertWidth, height: AlertHeight))
- alertView.center = CGPoint(x: self.frame.size.width/, y: self.frame.size.height/)
- alertView.layer.masksToBounds = true
- alertView.layer.cornerRadius =
- alertView.backgroundColor = UIColor.white
- return alertView
- }()
- lazy var titleLabel: UILabel = {
- let titleLabel = UILabel()
- titleLabel.font = UIFont.boldSystemFont(ofSize: )
- titleLabel.textColor = UIColor.black
- titleLabel.textAlignment = NSTextAlignment.center
- titleLabel.numberOfLines =
- titleLabel.text = self.title
- titleLabel.lineBreakMode = NSLineBreakMode.byCharWrapping
- return titleLabel
- }()
- lazy var topLineView: UIView = {
- let topLineView = UIView()
- topLineView.backgroundColor = UIColor.lightGray
- return topLineView
- }()
- lazy var messageLabel: UILabel = {
- let messageLabel = UILabel()
- messageLabel.font = UIFont.systemFont(ofSize: )
- messageLabel.textAlignment = .center
- messageLabel.numberOfLines =
- messageLabel.textAlignment = NSTextAlignment.center
- messageLabel.lineBreakMode = NSLineBreakMode.byCharWrapping
- return messageLabel
- }()
- var buttonScrollView: UIScrollView?
- var contentScrollView: UIScrollView?
- var items: NSMutableArray?
- var title: String?
- var message: String?
- var buttonWidth: CGFloat?
- var contentView: UIView?
- override init(frame: CGRect) {
- super.init(frame: frame)
- }
- // 便利构造函数
- convenience init(title:String, message:String, messageColor:UIColor?) {
- // 计算frame
- var screenWidth = UIScreen.main.bounds.size.width
- var screenHeight = UIScreen.main.bounds.size.height
- // On iOS7, screen width and height doesn't automatically follow orientation
- if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
- let interfaceOrientation = UIApplication.shared.statusBarOrientation
- if UIInterfaceOrientationIsLandscape(interfaceOrientation) {
- let tmp = screenWidth
- screenWidth = screenHeight
- screenHeight = tmp
- }
- }
- let rect = CGRect(x: , y: , width: screenWidth, height: screenHeight)
- self.init(frame: rect)
- self.items = NSMutableArray()
- self.title = title
- self.message = message
- // 设置views
- self.setupSubViews(messageColor)
- }
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- // MARK: - Setup UI
- func setupSubViews(_ color:UIColor?) {
- self.topView().addSubview(self.coverView)
- self.addSubview(self.alertView)
- // 设置title
- let labelHeight = self.heightOfRow(self.title!, font: , width: AlertWidth - * AlertPadding)
- titleLabel.frame = CGRect(x: AlertPadding, y: AlertPadding, width: AlertWidth - * AlertPadding, height: labelHeight)
- self.alertView.addSubview(self.titleLabel)
- topLineView.frame = CGRect(x: , y: self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height + , width: AlertWidth, height: 0.5)
- self.alertView.addSubview(self.topLineView)
- // 设置message
- let messageHeight = self.heightOfRow(self.message!, font: , width: AlertWidth - * AlertPadding)
- messageLabel.frame = CGRect(x: AlertPadding, y: self.topLineView.frame.origin.y + self.topLineView.frame.size.height + , width: AlertWidth - * AlertPadding, height: messageHeight + * AlertPadding)
- self.alertView.addSubview(self.messageLabel)
- let mesColor:UIColor = color ?? UIColor.black
- messageLabel.textColor = mesColor
- let attributeStr = changeTextChange(regex: "\\d+", text: self.message!, color: UIColor.red)
- self.messageLabel.attributedText = attributeStr
- self.alertView.addSubview(self.messageLabel)
- self.contentScrollView = UIScrollView(frame: CGRect.zero)
- self.alertView.addSubview(self.contentScrollView!)
- UIDevice.current.beginGeneratingDeviceOrientationNotifications()
- NotificationCenter.default.addObserver(self, selector: #selector(CustomAlertView.deviceOrientationDidChange(_:)), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
- }
- // dealloc
- deinit {
- UIDevice.current.endGeneratingDeviceOrientationNotifications()
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
- }
- // override func
- override func layoutSubviews() {
- self.buttonScrollView?.frame = CGRect(x: , y: self.alertView.frame.size.height-MenuHeight,width: self.alertView.frame.size.width, height: MenuHeight);
- self.contentScrollView?.frame = CGRect(x: , y: self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height, width: self.alertView.frame.size.width, height: self.alertView.frame.size.height - MenuHeight);
- self.contentView?.frame = CGRect(x: ,y: ,width: self.contentView!.frame.size.width, height: self.contentView!.frame.size.height);
- if self.contentView != nil {
- self.contentScrollView?.contentSize = self.contentView!.frame.size;
- }
- }
- override func willMove(toSuperview newSuperview: UIView?) {
- self.addButtonItem()
- if self.contentView != nil {
- self.contentScrollView?.addSubview(self.contentView!)
- }
- self.reLayout()
- }
- // show and dismiss
- func topView() -> UIView {
- let window = UIApplication.shared.keyWindow
- return (window?.subviews[])!
- }
- func show() {
- UIView.animate(withDuration: 0.5, animations: { () -> Void in
- self.coverView.alpha = 0.5
- }, completion: { (finished) -> Void in
- })
- self.topView().addSubview(self)
- self.showAnimation()
- }
- //------Preoperties------
- func addButtonWithTitle(_ title:String) -> NSInteger {
- let item = AlertItem()
- item.title = title
- item.action = {(ite:AlertItem)->Void in
- print("no action")
- }
- item.type = ButtonType.button_OK
- self.items?.add(item)
- return (self.items?.index(of: title))!
- }
- func addButton(_ type:ButtonType, title:String, handler:@escaping ((_ item:AlertItem) -> Void)) {
- let item = AlertItem()
- item.title = title
- item.action = handler
- item.type = type
- self.items?.add(item)
- item.tag = self.items?.index(of: item)
- }
- func addButtonItem() {
- self.buttonScrollView = UIScrollView(frame: CGRect(x: , y: self.alertView.frame.size.height - MenuHeight,width: AlertWidth, height: MenuHeight))
- self.buttonScrollView?.bounces = false
- self.buttonScrollView?.showsHorizontalScrollIndicator = false
- self.buttonScrollView?.showsVerticalScrollIndicator = false
- let width:CGFloat
- if (self.buttonWidth != nil) {
- width = self.buttonWidth!
- let a = CGFloat((self.items?.count)!)
- self.buttonScrollView?.contentSize = CGSize(width: a * width, height: MenuHeight)
- } else {
- width = (self.alertView.frame.size.width) / CGFloat((self.items?.count)!)
- }
- self.items?.enumerateObjects({ (item, idx, stop) in
- let button = UIButton(type: UIButtonType.system)
- button.frame = CGRect(x: CGFloat(idx) * width, y: , width: width, height: MenuHeight)
- button.backgroundColor = UIColor.white
- button.layer.shadowColor = UIColor.gray.cgColor
- button.layer.shadowRadius = 0.5
- button.layer.shadowOpacity =
- button.layer.shadowOffset = CGSize.zero
- button.layer.masksToBounds = false
- button.tag = + idx
- button.setTitleColor(UIColor.darkGray, for: .normal)
- let ite = item as! AlertItem
- button.setTitle(ite.title, for: UIControlState())
- button.setTitle(ite.title, for: UIControlState.selected)
- button.titleLabel?.font = UIFont.boldSystemFont(ofSize: (button.titleLabel?.font.pointSize)!)
- button.addTarget(self, action: #selector(CustomAlertView.buttonTouched(_:)), for: UIControlEvents.touchUpInside)
- self.buttonScrollView?.addSubview(button)
- // 按钮边框
- if idx != (self.items?.count)! - {
- let seprateLineVer = UIView(frame: CGRect(x: width - , y: , width: 0.5, height: MenuHeight))
- seprateLineVer.backgroundColor = UIColor.lightGray
- button.addSubview(seprateLineVer)
- }
- let seprateLineHor = UIView(frame: CGRect(x: , y: , width: self.buttonScrollView!.frame.size.width, height: 0.5))
- seprateLineHor.backgroundColor = UIColor.lightGray
- self.buttonScrollView?.addSubview(seprateLineHor)
- })
- self.alertView.addSubview(self.buttonScrollView!)
- }
- @objc func buttonTouched(_ button:UIButton) {
- let item:AlertItem = self.items![button.tag - ] as! AlertItem
- if (item.action != nil) {
- item.action!(item)
- }
- self.dismiss()
- }
- func reLayout() {
- var plus:CGFloat
- if self.contentView != nil {
- plus = (self.contentView!.frame.size.height) - ((self.alertView.frame.size.height) - MenuHeight)
- } else {
- plus = (self.messageLabel.frame.origin.y) + (self.messageLabel.frame.size.height) - ((self.alertView.frame.size.height) - MenuHeight)
- }
- plus = max(, plus)
- let height = min(self.screenBounds().size.height - MenuHeight, (self.alertView.frame.size.height) + plus)
- self.alertView.frame = CGRect(x: self.alertView.frame.origin.x, y: self.alertView.frame.origin.y, width: AlertWidth, height: height)
- self.alertView.center = self.center
- self.setNeedsDisplay()
- self.setNeedsLayout()
- }
- func dismiss() {
- self.hideAnimation()
- }
- // MARK: - showAnimation
- func showAnimation() {
- let popAnimation = CAKeyframeAnimation(keyPath: "transform")
- popAnimation.duration = 0.4
- popAnimation.values = [
- NSValue.init(caTransform3D: CATransform3DMakeScale(0.01, 0.01, 1.0)),
- NSValue.init(caTransform3D: CATransform3DMakeScale(1.1, 1.1, 1.0)),
- NSValue.init(caTransform3D: CATransform3DMakeScale(0.9, 0.9, 1.0)),
- NSValue.init(caTransform3D: CATransform3DIdentity)
- ]
- popAnimation.keyTimes = [0.2, 0.5, 0.75, 1.0]
- popAnimation.timingFunctions = [
- CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut),
- CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut),
- CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
- ]
- self.alertView.layer.add(popAnimation, forKey: nil)
- }
- func hideAnimation() {
- UIView.animate(withDuration: 0.4, animations: { () -> Void in
- self.coverView.alpha = 0.0
- self.alertView.alpha = 0.0
- }, completion: { (finished) -> Void in
- self.removeFromSuperview()
- })
- }
- // handle device orientation changes
- @objc func deviceOrientationDidChange(_ notification:Notification) {
- self.frame = self.screenBounds()
- UIView.animate(withDuration: 0.2, delay: 0.0, options: UIViewAnimationOptions(), animations: { () -> Void in
- self.reLayout()
- }) { (finished) -> Void in
- }
- }
- //------Tools-------
- // 计算frame
- func screenBounds() -> CGRect {
- var screenWidth = UIScreen.main.bounds.size.width
- var screenHeight = UIScreen.main.bounds.size.height
- // On iOS7, screen width and height doesn't automatically follow orientation
- if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
- let interfaceOrientation = UIApplication.shared.statusBarOrientation
- if UIInterfaceOrientationIsLandscape(interfaceOrientation) {
- let tmp = screenWidth
- screenWidth = screenHeight
- screenHeight = tmp
- }
- }
- return CGRect(x: , y: , width: screenWidth, height: screenHeight)
- }
- // 计算字符串高度
- func heightOfRow(_ text:String, font:CGFloat, width:CGFloat) -> CGFloat {
- let size:CGSize = text.boundingRect(with: CGSize(width: width, height: ), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: font)], context: nil).size
- return size.height;
- }
- //根据正则表达式改变文字颜色
- func changeTextChange(regex: String, text: String, color: UIColor) -> NSMutableAttributedString {
- let attributeString = NSMutableAttributedString(string: text)
- do {
- let regexExpression = try NSRegularExpression(pattern: regex, options: NSRegularExpression.Options())
- let result = regexExpression.matches(in: text, options: NSRegularExpression.MatchingOptions(), range: NSMakeRange(, text.characters.count))
- for item in result {
- attributeString.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: item.range)
- }
- } catch {
- print("Failed with error: \(error)")
- }
- return attributeString
- }
- }
实现效果如下:
Swift自定义AlertView的更多相关文章
- [IOS]swift自定义uicollectionviewcell
刚刚接触swift以及ios,不是很理解有的逻辑,导致某些问题.这里分享一下swift自定义uicollectionviewcell 首先我的viewcontroller不是直接继承uicollect ...
- iOS 第三方自定义Alertview项目MBProcessHud中的重要代码分析
做ios,弹出一个自定义的alertview挺常见的.ios7以前,我们可以对系统的UIAlertView进行一点操作,实现一点简单的定制,但是ios7不再允许我们这样做了.因此,我们需要自己创建一个 ...
- Swift 自定义打印方法
Swift 自定义打印方法 代码如下 // MARK:- 自定义打印方法 func MLLog<T>(_ message : T, file : String = #file, funcN ...
- 兼容iOs7的自定义alertView
转载请注明出处. 升级到ios7后,旧项目中使用的继承UIAlertView的自定义alertview无法正常显示了,无奈只好换思路去实现,改成从当前keywindow下创建要显示的alertview ...
- 自定义AlertView的方法和改变Alert的弹出位置以及其宽度
此方法在IOS7中不适合 一.自定义AlertView 1.首先新建一个OC类继承与AlertView. 2.然后再.m中添加方法 - (void)layoutSubviews 可以再这个方法里边改变 ...
- 自定义AlertView(Swift)
MyAlertView.swift // Pop Up Styles enum MyAlertViewStyle: Int { case success case error case notice ...
- swift 自定义弹框
// // ViewController.swift // animationAlert // // Created by su on 15/12/9. // Copyright © 2015 ...
- swift 自定义图片轮播视图
Swift封装图片轮播视图: import UIKit class XHAdLoopView: UIView { private var pageControl : UIPageControl? pr ...
- Swift 自定义Subscript
Swift可以方便给自定义类加下标,其中参数和返回值可以在类里定义为任意类型: subscript(parameters) -> ReturnType { get { //return some ...
随机推荐
- Linux入侵类问题排查思路
深入分析,查找入侵原因 一.检查隐藏帐户及弱口令 检查服务器系统及应用帐户是否存在 弱口令: 检查说明:检查管理员帐户.数据库帐户.MySQL 帐户.tomcat 帐户.网站后台管理员帐户等密码设置是 ...
- IIS 使用 web.config 实现从 http 自动301跳转到 https 的方法
现在很多网站为了安全,开启了 SSL 连接,那么开启 SSL 连接之后,如何将对应的 http 访问自动跳转到 https 上呢?之前介绍了 IIS 用 web.config 做域名的301跳转的方法 ...
- python字符的表示格式
%% 百分号标记 #就是输出一个% %c 字符及其ASCII码%s 字符串%d 有符号整数(十进制)%u 无符号整数(十进制)%o 无符号整数(八进制)%x 无符号整数(十六进制)%X 无符号整数(十 ...
- python - 手机号正则匹配
Python 手机号正则匹配 # -*- coding:utf-8 -*- import re def is_phone(phone): phone_pat = re.compile('^(13\d| ...
- Discrete Cosine Transform
离散余弦变换 由于实信号傅立叶变换的共轭对称性,导致DFT后在频域中有一半的数据冗余.离散余弦变换(DCT)在处理实信号时比离散傅立叶(DFT)变换更具优势.在处理声音信号这类实信号时,DFT得到的结 ...
- zzulioj - 2628: 小新的字母广场
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2628 题目描述 放假了,小新决定出去散散心,于是他来到了著名的字母广场.这个广场是由n*m块砖 ...
- vlang 试用
vlang 是最近出来的一门编程语言,集成了rust,golang, 等语言的特性,轻量.简洁.编译 快速,详细的比价参数可以参考官方文档 安装 目前尽管官方提供了linux以及mac 的二进制文件, ...
- vue中前端弹窗队列展示
在前端写一个弹窗可能很简单,那如果同时有多个弹窗呢 这样的话就要考虑弹窗的展示问题,肯定是不能叠加在一起的,这时候就要通过队列(先进先出)来展示 思路就是根据队列来实现,至于具体的实现方式,可以在项目 ...
- 【洛谷P5019】铺设道路
题目链接 众所周知,这道题和积木大赛是同一道题 题意就是给出一段自然数序列,每次操作\((L,R)\)把区间\([L,R]\)的数全部减一,不允许出现负数,问把序列变为零的最小操作次数 贪心做法 样例 ...
- (8)Go Map
Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现. Map map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用. map定义 G ...