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 ...
随机推荐
- 一些替代Xshell的软件推荐
FinalShell: 面附上一些截图和官方连接: 官网:http://www.hostbuf.com/ FinalShell是一体化的的服务器,网络管理软件,不仅是ssh客户端,还是功能强大的开发, ...
- PHP隐藏IP地址末位的方法
很久之前写过一个使用ASP隐藏IP地址末位的文章,也就是有时候为了保护用户的隐私,会隐藏用户的IP地址,达成类似于 222.222.222.* 的效果. 现在想要用PHP来实现,经过尝试,其实非常简 ...
- 查询响应慢,DB近乎崩溃
时间:18.11.22 一. 起由: 公司最近因业务,有大量注册,每天大约几万,貌似也不太高? 晚上8点左右,网站后台,前台突然大面积提示502.网站几乎瘫痪.买的阿里云的负载均衡和读写分离.分别是5 ...
- postgres常用运维sql
1.查看数据库大小 select pg_database_size('log_analysis'); postgres=# select pg_database_size('postExpress') ...
- python - django 使用ajax将图片上传到服务器并渲染到前端
一.前端代码 <!doctype html> <html lang="en"> <head> <meta charset="UT ...
- 持续集成学习7 jenkins自动化代码构建
一.整体功能 1.触发上下游构建 2.我们在触发一个job的时候顺便丢一些参数过去,这些参数有可能是我这次编译过程中产生的一些地址,版本号或动态的一些东西丢到下游作为下游的构建参数 3.不同种类的视图
- 为啥用DTO
0.部分参数对于开发前端的人来说是无意义的,因为传递也没有效果.所以不应该暴露给前端使用. 1.依据现有的类代码,即可方便的构造出DTO对象,而无需重新进行分析. 2.减少请求次数,大大提高效率. 3 ...
- SIGIR2018 Paper Abstract Reading Notes (1)
1.A Click Sequence Model for Web Search(日志分析) 更好的理解用户行为对于推动信息检索系统来说是非常重要的.已有的研究工作仅仅关注于建模和预测一次交互行为,例如 ...
- 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay
P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...
- SQL基础-连接表
一.连接表 1.SQL JOIN 忘记在哪保存的某位网友的图,先明白SQL JOIN, 2.关于笛卡尔积 笛卡尔积: 两个集合的乘积 重新建student表和teacher表: student表: C ...