iOS Swift 写一个弹框

前言:

写了一个Swift版本的弹框。

代码地址:

代码地址:https://gitee.com/yuency/Autolayout
示例代码类名 【PopViewController】【OutageSubscribePopView】

弹框效果:


弹框.png

上代码!

OutageSubscribePopView.swift

import UIKit

typealias BlockClickSubscribe = (_ text: String) -> Void
typealias BlockClickClose = () -> Void

class OutageSubscribePopView: UIView {
    
    static let buttonHeight: CGFloat = 52
    
    var clickSubscribe: BlockClickSubscribe?
    var clickClose: BlockClickClose?
    
    lazy var tapGesture = UITapGestureRecognizer()
    
    lazy var grayMaskView: UIView = {
        let grayMaskView = UIView()
        grayMaskView.backgroundColor = UIColor.black.withAlphaComponent(0.2)
        grayMaskView.addGestureRecognizer(tapGesture)
        return grayMaskView
    }()
    
    lazy var backView: UIView = {
        let backView = UIView()
        backView.backgroundColor = UIColor.white
        backView.layer.cornerRadius = 12
        return backView
    }()
    
    private lazy var shadowBar: OutageShadowBar = {
        let shadowBar = OutageShadowBar()
        return shadowBar
    }()
    
    lazy var subscribeButton: UIButton = {
        let subscribeButton = UIButton()
        subscribeButton.setTitle("这是我的标题", for: .normal)
        subscribeButton.setTitleColor(UIColor.blue, for: .normal)
        subscribeButton.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        return subscribeButton
    }()
    
    lazy var cancelButton: UIButton = {
        let cancelButton = UIButton()
        cancelButton.setTitle("取消", for: .normal)
        cancelButton.setTitleColor(UIColor.blue, for: .normal)
        cancelButton.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .regular)
        cancelButton.backgroundColor = UIColor.purple.withAlphaComponent(0.1)
        return cancelButton
    }()
    
    lazy var topRightCloseButton: UIButton = {
        let topRightCloseButton = UIButton()
        topRightCloseButton.backgroundColor = UIColor.green
        topRightCloseButton.setTitle("关闭", for: .normal)
        topRightCloseButton.setTitleColor(UIColor.red, for: .normal)
        return topRightCloseButton
    }()
    
    lazy var contentGrayView: UIView = {
        let contentGrayView = UIView()
        contentGrayView.layer.cornerRadius = 10
        contentGrayView.backgroundColor = UIColor.yellow
        return contentGrayView
    }()
    
    lazy var contentLabel: UILabel = {
        let contentLabel = UILabel()
        contentLabel.numberOfLines = 0
        return contentLabel
    }()
    
    lazy var titleLabel: UILabel = {
        let titleLabel = UILabel()
        titleLabel.font = UIFont.systemFont(ofSize: 14, weight: .regular)
        titleLabel.textColor = UIColor.black
        titleLabel.text = "我停电了"
        return titleLabel
    }()
    
    deinit {
        print("\((#file as NSString).lastPathComponent) dealloc")
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUI()
        setConstraints()
        setBindings()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 这段代码需要抽取出来, 左晨公用的
    static func getAttributeString(firstText: String) -> NSMutableAttributedString {
        let attributeString = NSMutableAttributedString(string: firstText)
        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = .natural
        let multipleAttributes: [NSAttributedString.Key: Any] = [
            .paragraphStyle: paragraph,
            .font: UIFont.systemFont(ofSize: 16, weight: .regular),
            .foregroundColor: UIColor.black]
        attributeString.addAttributes(multipleAttributes, range: NSRange(location: 0, length: firstText.count))
        
        let indexArray: [Int] = firstText.indicesOf(string: "\"")
        let indexCount = indexArray.count
        if indexCount % 2 == 0 {
            for i in stride(from: 0, to: indexArray.count - 1, by: 2) {
                attributeString.addAttribute(.font, value: UIFont.systemFont(ofSize: 16, weight: .bold), range: NSRange(location: indexArray[i] + 1, length: indexArray[i+1] - indexArray[i] - 1))
                attributeString.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: indexArray[i] + 1, length: indexArray[i+1] - indexArray[i] - 1))
            }
        }
        return attributeString
    }
    
    static func showView(name: String, age: String, time: String, clickSubscribe: @escaping BlockClickSubscribe, clickClose: @escaping BlockClickClose) {
        let subscribePopView = OutageSubscribePopView()
        subscribePopView.clickSubscribe = clickSubscribe
        subscribePopView.clickClose = clickClose
        
        let formatString = String(format: "这是内容,内容里面有文字样式是\"被引用加粗的文字\"这个就是重点啊,然后还有3个占位符%@AAA%@BBB%@CCC", name, age, time)
        subscribePopView.contentLabel.attributedText = OutageSubscribePopView.getAttributeString(firstText: formatString)
        
        let window = UIApplication.shared.windows.last
        window?.addSubview(subscribePopView)
        subscribePopView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        window?.layoutIfNeeded()
        subscribePopView.alpha = 0
        UIView.animate(withDuration: 0.1) {
            subscribePopView.alpha = 1
        } completion: { _ in
            UIView.animate(withDuration: 0.1, animations: {
                subscribePopView.backView.snp.updateConstraints { make in
                    // for layout animation in view presenting from bottom, content height depend on subviews
                    make.top.equalTo(subscribePopView.snp.bottom).offset(-subscribePopView.backView.frame.height)
                }
                subscribePopView.layoutIfNeeded()
            }, completion: nil)
        }
    }
    
    func setUI() {
        addSubview(grayMaskView)
        addSubview(backView)
        backView.addSubview(cancelButton)
        backView.addSubview(shadowBar)
        backView.addSubview(subscribeButton)
        backView.addSubview(topRightCloseButton)
        backView.addSubview(contentGrayView)
        contentGrayView.addSubview(contentLabel)
        backView.addSubview(titleLabel)
    }
    
    func setConstraints() {
        grayMaskView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        backView.snp.makeConstraints { make in
            // for layout animation in view presenting from bottom, content height depend on subviews
            make.top.equalTo(self.snp.bottom).offset(0)
            make.left.right.equalToSuperview()
        }
        
        var safeBottomHeight: CGFloat = 0
        if #available(iOS 11.0, *) {
            safeBottomHeight = UIApplication.shared.windows.last?.safeAreaInsets.bottom ?? 0
        } else {
            // Fallback on earlier versions
        }
        cancelButton.snp.makeConstraints { make in
            make.bottom.equalTo(-safeBottomHeight-20)
            make.left.equalTo(20)
            make.right.equalTo(-20)
            make.height.equalTo(OutageSubscribePopView.buttonHeight)
        }
        shadowBar.snp.makeConstraints { make in
            make.bottom.equalTo(cancelButton.snp.top).offset(-30)
            make.left.equalTo(20)
            make.right.equalTo(-20)
            make.height.equalTo(OutageSubscribePopView.buttonHeight)
        }
        subscribeButton.snp.makeConstraints { make in
            make.edges.equalTo(shadowBar)
        }
        contentGrayView.snp.makeConstraints { make in
            make.left.equalTo(20)
            make.right.equalTo(-20)
            make.bottom.equalTo(shadowBar.snp.top).offset(-20)
        }
        contentLabel.snp.makeConstraints { make in
            make.edges.equalTo(UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
        }
        titleLabel.snp.makeConstraints { make in
            make.left.equalTo(20)
            make.right.equalTo(topRightCloseButton.snp.left).offset(-13)
            make.bottom.equalTo(contentGrayView.snp.top).offset(-20)
            make.top.equalTo(20)
        }
        topRightCloseButton.snp.makeConstraints { make in
            make.centerY.equalTo(titleLabel)
            make.right.equalToSuperview().offset(-13)
            make.height.width.equalTo(44)
        }
    }
    
    func setBindings() {
        topRightCloseButton.addTarget(self, action: #selector(action_close), for: .touchUpInside);
        cancelButton.addTarget(self, action: #selector(action_close), for: .touchUpInside);
        tapGesture.addTarget(self, action: #selector(action_close))
        subscribeButton.addTarget(self, action: #selector(action_subscribe), for: .touchUpInside);
    }
    
    @objc func action_close() {
        if let clickClose = clickClose {
            clickClose()
        }
        disMissView()
    }
    
    @objc func action_subscribe() {
        if let clickSubscribe = clickSubscribe {
            clickSubscribe("9789697979865469789")
        }
        disMissView()
    }
    
    func disMissView() {
        clickSubscribe = nil
        clickClose = nil
        removeFromSuperview()
    }
}

class OutageShadowBar: UIView {
    let cornerRadius:CGFloat = OutageSubscribePopView.buttonHeight * 0.5
    override var bounds: CGRect {
        didSet {
            setupShadow()
        }
    }
    private func setupShadow() {
        backgroundColor = UIColor.white
        layer.cornerRadius = cornerRadius
        layer.borderWidth = 1
        layer.borderColor = UIColor.white.cgColor
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 2)
        layer.shadowOpacity = 0.1
        layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).cgPath
    }
}

public extension String {
    func indicesOf(string: String) -> [Int] {
        var indices = [Int]()
        var searchStartIndex = self.startIndex
        while searchStartIndex < self.endIndex, let range = self.range(of: string, range: searchStartIndex..<self.endIndex), !range.isEmpty {
            let index = distance(from: self.startIndex, to: range.lowerBound)
            indices.append(index)
            searchStartIndex = range.upperBound
        }
        return indices
    }
}

调用:

import UIKit

class PopViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    @IBAction func action_1(_ sender: UIButton) {
        OutageSubscribePopView.showView(name: "我是张三", age: "18岁了", time: "就在今年") { text in
            print("收到了东西 \(text)")
        } clickClose: {
            print("点击关闭")
        }
    }
}

结语

暂无

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容