今天项目加新需求,添加积分过期提醒功能:

第一反应就用系统的UIAlertViewController,但是message中积分是需要红色显示。

  1. // let str = "尊敬的顾客,您有1000积分即将过期,请尽快使用"
  2. // let attributeStr = changeTextChange(regex: "\\d+", text: str, color: UIColor.red)
  3. // let alertController = UIAlertController(title: "积分即将过期提醒",
  4. // message: attributeStr.string, preferredStyle: .alert)
  5. // let cancelAction = UIAlertAction(title: "兑换菜品", style: .cancel, handler: nil)
  6. // let okAction = UIAlertAction(title: "暂不兑换", style: .default, handler: {
  7. // action in
  8. // print("点击了确定")
  9. // })
  10. // alertController.addAction(cancelAction)
  11. // alertController.addAction(okAction)
  12. // self.present(alertController, animated: true, completion: nil)

//根据正则表达式改变文字颜色

  1.  

func changeTextChange(regex: String, text: String, color: UIColor) -> NSMutableAttributedString {

  1.  

let attributeString = NSMutableAttributedString(string: text)

  1.  

do {

  1.  

let regexExpression = try NSRegularExpression(pattern: regex, options: NSRegularExpression.Options())

  1.  

let result = regexExpression.matches(in: text, options: NSRegularExpression.MatchingOptions(), range: NSMakeRange(0, text.characters.count))

  1.  

for item in result {

  1.  

attributeString.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: item.range)

  1.  

}

  1.  

} catch {

  1.  

print("Failed with error: \(error)")

  1.  

}

  1.  

return attributeString

  1.  

}

用NSAttributedstring改变属性了的属性字符串,如果再转换成String,之前的属性就没有了,是否可以直接把NSAttributedstring的属性字符串直接添加到AlertViewController中替换掉要改变字体颜色的string呢?

网上说是有解决办法的,但是没找到解决办法,有知道记得告诉思思哈。

http://www.maccocoa.com/forum/archive/index.php/t-130.html

于是只有自定义AlertView,这样怎么都能实现了。

  1. //
  2. // CustomAlertView.swift
  3. // HaidilaoPad
  4. //
  5. // Created by 彭思 on 2018/5/3.
  6. // Copyright © 2018年 HongHuoTai. All rights reserved.
  7. //
  8.  
  9. import UIKit
  10.  
  11. let AlertWidth: CGFloat =
  12. let AlertHeight: CGFloat =
  13. let AlertPadding: CGFloat =
  14. let MenuHeight: CGFloat =
  15.  
  16. enum ButtonType {
  17. case button_OK
  18. case button_CANCEL
  19. case button_OTHER
  20. }
  21.  
  22. class AlertItem: NSObject {
  23. var title: String?
  24. var type: ButtonType?
  25. var tag: NSInteger?
  26. var action: ((_ item:AlertItem) -> Void)?
  27. }
  28.  
  29. class CustomAlertView: UIView {
  30.  
  31. // MARK: - Lazy
  32. lazy var coverView: UIView = {
  33. let coverView = UIView(frame: self.topView().bounds)
  34. coverView.backgroundColor = UIColor.black
  35. coverView.alpha =
  36. coverView.autoresizingMask = UIViewAutoresizing.flexibleHeight
  37. return coverView
  38. }()
  39. lazy var alertView: UIView = {
  40. let alertView = UIView(frame: CGRect(x: , y: , width: AlertWidth, height: AlertHeight))
  41. alertView.center = CGPoint(x: self.frame.size.width/, y: self.frame.size.height/)
  42. alertView.layer.masksToBounds = true
  43. alertView.layer.cornerRadius =
  44. alertView.backgroundColor = UIColor.white
  45. return alertView
  46. }()
  47. lazy var titleLabel: UILabel = {
  48. let titleLabel = UILabel()
  49. titleLabel.font = UIFont.boldSystemFont(ofSize: )
  50. titleLabel.textColor = UIColor.black
  51. titleLabel.textAlignment = NSTextAlignment.center
  52. titleLabel.numberOfLines =
  53. titleLabel.text = self.title
  54. titleLabel.lineBreakMode = NSLineBreakMode.byCharWrapping
  55. return titleLabel
  56. }()
  57. lazy var topLineView: UIView = {
  58. let topLineView = UIView()
  59. topLineView.backgroundColor = UIColor.lightGray
  60. return topLineView
  61. }()
  62. lazy var messageLabel: UILabel = {
  63. let messageLabel = UILabel()
  64. messageLabel.font = UIFont.systemFont(ofSize: )
  65. messageLabel.textAlignment = .center
  66. messageLabel.numberOfLines =
  67. messageLabel.textAlignment = NSTextAlignment.center
  68. messageLabel.lineBreakMode = NSLineBreakMode.byCharWrapping
  69. return messageLabel
  70. }()
  71.  
  72. var buttonScrollView: UIScrollView?
  73. var contentScrollView: UIScrollView?
  74.  
  75. var items: NSMutableArray?
  76. var title: String?
  77. var message: String?
  78.  
  79. var buttonWidth: CGFloat?
  80. var contentView: UIView?
  81.  
  82. override init(frame: CGRect) {
  83. super.init(frame: frame)
  84. }
  85.  
  86. // 便利构造函数
  87. convenience init(title:String, message:String, messageColor:UIColor?) {
  88.  
  89. // 计算frame
  90. var screenWidth = UIScreen.main.bounds.size.width
  91. var screenHeight = UIScreen.main.bounds.size.height
  92. // On iOS7, screen width and height doesn't automatically follow orientation
  93. if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
  94. let interfaceOrientation = UIApplication.shared.statusBarOrientation
  95. if UIInterfaceOrientationIsLandscape(interfaceOrientation) {
  96. let tmp = screenWidth
  97. screenWidth = screenHeight
  98. screenHeight = tmp
  99. }
  100. }
  101. let rect = CGRect(x: , y: , width: screenWidth, height: screenHeight)
  102. self.init(frame: rect)
  103. self.items = NSMutableArray()
  104. self.title = title
  105. self.message = message
  106.  
  107. // 设置views
  108. self.setupSubViews(messageColor)
  109. }
  110.  
  111. required init?(coder aDecoder: NSCoder) {
  112. fatalError("init(coder:) has not been implemented")
  113. }
  114.  
  115. // MARK: - Setup UI
  116.  
  117. func setupSubViews(_ color:UIColor?) {
  118.  
  119. self.topView().addSubview(self.coverView)
  120. self.addSubview(self.alertView)
  121. // 设置title
  122. let labelHeight = self.heightOfRow(self.title!, font: , width: AlertWidth - * AlertPadding)
  123. titleLabel.frame = CGRect(x: AlertPadding, y: AlertPadding, width: AlertWidth - * AlertPadding, height: labelHeight)
  124. self.alertView.addSubview(self.titleLabel)
  125. topLineView.frame = CGRect(x: , y: self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height + , width: AlertWidth, height: 0.5)
  126. self.alertView.addSubview(self.topLineView)
  127.  
  128. // 设置message
  129. let messageHeight = self.heightOfRow(self.message!, font: , width: AlertWidth - * AlertPadding)
  130. messageLabel.frame = CGRect(x: AlertPadding, y: self.topLineView.frame.origin.y + self.topLineView.frame.size.height + , width: AlertWidth - * AlertPadding, height: messageHeight + * AlertPadding)
  131. self.alertView.addSubview(self.messageLabel)
  132.  
  133. let mesColor:UIColor = color ?? UIColor.black
  134. messageLabel.textColor = mesColor
  135. let attributeStr = changeTextChange(regex: "\\d+", text: self.message!, color: UIColor.red)
  136. self.messageLabel.attributedText = attributeStr
  137. self.alertView.addSubview(self.messageLabel)
  138.  
  139. self.contentScrollView = UIScrollView(frame: CGRect.zero)
  140. self.alertView.addSubview(self.contentScrollView!)
  141.  
  142. UIDevice.current.beginGeneratingDeviceOrientationNotifications()
  143. NotificationCenter.default.addObserver(self, selector: #selector(CustomAlertView.deviceOrientationDidChange(_:)), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
  144. }
  145.  
  146. // dealloc
  147. deinit {
  148. UIDevice.current.endGeneratingDeviceOrientationNotifications()
  149. NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
  150. }
  151.  
  152. // override func
  153.  
  154. override func layoutSubviews() {
  155. self.buttonScrollView?.frame = CGRect(x: , y: self.alertView.frame.size.height-MenuHeight,width: self.alertView.frame.size.width, height: MenuHeight);
  156. 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);
  157. self.contentView?.frame = CGRect(x: ,y: ,width: self.contentView!.frame.size.width, height: self.contentView!.frame.size.height);
  158. if self.contentView != nil {
  159. self.contentScrollView?.contentSize = self.contentView!.frame.size;
  160. }
  161.  
  162. }
  163.  
  164. override func willMove(toSuperview newSuperview: UIView?) {
  165. self.addButtonItem()
  166. if self.contentView != nil {
  167. self.contentScrollView?.addSubview(self.contentView!)
  168. }
  169. self.reLayout()
  170. }
  171.  
  172. // show and dismiss
  173. func topView() -> UIView {
  174. let window = UIApplication.shared.keyWindow
  175. return (window?.subviews[])!
  176. }
  177.  
  178. func show() {
  179. UIView.animate(withDuration: 0.5, animations: { () -> Void in
  180. self.coverView.alpha = 0.5
  181. }, completion: { (finished) -> Void in
  182.  
  183. })
  184. self.topView().addSubview(self)
  185. self.showAnimation()
  186. }
  187.  
  188. //------Preoperties------
  189. func addButtonWithTitle(_ title:String) -> NSInteger {
  190. let item = AlertItem()
  191. item.title = title
  192. item.action = {(ite:AlertItem)->Void in
  193. print("no action")
  194. }
  195. item.type = ButtonType.button_OK
  196. self.items?.add(item)
  197. return (self.items?.index(of: title))!
  198. }
  199.  
  200. func addButton(_ type:ButtonType, title:String, handler:@escaping ((_ item:AlertItem) -> Void)) {
  201. let item = AlertItem()
  202. item.title = title
  203. item.action = handler
  204. item.type = type
  205. self.items?.add(item)
  206. item.tag = self.items?.index(of: item)
  207. }
  208.  
  209. func addButtonItem() {
  210. self.buttonScrollView = UIScrollView(frame: CGRect(x: , y: self.alertView.frame.size.height - MenuHeight,width: AlertWidth, height: MenuHeight))
  211. self.buttonScrollView?.bounces = false
  212. self.buttonScrollView?.showsHorizontalScrollIndicator = false
  213. self.buttonScrollView?.showsVerticalScrollIndicator = false
  214. let width:CGFloat
  215. if (self.buttonWidth != nil) {
  216. width = self.buttonWidth!
  217. let a = CGFloat((self.items?.count)!)
  218. self.buttonScrollView?.contentSize = CGSize(width: a * width, height: MenuHeight)
  219. } else {
  220. width = (self.alertView.frame.size.width) / CGFloat((self.items?.count)!)
  221. }
  222.  
  223. self.items?.enumerateObjects({ (item, idx, stop) in
  224. let button = UIButton(type: UIButtonType.system)
  225. button.frame = CGRect(x: CGFloat(idx) * width, y: , width: width, height: MenuHeight)
  226. button.backgroundColor = UIColor.white
  227. button.layer.shadowColor = UIColor.gray.cgColor
  228. button.layer.shadowRadius = 0.5
  229. button.layer.shadowOpacity =
  230. button.layer.shadowOffset = CGSize.zero
  231. button.layer.masksToBounds = false
  232. button.tag = + idx
  233. button.setTitleColor(UIColor.darkGray, for: .normal)
  234.  
  235. let ite = item as! AlertItem
  236.  
  237. button.setTitle(ite.title, for: UIControlState())
  238. button.setTitle(ite.title, for: UIControlState.selected)
  239. button.titleLabel?.font = UIFont.boldSystemFont(ofSize: (button.titleLabel?.font.pointSize)!)
  240.  
  241. button.addTarget(self, action: #selector(CustomAlertView.buttonTouched(_:)), for: UIControlEvents.touchUpInside)
  242. self.buttonScrollView?.addSubview(button)
  243.  
  244. // 按钮边框
  245. if idx != (self.items?.count)! - {
  246. let seprateLineVer = UIView(frame: CGRect(x: width - , y: , width: 0.5, height: MenuHeight))
  247. seprateLineVer.backgroundColor = UIColor.lightGray
  248. button.addSubview(seprateLineVer)
  249. }
  250.  
  251. let seprateLineHor = UIView(frame: CGRect(x: , y: , width: self.buttonScrollView!.frame.size.width, height: 0.5))
  252. seprateLineHor.backgroundColor = UIColor.lightGray
  253. self.buttonScrollView?.addSubview(seprateLineHor)
  254. })
  255. self.alertView.addSubview(self.buttonScrollView!)
  256. }
  257.  
  258. @objc func buttonTouched(_ button:UIButton) {
  259. let item:AlertItem = self.items![button.tag - ] as! AlertItem
  260. if (item.action != nil) {
  261. item.action!(item)
  262. }
  263. self.dismiss()
  264. }
  265.  
  266. func reLayout() {
  267. var plus:CGFloat
  268. if self.contentView != nil {
  269. plus = (self.contentView!.frame.size.height) - ((self.alertView.frame.size.height) - MenuHeight)
  270. } else {
  271. plus = (self.messageLabel.frame.origin.y) + (self.messageLabel.frame.size.height) - ((self.alertView.frame.size.height) - MenuHeight)
  272. }
  273. plus = max(, plus)
  274. let height = min(self.screenBounds().size.height - MenuHeight, (self.alertView.frame.size.height) + plus)
  275.  
  276. self.alertView.frame = CGRect(x: self.alertView.frame.origin.x, y: self.alertView.frame.origin.y, width: AlertWidth, height: height)
  277. self.alertView.center = self.center
  278. self.setNeedsDisplay()
  279. self.setNeedsLayout()
  280. }
  281.  
  282. func dismiss() {
  283. self.hideAnimation()
  284. }
  285.  
  286. // MARK: - showAnimation
  287. func showAnimation() {
  288. let popAnimation = CAKeyframeAnimation(keyPath: "transform")
  289. popAnimation.duration = 0.4
  290. popAnimation.values = [
  291. NSValue.init(caTransform3D: CATransform3DMakeScale(0.01, 0.01, 1.0)),
  292. NSValue.init(caTransform3D: CATransform3DMakeScale(1.1, 1.1, 1.0)),
  293. NSValue.init(caTransform3D: CATransform3DMakeScale(0.9, 0.9, 1.0)),
  294. NSValue.init(caTransform3D: CATransform3DIdentity)
  295. ]
  296. popAnimation.keyTimes = [0.2, 0.5, 0.75, 1.0]
  297. popAnimation.timingFunctions = [
  298. CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut),
  299. CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut),
  300. CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
  301. ]
  302. self.alertView.layer.add(popAnimation, forKey: nil)
  303. }
  304.  
  305. func hideAnimation() {
  306. UIView.animate(withDuration: 0.4, animations: { () -> Void in
  307. self.coverView.alpha = 0.0
  308. self.alertView.alpha = 0.0
  309. }, completion: { (finished) -> Void in
  310. self.removeFromSuperview()
  311. })
  312. }
  313.  
  314. // handle device orientation changes
  315. @objc func deviceOrientationDidChange(_ notification:Notification) {
  316. self.frame = self.screenBounds()
  317. UIView.animate(withDuration: 0.2, delay: 0.0, options: UIViewAnimationOptions(), animations: { () -> Void in
  318. self.reLayout()
  319. }) { (finished) -> Void in
  320.  
  321. }
  322. }
  323.  
  324. //------Tools-------
  325. // 计算frame
  326. func screenBounds() -> CGRect {
  327. var screenWidth = UIScreen.main.bounds.size.width
  328. var screenHeight = UIScreen.main.bounds.size.height
  329. // On iOS7, screen width and height doesn't automatically follow orientation
  330. if floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1 {
  331. let interfaceOrientation = UIApplication.shared.statusBarOrientation
  332. if UIInterfaceOrientationIsLandscape(interfaceOrientation) {
  333. let tmp = screenWidth
  334. screenWidth = screenHeight
  335. screenHeight = tmp
  336. }
  337. }
  338. return CGRect(x: , y: , width: screenWidth, height: screenHeight)
  339. }
  340.  
  341. // 计算字符串高度
  342. func heightOfRow(_ text:String, font:CGFloat, width:CGFloat) -> CGFloat {
  343. let size:CGSize = text.boundingRect(with: CGSize(width: width, height: ), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: font)], context: nil).size
  344. return size.height;
  345. }
  346.  
  347. //根据正则表达式改变文字颜色
  348. func changeTextChange(regex: String, text: String, color: UIColor) -> NSMutableAttributedString {
  349. let attributeString = NSMutableAttributedString(string: text)
  350. do {
  351. let regexExpression = try NSRegularExpression(pattern: regex, options: NSRegularExpression.Options())
  352. let result = regexExpression.matches(in: text, options: NSRegularExpression.MatchingOptions(), range: NSMakeRange(, text.characters.count))
  353. for item in result {
  354. attributeString.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: item.range)
  355. }
  356. } catch {
  357. print("Failed with error: \(error)")
  358. }
  359. return attributeString
  360. }
  361. }

 实现效果如下:

Swift自定义AlertView的更多相关文章

  1. [IOS]swift自定义uicollectionviewcell

    刚刚接触swift以及ios,不是很理解有的逻辑,导致某些问题.这里分享一下swift自定义uicollectionviewcell 首先我的viewcontroller不是直接继承uicollect ...

  2. iOS 第三方自定义Alertview项目MBProcessHud中的重要代码分析

    做ios,弹出一个自定义的alertview挺常见的.ios7以前,我们可以对系统的UIAlertView进行一点操作,实现一点简单的定制,但是ios7不再允许我们这样做了.因此,我们需要自己创建一个 ...

  3. Swift 自定义打印方法

    Swift 自定义打印方法 代码如下 // MARK:- 自定义打印方法 func MLLog<T>(_ message : T, file : String = #file, funcN ...

  4. 兼容iOs7的自定义alertView

    转载请注明出处. 升级到ios7后,旧项目中使用的继承UIAlertView的自定义alertview无法正常显示了,无奈只好换思路去实现,改成从当前keywindow下创建要显示的alertview ...

  5. 自定义AlertView的方法和改变Alert的弹出位置以及其宽度

    此方法在IOS7中不适合 一.自定义AlertView 1.首先新建一个OC类继承与AlertView. 2.然后再.m中添加方法 - (void)layoutSubviews 可以再这个方法里边改变 ...

  6. 自定义AlertView(Swift)

    MyAlertView.swift // Pop Up Styles enum MyAlertViewStyle: Int { case success case error case notice ...

  7. swift 自定义弹框

    // //  ViewController.swift //  animationAlert // //  Created by su on 15/12/9. //  Copyright © 2015 ...

  8. swift 自定义图片轮播视图

    Swift封装图片轮播视图: import UIKit class XHAdLoopView: UIView { private var pageControl : UIPageControl? pr ...

  9. Swift 自定义Subscript

    Swift可以方便给自定义类加下标,其中参数和返回值可以在类里定义为任意类型: subscript(parameters) -> ReturnType { get { //return some ...

随机推荐

  1. Linux入侵类问题排查思路

    深入分析,查找入侵原因 一.检查隐藏帐户及弱口令 检查服务器系统及应用帐户是否存在 弱口令: 检查说明:检查管理员帐户.数据库帐户.MySQL 帐户.tomcat 帐户.网站后台管理员帐户等密码设置是 ...

  2. IIS 使用 web.config 实现从 http 自动301跳转到 https 的方法

    现在很多网站为了安全,开启了 SSL 连接,那么开启 SSL 连接之后,如何将对应的 http 访问自动跳转到 https 上呢?之前介绍了 IIS 用 web.config 做域名的301跳转的方法 ...

  3. python字符的表示格式

    %% 百分号标记 #就是输出一个% %c 字符及其ASCII码%s 字符串%d 有符号整数(十进制)%u 无符号整数(十进制)%o 无符号整数(八进制)%x 无符号整数(十六进制)%X 无符号整数(十 ...

  4. python - 手机号正则匹配

    Python 手机号正则匹配 # -*- coding:utf-8 -*- import re def is_phone(phone): phone_pat = re.compile('^(13\d| ...

  5. Discrete Cosine Transform

    离散余弦变换 由于实信号傅立叶变换的共轭对称性,导致DFT后在频域中有一半的数据冗余.离散余弦变换(DCT)在处理实信号时比离散傅立叶(DFT)变换更具优势.在处理声音信号这类实信号时,DFT得到的结 ...

  6. zzulioj - 2628: 小新的字母广场

    题目链接:http://acm.zzuli.edu.cn/problem.php?id=2628 题目描述        放假了,小新决定出去散散心,于是他来到了著名的字母广场.这个广场是由n*m块砖 ...

  7. vlang 试用

    vlang 是最近出来的一门编程语言,集成了rust,golang, 等语言的特性,轻量.简洁.编译 快速,详细的比价参数可以参考官方文档 安装 目前尽管官方提供了linux以及mac 的二进制文件, ...

  8. vue中前端弹窗队列展示

    在前端写一个弹窗可能很简单,那如果同时有多个弹窗呢 这样的话就要考虑弹窗的展示问题,肯定是不能叠加在一起的,这时候就要通过队列(先进先出)来展示 思路就是根据队列来实现,至于具体的实现方式,可以在项目 ...

  9. 【洛谷P5019】铺设道路

    题目链接 众所周知,这道题和积木大赛是同一道题 题意就是给出一段自然数序列,每次操作\((L,R)\)把区间\([L,R]\)的数全部减一,不允许出现负数,问把序列变为零的最小操作次数 贪心做法 样例 ...

  10. (8)Go Map

    Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现. Map map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用. map定义 G ...