├── .gitignore ├── README.md ├── ZHFToolBox.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── zhanghaifeng.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── ZHFToolBox ├── 1.gif ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── back_ground.imageset │ │ ├── Contents.json │ │ └── back_ground.png │ ├── bmw_image.imageset │ │ ├── 971c6e6b3c46c573e5914bec0d6cb645.jpg │ │ └── Contents.json │ ├── cancel_white.imageset │ │ ├── Contents.json │ │ ├── cancel_white@1x.png │ │ ├── cancel_white@2x.png │ │ └── cancel_white@3x.png │ ├── icon_switch.imageset │ │ ├── Contents.json │ │ ├── icon_switch@2x.png │ │ └── icon_switch@3x.png │ ├── icon_switch_r.imageset │ │ ├── Contents.json │ │ ├── icon_switch_r@2x.png │ │ └── icon_switch_r@3x.png │ ├── inner_layerImage.imageset │ │ ├── Contents.json │ │ └── scanSucceed_back.png │ ├── left.imageset │ │ ├── Contents.json │ │ └── left.png │ ├── outer_layerImage.imageset │ │ ├── Contents.json │ │ └── scanSucceed_bottom.png │ ├── progressHint.imageset │ │ ├── Contents.json │ │ ├── progressHint.png │ │ ├── progressHint@2x.png │ │ └── progressHint@3x.png │ ├── right.imageset │ │ ├── Contents.json │ │ └── right.png │ └── test1.imageset │ │ ├── Contents.json │ │ └── test1.jpg ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── OneVC.swift ├── RedVC.swift ├── TBCalendar │ ├── Const.swift │ ├── Foundation+Extension.swift │ ├── TBCalendar.swift │ ├── TBCalendarAppearStyle.swift │ ├── TBCalendarDateCell.swift │ └── TBCalendarHeaderView.swift ├── TopTopTranslucentTableView │ ├── MessgeShowVC.swift │ ├── NormalCell.swift │ ├── NormalCell.xib │ └── TopTranslucentTableView.swift ├── TwoVC.swift ├── ViewController.swift ├── ZHFSubToolBox │ ├── CalendarView.swift │ ├── MyNSString.swift │ ├── PopCheckboxButtonView.swift │ ├── PopDiseaseView.swift │ ├── PopGifOpenBox │ │ ├── OpenBoxView.swift │ │ ├── PopAwayOpenBackGroundView.swift │ │ ├── PopBackGroundView.swift │ │ └── open_boxA.gif │ ├── PopImageView.swift │ ├── PopProgressBar.swift │ ├── PopRadioButtonView.swift │ ├── PopSmallChangeBigFatherView.swift │ ├── PopSomeColorView.swift │ ├── PopTextView.swift │ ├── PopTopOrBottomOutView.swift │ ├── SlideView.swift │ ├── SlideWhiteViewSubView.swift │ ├── UpDownView.swift │ ├── ZHFAlertControllerTool.swift │ ├── ZHFCalendarView.swift │ └── ZHFColor.swift └── test.json ├── ZHFToolBoxTests ├── Info.plist └── ZHFToolBoxTests.swift └── ZHFToolBoxUITests ├── Info.plist └── ZHFToolBoxUITests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | # Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZHFToolBox 2 | ## 弹框,提示框,自定义弹框,自定义提示框。包含弹出输入框,弹出单选框,弹出多选框,弹出图片,弹出简单的打开奖品的动画效果等,和大家分享高效的自定义自己项目需要的弹框思路。--Swift版本 3 | 4 | 5 | 6 | ![](./ZHFToolBox/1.gif) 7 | ### 最新更新 添加一个渐变的模拟进度条 8 | ### 效果图展现的内容包含下列弹框: 9 | 10 | 1.有序弹出一些View视图。(带回弹效果) 11 | 12 | 2.一个类似商品从盒子里弹出来的效果(带回弹效果) 13 | 14 | 3.一个类似商品从高空掉入盒子的效果(带回弹效果) 15 | 16 | 4.提示框由小变大弹出(弹出区域放的是一堆按钮,可多选) 17 | 18 | 5.提示框由小变大弹出(弹出区域放的是一堆按钮,可单选) 19 | 20 | 6.提示框由小变大弹出(弹出区域放一个带占位文字的输入框TextView) 21 | 22 | 7.提示框由小变大弹出(弹出区域放一张显示图片,尾部带两个自定义按钮) 23 | 24 | 8.弹出侧滑视图(侧滑视图带tableView点击跳转) 25 | 26 | 9.剩下的几个是对系统AlertView封装后弹出的效果 27 | 28 | 29 | ### 自定义这些弹框的思路: 30 | 31 | #### 一、弹框结构分析 32 | 33 | 我们知道弹框的结构基本上都是一个半透明的黑底View,然后上边放一个白色的View。白色View上放自己要在弹框里展示的内容(图片,按钮,文字,输入框等等)。 34 | 35 | #### 二、从思路分析中我们可以知道弹框的共性 36 | 37 | 半透明的黑底View,上边白色的View。这两个是必不可少的。甚至还有一个cancel按钮。 38 | 39 | 那么我们就自定义一下这个父视图(FatherView),因为我想让这个弹框弹出来时由小变大展示,我就给它起了PopSmallChangeBigFatherView这个名字。 40 | 41 | #### 然后我给这个父视图加上下面属性 42 | 43 | 1.背景区域的颜色和透明度 44 | 45 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 46 | 47 | 2.白色view用来装一些控件 48 | 49 | var WhiteView: UIView = UIView() 50 | 51 | 3.WhiteView从什么位置以什么样的大小弹出 52 | 53 | var whiteViewStartFrame: CGRect = CGRect.init(x: ScreenWidth/2 - 10, y: ScreenHeight/2 - 10, width: 20, height: 20) 54 | 55 | 4.WhiteView在什么位置以什么样的大小停下来 56 | 57 | var whiteViewEndFrame: CGRect = CGRect.init(x: 40, y: 100, width: ScreenWidth - 80, height: ScreenHeight - 230) 58 | 59 | 5.WhiteView变大变小的动画时间 60 | 61 | var defaultTime:CGFloat = 0.5 62 | 63 | 6.取消按钮 64 | 65 | var cancelBtn: UIButton = UIButton() 66 | 67 | #### 然后我让这个父视 68 | 69 | 1.有初始化方法 70 | 71 | func initPopBackGroundView() -> UIView 72 | 73 | 2.弹出效果(弹出按钮被点击) 74 | 75 | func addAnimate() 76 | 77 | 3. 收回的动画效果(取消按钮被点击) 78 | 79 | @objc func tapBtnAndcancelBtnClick() 80 | 81 | ### 三、就开始写一些需要自定义的弹框 82 | 就是所有弹框都继承: PopSmallChangeBigFatherView 83 | 84 | 1.class PopImageView: PopSmallChangeBigFatherView(弹个图、重写override func addAnimate())在父视图的WhiteView写要弹出的内容 85 | 86 | 2.class PopTextView: PopSmallChangeBigFatherView(弹个输入框、重写override func addAnimate())在父视图的WhiteView写要弹出的内容 87 | 88 | 3.class PopRadioButtonView: PopSmallChangeBigFatherView(弹个单选框、重写override func addAnimate())在父视图的WhiteView写要弹出的内容 89 | 90 | 4.class PopCheckboxButtonView: PopSmallChangeBigFatherView(弹个多选框、重写override func addAnimate())在父视图的WhiteView写要弹出的内容 91 | 92 | 5.class SlideWhiteViewSubView: SlideView(弹个左右滑视图、重写override func addAnimate())在父视图的WhiteView写要侧滑展示的内容 93 | 94 | ### 四、搞个特殊的(一个类似商品(从盒子里弹出来、从高空掉入盒子)的效果(带回弹效果)PopTopOrBottomOutView这个弹出效果和上面那几个不一样。那就继承UIView,以相同的思路写了。) 95 | # PS 96 | 如果感觉有用,感谢Star Fork! 97 | -------------------------------------------------------------------------------- /ZHFToolBox.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZHFToolBox.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ZHFToolBox.xcodeproj/xcuserdata/zhanghaifeng.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ZHFToolBox.xcodeproj/xcuserdata/zhanghaifeng.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZHFToolBox.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | ZHFToolBox.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ZHFToolBox/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/1.gif -------------------------------------------------------------------------------- /ZHFToolBox/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | } 22 | //定义一个全局函数打印方法 23 | //自定义标记 ->项目 ->buildSettings -> swift flag ->Debug -> -D DEBUG 24 | func ZHFLog(message : T, file : String = #file, line : Int = #line) { 25 | //在DEBUG环境下打印,在RELEASE环境下不打印 26 | #if DEBUG 27 | let file1 = (file as NSString).lastPathComponent 28 | let line1 = (line as Int) 29 | print("\(file1):line\(line1)---\(message)") 30 | #endif 31 | } 32 | -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/back_ground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "back_ground.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/back_ground.imageset/back_ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/back_ground.imageset/back_ground.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/bmw_image.imageset/971c6e6b3c46c573e5914bec0d6cb645.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/bmw_image.imageset/971c6e6b3c46c573e5914bec0d6cb645.jpg -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/bmw_image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "971c6e6b3c46c573e5914bec0d6cb645.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/cancel_white.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "cancel_white@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "cancel_white@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "cancel_white@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/cancel_white.imageset/cancel_white@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/cancel_white.imageset/cancel_white@1x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/cancel_white.imageset/cancel_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/cancel_white.imageset/cancel_white@2x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/cancel_white.imageset/cancel_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/cancel_white.imageset/cancel_white@3x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/icon_switch.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_switch@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_switch@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/icon_switch.imageset/icon_switch@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/icon_switch.imageset/icon_switch@2x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/icon_switch.imageset/icon_switch@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/icon_switch.imageset/icon_switch@3x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/icon_switch_r.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_switch_r@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_switch_r@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/icon_switch_r.imageset/icon_switch_r@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/icon_switch_r.imageset/icon_switch_r@2x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/icon_switch_r.imageset/icon_switch_r@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/icon_switch_r.imageset/icon_switch_r@3x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/inner_layerImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "scanSucceed_back.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/inner_layerImage.imageset/scanSucceed_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/inner_layerImage.imageset/scanSucceed_back.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/left.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "left.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/left.imageset/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/left.imageset/left.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/outer_layerImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "scanSucceed_bottom.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/outer_layerImage.imageset/scanSucceed_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/outer_layerImage.imageset/scanSucceed_bottom.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/progressHint.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "progressHint.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "progressHint@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "progressHint@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/progressHint.imageset/progressHint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/progressHint.imageset/progressHint.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/progressHint.imageset/progressHint@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/progressHint.imageset/progressHint@2x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/progressHint.imageset/progressHint@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/progressHint.imageset/progressHint@3x.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/right.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "right.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/right.imageset/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/right.imageset/right.png -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/test1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "test1.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZHFToolBox/Assets.xcassets/test1.imageset/test1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/Assets.xcassets/test1.imageset/test1.jpg -------------------------------------------------------------------------------- /ZHFToolBox/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ZHFToolBox/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /ZHFToolBox/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ZHFToolBox/OneVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OneVC.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class OneVC: UIViewController { 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | self.view.backgroundColor = ZHFColor.orange 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ZHFToolBox/RedVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RedVC.swift 3 | // SlideViewTest 4 | // 5 | // Created by 张海峰 on 2018/11/14. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class RedVC: UIViewController { 12 | var message:String = "" 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.view.backgroundColor = UIColor.red 16 | self.title = message 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ZHFToolBox/TBCalendar/Const.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Const.swift 3 | // SwiftTest 4 | // 5 | // Created by 1111 on 2017/11/7. 6 | // Copyright © 2017年 xuejianfeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let kScreenHeight = UIScreen.main.bounds.size.height 12 | let kScreenWidth = UIScreen.main.bounds.size.width 13 | 14 | //=================系统参数相关=============== 15 | // iPhone X 16 | let iPhoneX = (kScreenWidth == 375 && kScreenHeight == 812) ? true : false 17 | let CURRENT_SYS_VERSION = (UIDevice.current.systemVersion as NSString).floatValue 18 | let IOS8 = (UIDevice.current.systemVersion as NSString).doubleValue >= 8.0 19 | let NAV_HEIGHT = iPhoneX ? (44 + 44) : 64 20 | let TABBAR_HEIGHT = iPhoneX ? (49 + 34) : 49 21 | let kTabbarSafeBottomMargin = iPhoneX ? 34 : 0 22 | let BATTERY_BARHEIGHT = iPhoneX ? 44 : 20 23 | //=================================== 24 | enum TBCalendarHeaderViewType: Int { 25 | case leftDate 26 | case centerDate 27 | } 28 | 29 | let CHANGE_SELECT_DATE: String = "change_select_date" 30 | -------------------------------------------------------------------------------- /ZHFToolBox/TBCalendar/Foundation+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Foundation+Extension.swift 3 | // SwiftTest 4 | // 5 | // Created by 1111 on 2018/3/19. 6 | // Copyright © 2018年 xuejianfeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension String { 12 | /// 计算文本的高度 13 | func textHeight(fontSize: CGFloat, width: CGFloat) -> CGFloat { 14 | return self.boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: fontSize)], context: nil).size.height 15 | } 16 | } 17 | 18 | extension UIView{ 19 | ///点击事件 20 | func addTargetForTouch(target: Any, action: Selector){ 21 | let singleTap = UITapGestureRecognizer.init(target: target, action: action) 22 | self.addGestureRecognizer(singleTap) 23 | } 24 | 25 | // 长按事件 26 | func addTargetForLongTouch(target: Any, action: Selector){ 27 | let singleTap = UILongPressGestureRecognizer.init(target: target, action: action) 28 | singleTap.cancelsTouchesInView = false 29 | singleTap.minimumPressDuration = 0 30 | self.addGestureRecognizer(singleTap) 31 | } 32 | 33 | func fadeIn() { 34 | self.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3) 35 | self.alpha = 0; 36 | 37 | UIView.animate(withDuration: 0.35) { 38 | self.alpha = 1; 39 | self.transform = CGAffineTransform.init(scaleX: 1.0, y: 1.0) 40 | } 41 | } 42 | 43 | func fadeOut() { 44 | UIView.animate(withDuration: 0.35, animations: { 45 | self.transform = CGAffineTransform.init(scaleX: 1.3, y: 1.3) 46 | self.alpha = 0.0; 47 | }) { (finished) in 48 | if (finished) { 49 | self.removeFromSuperview() 50 | } 51 | } 52 | } 53 | 54 | func show() { 55 | let keywindow = UIApplication.shared.keyWindow 56 | keywindow?.addSubview(self) 57 | 58 | self.center = CGPoint.init(x: (keywindow?.bounds.size.width)! / 2, y: (keywindow?.bounds.size.height)! / 2) 59 | self.fadeIn() 60 | } 61 | 62 | func dismiss(){ 63 | self.fadeOut() 64 | } 65 | } 66 | 67 | extension UILabel { 68 | class func createWithLable(text: String, textColor: UIColor, textFont: UIFont, aliment: NSTextAlignment) -> UILabel { 69 | 70 | let label = UILabel.init() 71 | label.text = text 72 | label.textColor = textColor 73 | label.textAlignment = aliment 74 | label.font = textFont 75 | 76 | return label 77 | } 78 | } 79 | 80 | extension Date { 81 | 82 | func getDateWithDay() -> Int { 83 | 84 | return NSCalendar.current.component(.day, from: self) 85 | } 86 | 87 | func getDateWithMonth() -> Int { 88 | return NSCalendar.current.component(.month, from: self) 89 | } 90 | 91 | func getDateWithYear() -> Int { 92 | return NSCalendar.current.component(.year, from: self) 93 | } 94 | 95 | /// 判断当前日期是否为今年 96 | func isThisYear() -> Bool { 97 | // 获取当前日历 98 | let calender = Calendar.current 99 | // 获取日期的年份 100 | let yearComps = calender.component(.year, from: self) 101 | // 获取现在的年份 102 | let nowComps = calender.component(.year, from: Date()) 103 | 104 | return yearComps == nowComps 105 | } 106 | 107 | /// 是否是昨天 108 | func isYesterday() -> Bool { 109 | // 获取当前日历 110 | let calender = Calendar.current 111 | // 获取日期的年份 112 | let comps = calender.dateComponents([.year, .month, .day], from: self, to: Date()) 113 | // 根据头条显示时间 ,我觉得可能有问题 如果comps.day == 0 显示相同,如果是 comps.day == 1 显示时间不同 114 | // 但是 comps.day == 1 才是昨天 comps.day == 2 是前天 115 | // return comps.year == 0 && comps.month == 0 && comps.day == 1 116 | return comps.year == 0 && comps.month == 0 && comps.day == 0 117 | } 118 | 119 | /// 是否是前天 120 | func isBeforeYesterday() -> Bool { 121 | // 获取当前日历 122 | let calender = Calendar.current 123 | // 获取日期的年份 124 | let comps = calender.dateComponents([.year, .month, .day], from: self, to: Date()) 125 | // 126 | // return comps.year == 0 && comps.month == 0 && comps.day == 2 127 | return comps.year == 0 && comps.month == 0 && comps.day == 1 128 | } 129 | 130 | /// 判断是否是今天 131 | func isToday() -> Bool { 132 | // 日期格式化 133 | let formatter = DateFormatter() 134 | // 设置日期格式 135 | formatter.dateFormat = "yyyy-MM-dd" 136 | 137 | let dateStr = formatter.string(from: self) 138 | let nowStr = formatter.string(from: Date()) 139 | return dateStr == nowStr 140 | } 141 | 142 | } 143 | 144 | /** 145 | * 扩展部分 146 | */ 147 | extension UIColor { 148 | 149 | /** 150 | * 16进制 转 RGBA 151 | */ 152 | class func UIColorFromRGBA(rgb:Int, alpha:CGFloat) ->UIColor { 153 | 154 | return UIColor(red: ((CGFloat)((rgb & 0xFF0000) >> 16)) / 255.0, 155 | green: ((CGFloat)((rgb & 0xFF00) >> 8)) / 255.0, 156 | blue: ((CGFloat)(rgb & 0xFF)) / 255.0, 157 | alpha: alpha) 158 | } 159 | 160 | /** 161 | * 16进制 转 RGB 162 | */ 163 | class func UIColorFromRGB(rgb:Int) ->UIColor { 164 | 165 | return UIColor(red: ((CGFloat)((rgb & 0xFF0000) >> 16)) / 255.0, 166 | green: ((CGFloat)((rgb & 0xFF00) >> 8)) / 255.0, 167 | blue: ((CGFloat)(rgb & 0xFF)) / 255.0, 168 | alpha: 1.0) 169 | } 170 | } 171 | 172 | /** 173 | * 设置控件的阴影参数 174 | */ 175 | 176 | func setShadowForView(view: UIView, color: UIColor, shadowOffset: CGSize, shadowOpacity: CGFloat, shadowRadius: CGFloat){ 177 | view.layer.shadowColor = color.cgColor//shadowColor阴影颜色 178 | view.layer.shadowOffset = shadowOffset//shadowOffset阴影偏移,x向右偏移4,y向下偏移4,默认(0, -3),这个跟shadowRadius配合使用 179 | view.layer.shadowOpacity = Float(shadowOpacity)//阴影透明度,默认0 180 | view.layer.shadowRadius = shadowRadius//阴影半径,默认3 181 | } 182 | 183 | func compareDate(oneDay: NSDate, anotherDay: NSDate) -> Int{ 184 | 185 | let dateFormatter = DateFormatter.init() 186 | dateFormatter.dateFormat = "yyyy-MM" 187 | 188 | let dateA = dateFormatter.date(from: dateFormatter.string(from: oneDay as Date)) 189 | let dateB = dateFormatter.date(from: dateFormatter.string(from: anotherDay as Date)) 190 | 191 | let result = dateA?.compare(dateB!) 192 | if (result!.rawValue == ComparisonResult.orderedDescending.rawValue) { 193 | //NSLog(@"Date1 is in the future"); 194 | return 1; 195 | } 196 | else if (result!.rawValue == ComparisonResult.orderedAscending.rawValue){ 197 | //NSLog(@"Date1 is in the past"); 198 | return -1; 199 | } 200 | //NSLog(@"Both dates are the same"); 201 | return 0; 202 | } 203 | 204 | func getMonthEnd(date: NSDate) -> NSDate { 205 | let format = DateFormatter.init() 206 | format.dateFormat = "yyyy-MM" 207 | let newDate: Date = format.date(from: format.string(from: date as Date))! 208 | var interval: Double = 0 209 | var beginDate: Date = Date() 210 | var endDate: Date = Date() 211 | var calendar = NSCalendar.current 212 | calendar.firstWeekday = 2 //设定周一为周首日 213 | let ok: Bool = calendar.dateInterval(of: .month, start: &beginDate, interval: &interval, for: newDate) 214 | //分别修改为 NSDayCalendarUnit NSWeekCalendarUnit NSYearCalendarUnit 215 | if (ok) { 216 | endDate = beginDate.addingTimeInterval(interval - 1) 217 | }else { 218 | return Date.init() as NSDate; 219 | } 220 | let myDateFormatter = DateFormatter.init() 221 | myDateFormatter.dateFormat = "yyyy-MM-dd" 222 | endDate = myDateFormatter.date(from: myDateFormatter.string(from: endDate))! 223 | return endDate as NSDate; 224 | } 225 | 226 | func getMonthBegin(date: NSDate) -> NSDate { 227 | let format = DateFormatter.init() 228 | format.dateFormat = "yyyy-MM" 229 | let newDate: Date = format.date(from: format.string(from: date as Date))! 230 | var interval: Double = 0 231 | var beginDate: Date = Date() 232 | var endDate: Date = Date() 233 | var calendar = NSCalendar.current 234 | calendar.firstWeekday = 2 //设定周一为周首日 235 | 236 | let ok: Bool = calendar.dateInterval(of: .month, start: &beginDate, interval: &interval, for: newDate) 237 | //分别修改为 NSDayCalendarUnit NSWeekCalendarUnit NSYearCalendarUnit 238 | if (ok) { 239 | endDate = beginDate.addingTimeInterval(interval - 1) 240 | }else { 241 | return Date.init() as NSDate; 242 | } 243 | 244 | let myDateFormatter = DateFormatter.init() 245 | myDateFormatter.dateFormat = "yyyy-MM-dd" 246 | endDate = Date.init(timeInterval: -86400, since: beginDate) 247 | 248 | return endDate as NSDate; 249 | } 250 | -------------------------------------------------------------------------------- /ZHFToolBox/TBCalendar/TBCalendar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TBCalendar.swift 3 | // SwiftTest 4 | // 5 | // Created by 1111 on 2018/4/9. 6 | // Copyright © 2018年 xuejianfeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @objc protocol TBCalendarDataSource: NSObjectProtocol{ 12 | /** 13 | * Tells the dataSource a call back is the calendar of height. 14 | */ 15 | @objc func calender(calender: TBCalendar, layoutCallBackHeight: CGFloat) -> Void 16 | 17 | /** 18 | * Asks the dataSource for a title for the specific date as a replacement of the day text 19 | */ 20 | @objc optional func calendar(calendar: TBCalendar, titleForDate: NSDate) -> String 21 | 22 | /** 23 | * Asks the dataSource for a subtitle for the specific date under the day text. 24 | */ 25 | @objc optional func calender(calendar: TBCalendar, subTitleForDate: NSDate) -> String 26 | } 27 | 28 | @objc protocol TBCalendarDataDelegate: NSObjectProtocol{ 29 | /** 30 | * Asks the delegate whether the specific date is allowed to be selected by tapping. 31 | */ 32 | @objc optional func calender(calender: TBCalendar, shouldSelectDate: NSDate) -> Void 33 | 34 | /** 35 | * Tells the delegate a date in the calendar is selected by tapping. 36 | */ 37 | @objc optional func calender(calender: TBCalendar, didSelectDate: NSDate) -> Void 38 | } 39 | 40 | 41 | class TBCalendar: UIView, UICollectionViewDelegate, UICollectionViewDataSource{ 42 | static let TBCalendarDateCellID = "LZBCalendarDateCellID" 43 | static let limitation_Low = 28 44 | static let limitation_Medium = 35 45 | static let limitation_High = 42 46 | 47 | /** 48 | * The object that acts as the data source of the calendar. 49 | */ 50 | var dataSource: TBCalendarDataSource? 51 | 52 | /** 53 | * The object that acts as the data source of the calendar. 54 | */ 55 | var delegate: TBCalendarDataDelegate? 56 | 57 | private var itemHeight: CGFloat = 0 58 | private var style: TBCalendarAppearStyle? 59 | private var currentSelctCell: TBCalendarDateCell? 60 | private var dotArr = [UIView]() 61 | private var itemNum: Int? 62 | 63 | lazy var contentView: UIView = getContentView() 64 | lazy var collectionView: UICollectionView = getCollectionView() 65 | lazy var collectFlowLayout: UICollectionViewFlowLayout = getCollectFlowLayout() 66 | lazy var headerView: TBCalendarHeaderView = self.getHeaderView() 67 | 68 | init(style: TBCalendarAppearStyle, frame: CGRect) { 69 | super.init(frame: frame) 70 | self.style = style 71 | self.setupUI() 72 | } 73 | 74 | func setupUI() { 75 | self.addSubview(self.headerView) 76 | self.headerView.monthDate = (self.style?.today)! 77 | self.addSubview(self.contentView) 78 | self.contentView.addSubview(self.collectionView) 79 | self.collectionView.register(TBCalendarDateCell.self, forCellWithReuseIdentifier: TBCalendar.TBCalendarDateCellID) 80 | 81 | 82 | self.headerView.previousMonth = {(date) ->Void in 83 | self.style?.today = date; 84 | self.setNeedsLayout() 85 | self.collectionView.reloadData() 86 | } 87 | 88 | self.headerView.nextMonth = {(date) ->Void in 89 | self.style?.today = date; 90 | self.setNeedsLayout() 91 | self.collectionView.reloadData() 92 | } 93 | } 94 | 95 | override func layoutSubviews() { 96 | super.layoutSubviews() 97 | 98 | let width = self.bounds.size.width; 99 | self.headerView.frame = CGRect.init(x: 0, y: 0, width: width, height: (self.style?.headerViewHeihgt!)!); 100 | layoutCollectionView() 101 | self.itemNum = 1; 102 | } 103 | 104 | func layoutCollectionView() { 105 | 106 | let itemWidth = Int(self.bounds.size.width) / (self.style?.weekDateDays.count)!; 107 | var itemHeight = itemWidth; 108 | if((self.style?.isNeedCustomHeihgt)! && (self.style?.itemHeight)! > 0.0) 109 | { 110 | itemHeight = Int((self.style?.itemHeight)!) 111 | } 112 | else 113 | { 114 | itemHeight = itemWidth; 115 | } 116 | self.itemHeight = CGFloat(itemHeight); 117 | self.collectFlowLayout.itemSize = CGSize.init(width: CGFloat(itemWidth), height: CGFloat(itemHeight - 10)) 118 | 119 | //collectinView高度 120 | let marginDays = self.firstDayInFirstWeekThisMonth(date: (self.style?.today)!) 121 | let itemCount = marginDays + self.totalDaysThisMonth(date: (self.style?.today)!) 122 | var collectionViewHeight = 0; 123 | if(itemCount <= TBCalendar.limitation_Low){ 124 | collectionViewHeight = TBCalendar.limitation_Low / (self.style?.weekDateDays.count)! * Int(self.itemHeight) 125 | } 126 | else if(itemCount > TBCalendar.limitation_Low && itemCount <= TBCalendar.limitation_Medium){ 127 | collectionViewHeight = TBCalendar.limitation_Medium/(self.style?.weekDateDays.count)! * Int(self.itemHeight) 128 | } 129 | else{ 130 | collectionViewHeight = TBCalendar.limitation_High/(self.style?.weekDateDays.count)! * Int(self.itemHeight) 131 | } 132 | 133 | 134 | self.collectionView.frame = CGRect.init(x: 0, y: 0, width: Int(self.bounds.size.width), height: collectionViewHeight - 50); 135 | 136 | 137 | self.contentView.frame = CGRect.init(x: 0, y: self.headerView.frame.maxY, width: self.bounds.size.width, height: CGFloat(Int(collectionViewHeight) - 50)) 138 | self.collectionView.collectionViewLayout = self.collectFlowLayout 139 | 140 | self.callBackHeight(height: CGFloat(collectionViewHeight) + (self.style?.headerViewHeihgt)! + 10) 141 | } 142 | // collectCell-dataSource 143 | func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool { 144 | 145 | let marginDays = self.firstDayInFirstWeekThisMonth(date: (self.style?.today)!) 146 | let daysThisMonth = self.totalDaysThisMonth(date: (self.style?.today)!) 147 | 148 | if(indexPath.row >= marginDays && indexPath.row <= marginDays + daysThisMonth - 1) 149 | { 150 | var day = 0; 151 | day = indexPath.row - marginDays + 1 152 | let date = self.dateByday(day: day, date: (self.style?.today)!) 153 | 154 | return self.shouldSelectDate(date: date as NSDate) 155 | } 156 | else{ 157 | return false 158 | } 159 | 160 | } 161 | 162 | @objc func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 163 | 164 | let marginDays: NSInteger = self.firstDayInFirstWeekThisMonth(date: (self.style?.today)!); 165 | let daysThisMonth: NSInteger = self.totalDaysThisMonth(date: (self.style?.today)!); 166 | if(indexPath.row >= marginDays && (indexPath.row <= (marginDays + daysThisMonth - 1))){ 167 | 168 | let day: NSInteger = indexPath.row - marginDays + 1 169 | let date: Date = self.dateByday(day: day, date: (self.style?.today)!) 170 | let cell: TBCalendarDateCell = collectionView.cellForItem(at: indexPath) as! TBCalendarDateCell 171 | if(self.style!.isSupportMoreSelect!){ 172 | self.didSelectDate(date: date as NSDate) 173 | cell.updateCellSelectCellColor() 174 | } 175 | else 176 | { 177 | if(self.currentSelctCell == cell) 178 | { 179 | return; 180 | } 181 | 182 | self.currentSelctCell?.isSelected = false 183 | self.currentSelctCell?.updateCellSelectCellColor() 184 | cell.isSelected = true 185 | self.currentSelctCell = cell 186 | self.didSelectDate(date: date as NSDate) 187 | cell.updateCellSelectCellColor(animation:true) 188 | } 189 | } 190 | else 191 | { 192 | // self.collectionView(collectionView, didDeselectItemAt: indexPath) 193 | } 194 | } 195 | 196 | // DataSource 197 | func titleForDate(date: NSDate) -> String { 198 | 199 | if (self.dataSource != nil) && (self.dataSource?.responds(to: #selector(TBCalendarDataSource.calendar(calendar:titleForDate:))))! { 200 | return (self.dataSource?.calendar!(calendar: self, titleForDate: date))! 201 | } 202 | 203 | return ""; 204 | } 205 | 206 | 207 | func subtitleForDate(date: NSDate) -> String { 208 | if (self.dataSource != nil) && (self.dataSource?.responds(to: #selector(TBCalendarDataSource.calender(calendar:subTitleForDate:))))! { 209 | return (self.dataSource?.calender!(calendar: self, subTitleForDate: date))! 210 | } 211 | 212 | return "" 213 | } 214 | 215 | func callBackHeight(height: CGFloat) -> Void { 216 | if (self.dataSource != nil) && (self.dataSource?.responds(to: #selector(TBCalendarDataSource.calender(calender:layoutCallBackHeight:))))! { 217 | return (self.dataSource?.calender(calender: self, layoutCallBackHeight: height))! 218 | } 219 | } 220 | 221 | // delegate 222 | func shouldSelectDate(date: NSDate) -> Bool { 223 | 224 | if (self.delegate != nil) && (self.delegate?.responds(to: #selector(TBCalendarDataDelegate.calender(calender:shouldSelectDate:))))! { 225 | return ((self.delegate?.calender!(calender: self, shouldSelectDate: date)) != nil) 226 | } 227 | 228 | return true 229 | } 230 | 231 | func didSelectDate(date: NSDate) { 232 | 233 | if (self.delegate != nil) && (self.delegate?.responds(to: #selector(TBCalendarDataDelegate.calender(calender:didSelectDate:))))! { 234 | self.delegate?.calender!(calender: self, didSelectDate: date) 235 | } 236 | } 237 | 238 | func setDataArr(arr: [UIView]) { 239 | self.dotArr.removeAll() 240 | self.dotArr += arr 241 | self.collectionView.reloadData() 242 | } 243 | 244 | // private 245 | func totalDaysThisMonth(date: NSDate) -> Int { 246 | let range = NSCalendar.current.range(of: .day, in: .month, for: date as Date) 247 | 248 | return (range?.count)! 249 | } 250 | 251 | func firstDayInFirstWeekThisMonth(date: NSDate) -> Int { 252 | var calendar = NSCalendar.current 253 | calendar.firstWeekday = 1 254 | 255 | var comp = calendar.dateComponents([.year, .month, .day], from: date as Date) 256 | comp.day = 1; 257 | 258 | let firstDayOfMonthDate = calendar.date(from: comp) 259 | let firstWeekday = calendar.ordinality(of: .weekday, in: .weekOfMonth, for: firstDayOfMonthDate!) 260 | return firstWeekday! - 1 261 | } 262 | 263 | func dateByday(day: Int, date: NSDate) -> Date { 264 | let calendar = NSCalendar.current 265 | let comp = calendar.dateComponents([.year, .month, .day], from: date as Date) 266 | let newComp = NSDateComponents.init() 267 | newComp.day = day 268 | newComp.year = comp.year! 269 | newComp.month = comp.month! 270 | 271 | let formatter = DateFormatter.init() 272 | formatter.dateFormat = "YYYY-MM-dd" 273 | let string: String = "\(newComp.year)" + "-" + "\(newComp.month)" + "-" + "\(newComp.day)" 274 | 275 | return formatter.date(from: string)! 276 | } 277 | 278 | // UICollectionViewDataSource 279 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 280 | 281 | let marginDays = self.firstDayInFirstWeekThisMonth(date: (self.style?.today)!) 282 | let itemCount = marginDays + self.totalDaysThisMonth(date: (self.style?.today)!) 283 | 284 | if itemCount >= TBCalendar.limitation_High { 285 | return 0 286 | } 287 | 288 | if (itemCount > TBCalendar.limitation_Medium) && (itemCount <= TBCalendar.limitation_High) { 289 | return TBCalendar.limitation_High 290 | } 291 | else if (itemCount > TBCalendar.limitation_Low) && (itemCount <= TBCalendar.limitation_Medium){ 292 | return TBCalendar.limitation_Medium 293 | } 294 | else{ 295 | return TBCalendar.limitation_Low 296 | } 297 | } 298 | 299 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 300 | 301 | let cell: TBCalendarDateCell = collectionView.dequeueReusableCell(withReuseIdentifier: TBCalendar.TBCalendarDateCellID, for: indexPath) as! TBCalendarDateCell 302 | cell.isSelected = false 303 | cell.updateCellSelectCellColor() 304 | cell.style = (self.style)! 305 | let marginDays = self.firstDayInFirstWeekThisMonth(date: (self.style?.today)!) 306 | let daysThisMonth = self.totalDaysThisMonth(date: (self.style?.today)!) 307 | 308 | cell.updateCellDotView(status: "7") 309 | if indexPath.row < marginDays { 310 | cell.updateCellDotView(status: "7") 311 | cell.reloadCellData(title: "", subTitle: "") 312 | } 313 | else if indexPath.row > (marginDays + daysThisMonth - 1) { 314 | cell.updateCellDotView(status: "7") 315 | cell.reloadCellData(title: "", subTitle: "") 316 | } 317 | else{ 318 | cell.updateCellDotView(status: "7") 319 | 320 | let day = indexPath.row - marginDays + 1 321 | let date = self.dateByday(day: day, date: (self.style?.today)!) 322 | cell.isSelected = self.isToday(date: date, cell: cell) 323 | 324 | let row = indexPath.row 325 | if (row % 7 == 0) || ((row + 1) % 7 == 0){ 326 | cell.dateLabel.textColor = UIColor.UIColorFromRGB(rgb: 0x999999) 327 | } 328 | else{ 329 | cell.dateLabel.textColor = UIColor.UIColorFromRGB(rgb: 0x000000) 330 | } 331 | 332 | let dateFormatter = DateFormatter.init() 333 | dateFormatter.dateFormat = "dd" 334 | 335 | if self.dotArr.count > 0 { 336 | 337 | let v = self.dotArr[indexPath.row - marginDays] 338 | if v.tag == -2 || v.tag == -1{ 339 | cell.isSelected = true; 340 | self.currentSelctCell = cell 341 | } 342 | else 343 | { 344 | cell.isSelected = false 345 | } 346 | } 347 | else{ 348 | cell.updateCellDotView(status: "7") 349 | } 350 | 351 | let dateStr: String = self.titleForDate(date: date as NSDate) 352 | if dateStr.count > 0{ 353 | cell.reloadCellData(title: dateStr) 354 | } 355 | else { 356 | cell.reloadCellData(title: "\(day)") 357 | } 358 | } 359 | 360 | cell.updateCellSelectBackgroundColor() 361 | return cell 362 | } 363 | 364 | func isToday(date: Date, cell: TBCalendarDateCell) -> Bool { 365 | 366 | let nowDate = Date() 367 | if date.getDateWithMonth() == nowDate.getDateWithMonth() { 368 | let result = nowDate.getDateWithDay() - date.getDateWithDay() 369 | if result == 0 { 370 | self.currentSelctCell = cell 371 | return true 372 | } 373 | else { 374 | return false 375 | } 376 | } 377 | 378 | return true 379 | } 380 | 381 | // lazy 382 | func getHeaderView() -> TBCalendarHeaderView { 383 | let headerView = TBCalendarHeaderView.init(type: .centerDate, style: self.style!, frame: CGRect.init()) 384 | return headerView 385 | } 386 | 387 | func getContentView() -> UIView { 388 | let view = UIView.init() 389 | view.backgroundColor = UIColor.UIColorFromRGB(rgb: 0xffffff) 390 | return view 391 | } 392 | 393 | func getCollectionView() -> UICollectionView { 394 | let collectionView = UICollectionView.init(frame: self.contentView.bounds, collectionViewLayout: self.collectFlowLayout) 395 | collectionView.dataSource = self 396 | collectionView.delegate = self 397 | collectionView.backgroundColor = UIColor.UIColorFromRGB(rgb: 0xffffff) 398 | return collectionView 399 | } 400 | 401 | func getCollectFlowLayout() -> UICollectionViewFlowLayout { 402 | let collectFlowLayout = UICollectionViewFlowLayout.init() 403 | collectFlowLayout.minimumLineSpacing = 0.0; 404 | collectFlowLayout.minimumInteritemSpacing = 0.0; 405 | collectFlowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0); 406 | return collectFlowLayout 407 | } 408 | 409 | required init?(coder aDecoder: NSCoder) { 410 | fatalError("init(coder:) has not been implemented") 411 | } 412 | } 413 | -------------------------------------------------------------------------------- /ZHFToolBox/TBCalendar/TBCalendarAppearStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TBCalendarAppearStyle.swift 3 | // SwiftTest 4 | // 5 | // Created by 1111 on 2018/4/2. 6 | // Copyright © 2018年 xuejianfeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TBCalendarAppearStyle: NSObject { 12 | // head-data 13 | /** 14 | * 设置item的高度,isNeedCustomHeihgt是YES,可以设置itemHeight 15 | */ 16 | var isNeedCustomHeihgt: Bool? 17 | /** 18 | * 设置当前日期 19 | */ 20 | var today: NSDate? 21 | /** 22 | * 设置是否支持同时选中多个日期,默认isSupportMoreSelect = NO 23 | */ 24 | var isSupportMoreSelect: Bool? 25 | /** 26 | * 设置星期日期的样式,默认是中文 @"日",@"一",@"二",@"三",@"四",@"五",@"六" 27 | */ 28 | var weekDateDays = [String]() 29 | 30 | //头部style设置 31 | /** 32 | * 设置头部View的选择月份View的高度 33 | */ 34 | var headerViewDateHeight: CGFloat? 35 | /** 36 | * 设置头部View的星期几View的高度 37 | */ 38 | var headerViewWeekHeight: CGFloat? 39 | /** 40 | * 设置头部View的星期几View与选择月份View中间分割线的高度 41 | */ 42 | var headerViewLineHeight: CGFloat? 43 | /** 44 | * 获得整个头部View的高度 45 | */ 46 | var headerViewHeihgt: CGFloat? 47 | /** 48 | * 设置头部View的选择月份View的字体 49 | */ 50 | var headerViewDateFont: UIFont? 51 | /** 52 | * 设置头部View的选择月份View的字体颜色 53 | */ 54 | var headerViewDateColor: UIColor? 55 | /** 56 | * 设置头部View的星期几View的字体 57 | */ 58 | var headerViewWeekFont: UIFont? 59 | /** 60 | * 设置头部View的星期几View的字体颜色 61 | */ 62 | var headerViewWeekColor: UIColor? 63 | 64 | // 日期sytle设置 65 | /** 66 | * 设置日期item的的高度,宽度根据屏幕宽度自动适应 isNeedCustomHeihgt = YES 有效 67 | */ 68 | var itemHeight: CGFloat? 69 | /** 70 | * 设置日期item的标题字体大小 71 | */ 72 | var dateTittleFont: UIFont? 73 | /** 74 | * 设置日期item的描述字体大小 75 | */ 76 | var dateDescFont: UIFont? 77 | /** 78 | * 设置日期item的标题字体选中颜色 79 | */ 80 | var dateTittleSelectColor: UIColor? 81 | /** 82 | * 设置日期item的标题字体未选中颜色 83 | */ 84 | var dateTittleUnselectColor: UIColor? 85 | /** 86 | * 设置日期item的选中背景颜色 87 | */ 88 | var dateBackSelectColor: UIColor? 89 | /** 90 | * 设置日期item的未选中背景颜色 91 | */ 92 | var dateBackUnselectColor: UIColor? 93 | /** 94 | * 设置日期item的描述选中背景颜色 95 | */ 96 | var dateDescSelectColor: UIColor? 97 | /** 98 | * 设置日期item的描述未选中背景颜色 99 | */ 100 | var dateDescUnselectColor: UIColor? 101 | /** 102 | * 设置日期item的title与描述间距 UIOffset 103 | */ 104 | var dateTitleDescOffset: UIOffset? 105 | 106 | override init() { 107 | self.isNeedCustomHeihgt = true; 108 | self.today = NSDate.init(); 109 | 110 | self.headerViewDateHeight = 70; 111 | self.headerViewLineHeight = 1.0; 112 | self.headerViewWeekHeight = 20; 113 | self.weekDateDays = ["S","M","T","W","T","F","S"] 114 | self.headerViewDateFont = UIFont.systemFont(ofSize: 18) 115 | self.headerViewWeekFont = UIFont.systemFont(ofSize: 14) 116 | self.headerViewWeekColor = ZHFColor.zhf_color(withHex: 0x4F505F) 117 | self.headerViewDateColor = ZHFColor.zhf_color(withHex: 0x4F505F) 118 | 119 | self.itemHeight = 0; 120 | self.dateTittleFont = UIFont.systemFont(ofSize: 14) 121 | self.dateDescFont = UIFont.systemFont(ofSize: 14) 122 | self.dateTittleSelectColor = ZHFColor.zhf_color(withHex: 0x000000) 123 | self.dateTittleUnselectColor = ZHFColor.zhf_color(withHex: 0x000000) 124 | self.dateDescSelectColor = UIColor.blue 125 | self.dateDescUnselectColor = UIColor.purple 126 | self.dateBackUnselectColor = UIColor.white 127 | self.dateBackSelectColor = ZHFColor.zhf_color(withHex: 0xEEEEEE) 128 | self.isSupportMoreSelect = false; 129 | self.dateTitleDescOffset = UIOffset(horizontal: 0, vertical: 10); 130 | self.headerViewHeihgt = headerViewDateHeight! + headerViewLineHeight! + headerViewWeekHeight! 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /ZHFToolBox/TBCalendar/TBCalendarDateCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TBCalendarDateCell.swift 3 | // SwiftTest 4 | // 5 | // Created by 1111 on 2018/4/9. 6 | // Copyright © 2018年 xuejianfeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TBCalendarDateCell: UICollectionViewCell { 12 | public var style: TBCalendarAppearStyle{ 13 | get{ 14 | return TBCalendarAppearStyle.init() 15 | } 16 | 17 | set{ 18 | self.setStyle(style: newValue) 19 | } 20 | } 21 | lazy var dateLabel: UILabel = getDateLabel() 22 | lazy var dotView: UIView = getDotView() 23 | public var isToday: Bool? 24 | 25 | lazy var descLabel: UILabel = getDescLabel() 26 | private var dateLableHeight: CGFloat = 0 27 | private var descLabelHeiht: CGFloat = 0 28 | 29 | override init(frame: CGRect) { 30 | super.init(frame: frame) 31 | 32 | self.contentView.addSubview(dateLabel) 33 | self.contentView.addSubview(descLabel) 34 | self.dateLabel.addSubview(dotView) 35 | } 36 | 37 | override func layoutSubviews() { 38 | super.layoutSubviews() 39 | 40 | let width = self.bounds.size.width 41 | let height = self.bounds.size.height 42 | if(self.dateLableHeight > 0) 43 | { 44 | self.dateLabel.center = CGPoint.init(x: width * 0.5, y: height * 0.5) 45 | self.dateLabel.bounds = CGRect.init(x: 0, y: 0, width: 34, height: 34) 46 | 47 | self.dotView.center.x = self.dateLabel.frame.width * 0.5; 48 | self.dotView.center.y = self.dateLabel.frame.height * 0.5 + 10; 49 | self.dotView.bounds = CGRect.init(x: 0, y: 0, width: 4, height: 4) 50 | } 51 | if(self.descLabelHeiht > 0) 52 | { 53 | self.descLabel.center = CGPoint.init(x: width*0.5, y: height*0.5 + self.descLabelHeiht*0.5+(self.style.dateTitleDescOffset?.vertical)! * 0.5); 54 | self.descLabel.bounds = CGRect.init(x: 0, y: 0, width: Int(width), height: Int(self.descLabelHeiht) - 2) 55 | } 56 | } 57 | 58 | func setStyle(style: TBCalendarAppearStyle) { 59 | 60 | let str = "1" 61 | self.dateLableHeight = str.textHeight(fontSize: (style.dateTittleFont?.pointSize)!, width: 20) 62 | self.descLabelHeiht = str.textHeight(fontSize: (style.dateDescFont?.pointSize)!, width: 20) 63 | self.dateLabel.font = style.dateTittleFont; 64 | self.dateLabel.textColor = self.isSelected ? style.dateTittleSelectColor:style.dateTittleUnselectColor; 65 | self.descLabel.font = style.dateDescFont; 66 | self.descLabel.textColor = self.isSelected ? style.dateDescSelectColor:style.dateDescUnselectColor; 67 | } 68 | // 暴露出来的方法,供外界使用 69 | func reloadCellData(title: String) { 70 | self.dateLabel.text = title.count > 0 ? title : "" 71 | } 72 | 73 | func reloadCellData(subtitle: String) { 74 | self.descLabel.text = subtitle.count > 0 ? subtitle : "" 75 | } 76 | 77 | func reloadCellData(title: String, subTitle: String) { 78 | reloadCellData(title: title) 79 | reloadCellData(subtitle: subTitle) 80 | } 81 | 82 | func updateCellDotView(status: String) { 83 | // 旷工0 迟到1 早退2 异常3 人工处理过异常4 ERP处理过异常5 法定节假日6 休息7 正常8 84 | // 蓝色8 橙色0,1,2,3,9 剩下状态为没有颜色 85 | 86 | let statusToInt = Int(status) 87 | if (status.count > 0) { 88 | if (statusToInt == 8) { //正常签到或者ERP有补签卡都是正常 89 | self.dotView.backgroundColor = UIColor.UIColorFromRGB(rgb: 0x29B6F6) 90 | } 91 | else if (statusToInt == 0 || statusToInt == 1 || statusToInt == 2 || statusToInt == 3 || statusToInt == 9) 92 | { 93 | self.dotView.backgroundColor = UIColor.UIColorFromRGB(rgb: 0xF48900) 94 | } 95 | else 96 | { 97 | self.dotView.backgroundColor = UIColor.clear 98 | } 99 | } 100 | else 101 | { 102 | // 现在后台返回30条数据,然后status为null然后doubleValue后为0,所以会显示为旷工颜色,所以要做判空处理 103 | self.dotView.backgroundColor = UIColor.clear 104 | } 105 | } 106 | 107 | func updateCellSelectBackgroundColor() { 108 | self.dateLabel.backgroundColor = self.isSelected ? UIColor.UIColorFromRGB(rgb: 0xEEEEEE) : UIColor.UIColorFromRGB(rgb: 0xffffff); 109 | } 110 | 111 | func updateCellSelectTitleColor() { 112 | //self.dateLabel.textColor = self.isSelected ? self.style.dateTittleSelectColor:self.style.dateTittleUnselectColor; 113 | } 114 | 115 | func updateCellSelectSubtitleColor() { 116 | //self.descLabel.textColor = self.isSelected ? self.style.dateDescSelectColor:self.style.dateDescUnselectColor; 117 | } 118 | 119 | func updateCellSelectCellColor() { 120 | updateCellSelectCellColor(animation: false) 121 | } 122 | 123 | func updateCellSelectCellColor(animation: Bool) { 124 | 125 | updateCellSelectTitleColor() 126 | updateCellSelectSubtitleColor() 127 | updateCellSelectBackgroundColor() 128 | } 129 | 130 | // lazy 相关函数 131 | func getDateLabel() -> UILabel { 132 | let dateLabel = UILabel.init() 133 | dateLabel.layer.cornerRadius = 17 134 | dateLabel.layer.masksToBounds = true 135 | dateLabel.textAlignment = .center 136 | return dateLabel 137 | } 138 | 139 | func getDotView() -> UIView { 140 | let dotView = UIView.init() 141 | dotView.layer.cornerRadius = 2; 142 | dotView.layer.masksToBounds = true 143 | dotView.backgroundColor = UIColor.clear 144 | return dotView 145 | } 146 | 147 | func getDescLabel() -> UILabel { 148 | let descLabel = UILabel.init() 149 | descLabel.textAlignment = .center 150 | return descLabel 151 | } 152 | 153 | required init?(coder aDecoder: NSCoder) { 154 | fatalError("init(coder:) has not been implemented") 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /ZHFToolBox/TBCalendar/TBCalendarHeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TBCalendarHeaderView.swift 3 | // SwiftTest 4 | // 5 | // Created by 1111 on 2018/4/2. 6 | // Copyright © 2018年 xuejianfeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | class TBCalendarHeaderView: UIView { 11 | 12 | typealias click = (NSDate) -> Void 13 | public var previousMonth: ((_ date: NSDate) -> Void)? 14 | public var nextMonth: ((_ date: NSDate) -> Void)? 15 | public var monthDate: NSDate{ 16 | get{ 17 | return remberMonthDate 18 | } 19 | 20 | set{ 21 | remberMonthDate = newValue 22 | self.setMonthDate(date: newValue) 23 | } 24 | } 25 | private var remberMonthDate = NSDate() 26 | private var headType: TBCalendarHeaderViewType 27 | private var style: TBCalendarAppearStyle 28 | lazy var topView: UIView = getTopView() 29 | lazy var dateLable: UILabel = getDateLable() 30 | lazy var previousButton: UIButton = getPreviousButton() 31 | lazy var nextButton: UIButton = getNextButton() 32 | lazy var bottomView: UIView = UIView.init() 33 | lazy var weekdayLabels: [UILabel] = [UILabel]() 34 | lazy var lineView: UIView = UIView.init() 35 | 36 | init(type: TBCalendarHeaderViewType, style: TBCalendarAppearStyle, frame: CGRect) { 37 | self.headType = type 38 | self.style = style 39 | super.init(frame: frame) 40 | self.setupUI() 41 | } 42 | 43 | func setupUI() { 44 | self.addSubview(self.topView) 45 | self.addSubview(self.bottomView) 46 | self.addSubview(self.lineView) 47 | self.topView.addSubview(self.dateLable) 48 | 49 | switch self.headType { 50 | case TBCalendarHeaderViewType.leftDate: 51 | break; 52 | case TBCalendarHeaderViewType.centerDate: 53 | self.topView.addSubview(self.previousButton) 54 | self.topView.addSubview(self.nextButton) 55 | self.previousButton.isHidden = false 56 | self.nextButton.isHidden = false 57 | break; 58 | } 59 | 60 | let weekDateDays: [String] = self.style.weekDateDays 61 | 62 | for _ in weekDateDays 63 | { 64 | let label = UILabel.init(frame: CGRect.zero) 65 | label.textAlignment = .center 66 | self.bottomView.addSubview(label) 67 | self.weekdayLabels.append(label) 68 | } 69 | 70 | self.initValidSettingData() 71 | } 72 | 73 | override func layoutSubviews() { 74 | super.layoutSubviews() 75 | let selfWidth: CGFloat = self.bounds.size.width 76 | 77 | if self.style.isNeedCustomHeihgt! { 78 | self.topView.frame = CGRect.init(x: 0, y:0, width: selfWidth, height: self.style.headerViewDateHeight!) 79 | self.lineView.frame = CGRect.init(x: 0, y: self.topView.frame.maxY, width: selfWidth, height: self.style.headerViewLineHeight!) 80 | self.bottomView.frame = CGRect.init(x: 0, y: self.lineView.frame.maxY, width: selfWidth, height: self.style.headerViewWeekHeight!) 81 | 82 | switch (self.headType) 83 | { 84 | case .leftDate: 85 | 86 | self.dateLable.frame = CGRect.init(x: 0, y: 0, width: selfWidth, height: self.topView.frame.size.height); 87 | self.dateLable.textAlignment = .center; 88 | 89 | break; 90 | case .centerDate: 91 | 92 | let image = UIImage.init(named: "icon_switch") 93 | self.dateLable.frame = CGRect.init(x: selfWidth * 0.5 - 60, y: 0, width: 120, height: self.topView.frame.size.height); 94 | 95 | self.previousButton.frame = CGRect.init(x: 30, y: 0, width: (image?.size.width)! + 20, height: self.topView.frame.size.height); 96 | self.nextButton.frame = CGRect.init(x: selfWidth - (image?.size.width)! - 50, y: 0, width: (image?.size.width)! + 20, height: self.topView.frame.size.height); 97 | break; 98 | } 99 | 100 | let weekdayWidth = self.bottomView.bounds.size.width / CGFloat(self.style.weekDateDays.count) 101 | let weekdayHeight = self.bottomView.bounds.size.height; 102 | 103 | 104 | for (index, value) in self.weekdayLabels.enumerated() { 105 | 106 | value.frame = CGRect.init(x: CGFloat(index) * weekdayWidth, y: 0, width: weekdayWidth, height: weekdayHeight) 107 | } 108 | } 109 | else 110 | { 111 | //计算高度 112 | } 113 | } 114 | 115 | func initValidSettingData(){ 116 | self.dateLable.font = self.style.headerViewDateFont; 117 | self.dateLable.textColor = self.style.headerViewDateColor; 118 | 119 | for item: UILabel in self.weekdayLabels { 120 | item.font = self.style.headerViewWeekFont 121 | item.textColor = self.style.headerViewWeekColor 122 | } 123 | 124 | for (index, value) in self.weekdayLabels.enumerated() { 125 | 126 | if index < self.style.weekDateDays.count { 127 | value.text = self.style.weekDateDays[index]; 128 | } 129 | } 130 | } 131 | 132 | func getTopView() -> UIView { 133 | let topView = UIView.init() 134 | topView.backgroundColor = UIColor.white 135 | return topView 136 | } 137 | 138 | func getDateLable() -> UILabel { 139 | let dateLabel = UILabel.init() 140 | dateLabel.numberOfLines = 2 141 | dateLabel.textAlignment = .center 142 | return dateLabel 143 | } 144 | 145 | func getPreviousButton() -> UIButton { 146 | let btn = UIButton.init(type: .custom) 147 | btn.setImage(UIImage.init(named: "icon_switch"), for: .normal) 148 | btn.addTarget(self, action: #selector(previousButtonClick), for: .touchUpInside) 149 | return btn 150 | } 151 | 152 | func getNextButton() -> UIButton { 153 | let btn = UIButton.init(type: .custom) 154 | btn.setImage(UIImage.init(named: "icon_switch_r"), for: .normal) 155 | btn.addTarget(self, action: #selector(nextButtonClick), for: .touchUpInside) 156 | return btn 157 | } 158 | 159 | @objc func previousButtonClick() { 160 | self.monthDate = self.lastMonth(date: self.monthDate) 161 | NotificationCenter.default.post(name: NSNotification.Name(rawValue: CHANGE_SELECT_DATE), object: monthDate) 162 | if self.previousMonth != nil { 163 | self.previousMonth!(self.monthDate) 164 | } 165 | } 166 | 167 | @objc func nextButtonClick() { 168 | self.monthDate = self.nextMonth(date: self.monthDate) 169 | NotificationCenter.default.post(name: NSNotification.Name(rawValue: CHANGE_SELECT_DATE), object: monthDate) 170 | if self.nextMonth != nil { 171 | self.nextMonth!(self.monthDate) 172 | } 173 | } 174 | 175 | func setMonthDate(date: NSDate){ 176 | //如果点击的日期超过当前日期 不让其点击 || [TBUtils compareOneDay:monthDate withAnotherDay:[NSDate dateWithString:@"2017-03" format:@"yyyy-MM"]] == -1 177 | if compareDate(oneDay: monthDate, anotherDay: Date() as NSDate) == 1 { 178 | return; 179 | } 180 | 181 | self.nextButton.alpha = 1; 182 | self.previousButton.alpha = 1; 183 | 184 | let monthStr: String = self.month(date: date) 185 | let yearStr: String = "\(self.year(year: date))." 186 | self.dateLable.text = yearStr + monthStr 187 | //self.dateLable.attributedText = self.createAttrStr(monthStr: monthStr, yearStr: yearStr) 188 | 189 | var date = getMonthEnd(date: date) 190 | 191 | let myDateFormatter = DateFormatter.init() 192 | myDateFormatter.dateFormat = "yyyy-MM-dd" 193 | let endDate = Date.init(timeInterval: 86400, since: date as Date) 194 | 195 | 196 | if (compareDate(oneDay: endDate as NSDate, anotherDay: NSDate()) == 1) { 197 | self.nextButton.alpha = 0.5; 198 | self.nextButton.isEnabled = false; 199 | } 200 | else 201 | { 202 | self.nextButton.alpha = 1; 203 | self.nextButton.isEnabled = true; 204 | } 205 | 206 | date = getMonthBegin(date: date) 207 | let PreDate = Date.init(timeInterval: -86400, since: date as Date) 208 | 209 | let dateFormatter = DateFormatter.init() 210 | dateFormatter.dateFormat = "yyyy-MM" 211 | 212 | if compareDate(oneDay: PreDate as NSDate, anotherDay: dateFormatter.date(from: "2017-03")! as NSDate) == -1 { 213 | self.previousButton.alpha = 0.5; 214 | self.previousButton.isEnabled = false; 215 | } 216 | else 217 | { 218 | self.previousButton.alpha = 1; 219 | self.previousButton.isEnabled = true; 220 | } 221 | } 222 | 223 | func nextMonth(date: NSDate) -> NSDate{ 224 | 225 | let dateComponents = NSDateComponents.init() 226 | let currentMonth = self.month(date: date) 227 | 228 | if(currentMonth == "12") 229 | { 230 | dateComponents.year = +1; 231 | dateComponents.month = -11; 232 | } 233 | else 234 | { 235 | dateComponents.month = +1; 236 | } 237 | 238 | return NSCalendar.current.date(byAdding: dateComponents as DateComponents, to: date as Date)! as NSDate 239 | } 240 | 241 | func lastMonth(date: NSDate) -> NSDate{ 242 | let dateComponents = NSDateComponents.init() 243 | let currentMonth = self.month(date: date) 244 | if(currentMonth == "01") 245 | { 246 | dateComponents.year = -1; 247 | dateComponents.month = +11; 248 | } 249 | else 250 | { 251 | dateComponents.month = -1; 252 | } 253 | 254 | return NSCalendar.current.date(byAdding: dateComponents as DateComponents, to: date as Date)! as NSDate 255 | } 256 | 257 | func month(date: NSDate) -> String { 258 | var str = "" 259 | if (NSCalendar.current.component(.month, from: date as Date) < 10) { 260 | str = "0" + "\(NSCalendar.current.component(.month, from: date as Date))" 261 | } 262 | else 263 | { 264 | str = "\(NSCalendar.current.component(.month, from: date as Date))" 265 | } 266 | 267 | return str; 268 | } 269 | 270 | func year(year: NSDate) -> Int{ 271 | return NSCalendar.current.component(.year, from: year as Date) 272 | } 273 | 274 | func createAttrStr(monthStr: String, yearStr: String) -> NSMutableAttributedString{ 275 | let monthDict = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 24), NSAttributedString.Key.foregroundColor:ZHFColor.zhf_color(withHex: 0x4F505F)] 276 | let yearDict = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor:ZHFColor.zhf_color(withHex: 0x999999)] 277 | 278 | let str: String = monthStr + yearStr 279 | 280 | let mutableAtt: NSMutableAttributedString = NSMutableAttributedString.init(string: str, attributes: monthDict) 281 | mutableAtt.addAttributes(yearDict, range: NSRange.init(location: monthStr.count, length: yearStr.count)) 282 | 283 | return mutableAtt 284 | } 285 | 286 | required init?(coder aDecoder: NSCoder) { 287 | fatalError("init(coder:) has not been implemented") 288 | } 289 | 290 | } 291 | -------------------------------------------------------------------------------- /ZHFToolBox/TopTopTranslucentTableView/MessgeShowVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessgeAlapaTableView.swift 3 | // Swift Test 4 | // 5 | // Created by IOSZHF on 2022/5/17. 6 | // 7 | 8 | import UIKit 9 | 10 | class MessgeShowVC: UIViewController { 11 | var number: NSInteger = 0 12 | var time: Timer = Timer() 13 | var topTranslucentTableView: TopTranslucentTableView = TopTranslucentTableView() 14 | 15 | override func viewWillDisappear(_ animated: Bool) { 16 | super.viewWillDisappear(animated) 17 | self.time.invalidate() 18 | } 19 | deinit { 20 | print("销毁MessgeAlapaTableView") 21 | } 22 | override func viewDidLoad() { 23 | super.viewDidLoad() 24 | self.view.backgroundColor = UIColor.white 25 | //背景图 26 | let imageView: UIView = UIImageView.init(image: UIImage.init(named: "back_ground")) 27 | imageView.frame = CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height) 28 | imageView.contentMode = .scaleAspectFill 29 | self.view.addSubview(imageView) 30 | topTranslucentTableView.frame = CGRect.init(x: 0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 300) 31 | self.view.addSubview(topTranslucentTableView.initTopTranslucentTableView()) 32 | 33 | self.time = Timer.init(timeInterval: 1, target: self, selector: #selector(addMessage), userInfo: nil, repeats: true) 34 | RunLoop.current.add(self.time, forMode: .common)//,common 保证滚动时定时器也走 35 | } 36 | @objc func addMessage() { 37 | number = number + 1 38 | topTranslucentTableView.addMessageData(number: number) 39 | if number==20{//20秒关闭定时器退到上一页 40 | self.time.invalidate() 41 | self.navigationController?.popViewController(animated: true) 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /ZHFToolBox/TopTopTranslucentTableView/NormalCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NormalCell.swift 3 | // Swift Test 4 | // 5 | // Created by IOSZHF on 2022/5/17. 6 | // 7 | 8 | import UIKit 9 | 10 | class NormalCell: UITableViewCell { 11 | 12 | @IBOutlet weak var messageLabel: UILabel! 13 | override func awakeFromNib() { 14 | super.awakeFromNib() 15 | // Initialization code 16 | } 17 | 18 | override func setSelected(_ selected: Bool, animated: Bool) { 19 | super.setSelected(selected, animated: animated) 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /ZHFToolBox/TopTopTranslucentTableView/NormalCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /ZHFToolBox/TopTopTranslucentTableView/TopTranslucentTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TopTranslucentTableView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by IOSZHF on 2022/5/19. 6 | // Copyright © 2022 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TopTranslucentTableView: UIView { 12 | lazy var messageData :[String] = [String]() 13 | lazy var tableView : UITableView = { 14 | let tableView = UITableView.init(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300), style: .plain) 15 | // tableView.register(NormalCell.self, forCellReuseIdentifier: "normalcell") 16 | tableView.register(UINib.init(nibName: "NormalCell", bundle: Bundle.main), forCellReuseIdentifier: "NormalCellID") 17 | tableView.delegate = self 18 | tableView.dataSource = self 19 | tableView.backgroundColor = .clear 20 | tableView.separatorStyle = .none 21 | return tableView 22 | }() 23 | //初始化视图 24 | func initTopTranslucentTableView() -> UIView { 25 | self.backgroundColor = .clear 26 | // 渐变蒙层 27 | let layer :CAGradientLayer = CAGradientLayer.init() 28 | layer.colors = [ 29 | UIColor.init(white: 0, alpha: 0.05).cgColor, 30 | UIColor.init(white: 0, alpha: 1.0).cgColor 31 | ]; 32 | layer.locations = [0, 0.15]; // 设置颜色的范围 33 | layer.startPoint = CGPoint.init(x: 0, y: 0) // 设置颜色渐变的起点 34 | layer.endPoint = CGPoint.init(x: 0, y: 1) // 设置颜色渐变的终点,与 startPoint 形成一个颜色渐变方向 35 | layer.frame = CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300); // 设置 Frame 36 | self.layer.mask = layer; // 设置 mask 属性 37 | self.addSubview(self.tableView) 38 | return self 39 | } 40 | func addMessageData(number:NSInteger) { 41 | self.messageData.append("添加第\(number)条消息") 42 | self.tableView.insertRows(at: [IndexPath(row: self.messageData.count-1, section: 0)], with: .none) 43 | self.tableView.scrollToRow(at: IndexPath(row: self.messageData.count-1, section: 0), at: .bottom, animated: true)//滚到底部 44 | } 45 | } 46 | extension TopTranslucentTableView: UITableViewDelegate,UITableViewDataSource{ 47 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 48 | return self.messageData.count 49 | } 50 | 51 | func numberOfSections(in tableView: UITableView) -> Int { 52 | return 1 53 | } 54 | 55 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 56 | return 0.1 57 | } 58 | 59 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 60 | let cell = tableView.dequeueReusableCell(withIdentifier: "NormalCellID", for: indexPath) as! NormalCell 61 | cell.backgroundColor = .clear 62 | cell.messageLabel.text = self.messageData[indexPath.row] 63 | cell.selectionStyle = UITableViewCell.SelectionStyle.none 64 | return cell 65 | } 66 | 67 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 68 | return 40 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ZHFToolBox/TwoVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TwoVC.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/10. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TwoVC: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.view.backgroundColor = ZHFColor.green 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /ZHFToolBox/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | import UIKit 14 | //设备物理尺寸 15 | let ScreenHeight = UIScreen.main.bounds.size.height 16 | let ScreenWidth = UIScreen.main.bounds.size.width 17 | class ViewController: UIViewController { 18 | var tableView:UITableView! 19 | lazy var dataMarr:NSMutableArray = NSMutableArray() 20 | var popImageView: PopImageView = PopImageView() 21 | var popTextView: PopTextView = PopTextView() 22 | var popRadioButtonView: PopRadioButtonView = PopRadioButtonView() 23 | var popCheckboxButtonView: PopCheckboxButtonView = PopCheckboxButtonView() 24 | var popTopOrBottomOutView: PopTopOrBottomOutView = PopTopOrBottomOutView() 25 | var popSomeColorView: PopSomeColorView = PopSomeColorView() 26 | var slideWhiteViewSubView: SlideWhiteViewSubView = SlideWhiteViewSubView() 27 | //拆开一个盒子的动画效果 28 | var popAwayOpenView : PopAwayOpenBackGroundView = PopAwayOpenBackGroundView() //gif背景图 29 | var openBoxView : OpenBoxView! //盒子打开动画效果图 30 | var calendarView: CalendarView = CalendarView() 31 | var progressBar: PopProgressBar! //进度条 32 | var displayLink: CADisplayLink! //定时器 33 | var currentValue: CGFloat = 0; 34 | 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | self.title = "自定义几种提示框" 38 | self.addTableView() 39 | self.dataMarr = ["一个按钮,无点击事件", 40 | "一个按钮,有点击事件", 41 | "两个按钮,有点击事件", 42 | "提示框由小变大弹出(带图片)", 43 | "提示框由小变大弹出(带输入框)", 44 | "提示框由小变大弹出(单选按钮)", 45 | "提示框由小变大弹出(多选按钮)", 46 | "商品弹出盒子的效果", 47 | "商品落入盒子的效果", 48 | "有序弹出一堆框", 49 | "弹出一个带列表的左滑框", 50 | "弹出一个带列表的右滑框", 51 | "弹出一个带有gif背景图的拆产品", 52 | "模拟进度条", 53 | "单选病情", 54 | "弹出日历", 55 | "直播第一条消息半透明"] 56 | } 57 | func addTableView(){ 58 | tableView = UITableView.init(frame: CGRect.init(x: 0, y: 44, width: ScreenWidth, height: ScreenHeight - 44), style: .plain) 59 | self.view.addSubview(tableView) 60 | tableView.backgroundColor = ZHFColor.zhff9_backGroundColor 61 | tableView.separatorColor = ZHFColor.initString(hex: "cccccc") 62 | tableView.separatorInset = UIEdgeInsets.init(top: 0, left: 25, bottom: 0, right: 0) 63 | tableView.delegate = self 64 | tableView.dataSource = self 65 | } 66 | } 67 | extension ViewController :UITableViewDataSource,UITableViewDelegate 68 | { 69 | func numberOfSections(in tableView: UITableView) -> Int { 70 | return 1 71 | } 72 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 73 | return self.dataMarr.count 74 | } 75 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 76 | let alertCellIdentifier = "alertCellIdentifier" 77 | var cell = tableView.dequeueReusableCell(withIdentifier: alertCellIdentifier) 78 | if cell == nil { 79 | cell = UITableViewCell(style:.default, reuseIdentifier: alertCellIdentifier) 80 | } 81 | cell?.textLabel?.text = self.dataMarr[indexPath.row] as? String 82 | cell?.textLabel?.font = UIFont.systemFont(ofSize: 13) 83 | cell?.textLabel?.textColor = ZHFColor.zhf_randomColor() 84 | cell?.selectionStyle = .none 85 | return cell! 86 | } 87 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 88 | let message = self.dataMarr[indexPath.row] as! String 89 | if indexPath.row == 0 { 90 | // 一个按钮,无点击事件 91 | ZHFAlertControllerTool.showAlert(currentVC: self, title: "", meg: message, cancelBtn: "确定") 92 | } 93 | else if indexPath.row == 1 { 94 | // 一个按钮,有点击事件 95 | ZHFAlertControllerTool.showAlert(currentVC: self, title: "提示", meg: message, okBtn: "点击跳页", handler: { (_) in 96 | let oneVC: OneVC = OneVC() 97 | self.navigationController?.pushViewController(oneVC, animated: true) 98 | }) 99 | } 100 | else if indexPath.row == 2 { 101 | //两个按钮,有点击事件 102 | ZHFAlertControllerTool.showAlert(currentVC: self, title: "最美提示", meg: message, oneBtn: "跳页", otherBtn: "取消", oneHandler: { (_) in 103 | self.oneBtnClick(btn: UIButton()) 104 | }, otherHandler: { (_) in 105 | //取消按钮要处理事件 106 | }) 107 | } 108 | else if indexPath.row == 3 { 109 | //带图片的弹框 110 | self.popImageView.addAnimate() 111 | self.popImageView.oneBtn.addTarget(self, action: #selector(self.oneBtnClick), for: .touchUpInside) 112 | self.popImageView.otherBtn.addTarget(self, action: #selector(self.otherBtnClick), for: .touchUpInside) 113 | } 114 | else if indexPath.row == 4{ 115 | //带输入框的弹框 116 | self.popTextView.whiteViewEndFrame = CGRect.init(x: 20, y: 100, width: ScreenWidth - 40, height: ScreenHeight - 300) 117 | self.popTextView.addAnimate() 118 | self.popTextView.textStr = message 119 | self.popTextView.oneBtn.addTarget(self, action: #selector(self.oneBtn4Click), for: .touchUpInside) 120 | self.popTextView.otherBtn.addTarget(self, action: #selector(self.otherBtn4Click), for: .touchUpInside) 121 | } 122 | else if indexPath.row == 5{ 123 | //单选框的弹框 124 | self.popRadioButtonView.whiteViewEndFrame = CGRect.init(x: 20, y: 100, width: ScreenWidth - 40, height: ScreenHeight - 300) 125 | self.popRadioButtonView.contentArr = ["小炒肉","宫爆鸡丁","炒肉","油麦菜","大白菜","蚂蚁上树","西红柿炒鸡蛋","鱼香肉丝","糖醋排骨"] 126 | self.popRadioButtonView.addAnimate() 127 | self.popRadioButtonView.delegate = self 128 | } 129 | else if indexPath.row == 6{ 130 | //多选框的弹框 131 | self.popCheckboxButtonView.whiteViewEndFrame = CGRect.init(x: 20, y: 100, width: ScreenWidth - 40, height: ScreenHeight - 300) 132 | self.popCheckboxButtonView.contentArr = ["小炒肉","宫爆鸡丁","炒肉","油麦菜","大白菜","蚂蚁上树","西红柿炒鸡蛋","鱼香肉丝","糖醋排骨"] 133 | self.popCheckboxButtonView.addAnimate() 134 | self.popCheckboxButtonView.delegate = self 135 | } 136 | else if indexPath.row == 7{ 137 | //从下向上 138 | self.popTopOrBottomOutView.topOrBottomViewStartFrame = CGRect.init(x: 25, y: ScreenHeight, width: ScreenWidth - 50, height: 500) 139 | self.popTopOrBottomOutView.addAnimateFromBottom() 140 | } 141 | else if indexPath.row == 8{ 142 | //从上向下 143 | self.popTopOrBottomOutView.topOrBottomViewStartFrame = CGRect.init(x: 25, y: -ScreenHeight, width: ScreenWidth - 50, height: 500) 144 | self.popTopOrBottomOutView.addAnimateFromTop() 145 | } 146 | else if indexPath.row == 9{ 147 | //有序弹出一堆框 148 | self.popSomeColorView.addAnimate() 149 | self.popSomeColorView.delegate = self; 150 | //实现回调,获取回调回来的值 (闭包) 151 | self.popSomeColorView.backClosure = { 152 | (backStr: String) -> Void in 153 | let redVC: RedVC = RedVC() 154 | redVC.message = backStr 155 | self.navigationController?.pushViewController(redVC, animated: true) 156 | } 157 | } 158 | else if indexPath.row == 10{ 159 | //弹出一个带列表的左滑框 160 | slideWhiteViewSubView.isfromLeft = true //从左边滑出 161 | let whiteViewWidth = ScreenWidth*3/4 162 | slideWhiteViewSubView.whiteViewStartFrame = CGRect.init(x: -whiteViewWidth, y: 0, width: whiteViewWidth, height: ScreenHeight) 163 | slideWhiteViewSubView.whiteViewEndFrame = CGRect.init(x: 0, y: 0, width: whiteViewWidth, height: ScreenHeight) 164 | slideWhiteViewSubView.addAnimate() 165 | slideWhiteViewSubView.delegate = self 166 | } 167 | else if indexPath.row == 11{ 168 | //弹出一个带列表的右滑框 169 | slideWhiteViewSubView.isfromLeft = false //从右边滑出 170 | let whiteViewWidth = ScreenWidth*4/5 171 | let whiteViewHeight = ScreenHeight*8/9 172 | slideWhiteViewSubView.whiteViewStartFrame = CGRect.init(x: ScreenWidth, y:(ScreenHeight - whiteViewHeight)/2, width: whiteViewWidth, height: whiteViewHeight) 173 | slideWhiteViewSubView.whiteViewEndFrame = CGRect.init(x: ScreenWidth - whiteViewWidth, y: (ScreenHeight - whiteViewHeight)/2, width: whiteViewWidth, height: whiteViewHeight) 174 | slideWhiteViewSubView.addAnimate() 175 | slideWhiteViewSubView.delegate = self 176 | } 177 | else if indexPath.row == 12{ 178 | //播放gif图 179 | self.popAwayOpenView.addAnimate() 180 | //当播放GIF图一半时,弹出加载的产品图 1.5 为GIF播放一半所用的时间 181 | if #available(iOS 10.0, *) { 182 | Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false, block: { (_) in 183 | self.popGood() 184 | }) 185 | } else { 186 | sleep(UInt32(1.5)) 187 | self.popGood() 188 | } 189 | } 190 | else if indexPath.row == 13{ 191 | //弹出一个模拟渐变进度条 192 | currentValue = 0 193 | progressBar = PopProgressBar() 194 | progressBar.addAnimate(view: progressBar.initPopBackGroundView()) 195 | displayLink = CADisplayLink.init(target: self, selector: #selector(displayLinkRun)) 196 | displayLink.add(to: RunLoop.current, forMode: .default) 197 | progressBar.displayLink = displayLink 198 | } 199 | else if indexPath.row == 14{ 200 | let arr = ["心率失常","一度房室传导阻滞","心率失常","一度房室传导阻滞","心率失常","一度房室传导阻滞","心率失常","一度房室传导阻滞","心率失常","心率失常","一度房室传导阻滞","心率失常","心率失常","心率失常","一度房室传导阻滞","心率失常","一度房室传导阻滞","心率失常","一度房室传导阻滞","心率失常","一度房室传导阻滞","心率失常","心率失常","一度房室传导阻滞","心率失常","心率失常"] 201 | let popDiseaseView: PopDiseaseView = PopDiseaseView() 202 | popDiseaseView.addWhiteViewContent(arr: arr as NSArray) 203 | popDiseaseView.addAnimate(view: popDiseaseView.initPopDiseaseView()) 204 | popDiseaseView.clickValueClosure { (text) in 205 | ZHFLog(message: text) 206 | } 207 | } 208 | else if indexPath.row == 15{ 209 | let calendarView: ZHFCalendarView = ZHFCalendarView() 210 | calendarView.pointColor = ZHFColor.zhf_color(withHex: 0x42D2BE)//大小点颜色 211 | // calendarView.bigGreenPoints = [0] //大点数组 212 | // calendarView.smallGreenPoints = [0] //小点数组 213 | calendarView.addAnimate() 214 | //点击的是--年--月--日 215 | calendarView.clickValueClosure { (text) in 216 | let arr = text!.components(separatedBy:"-") 217 | ZHFLog(message: "\(arr[0]).\(arr[1]).\(arr[2])") 218 | 219 | } 220 | } 221 | else if indexPath.row == 16{ 222 | self.navigationController?.pushViewController(MessgeShowVC.init(), animated: true) 223 | } 224 | } 225 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 226 | return 40 227 | } 228 | @objc func displayLinkRun(){ 229 | if currentValue > 1 { 230 | //加载完成 关闭定时器,隐藏进度条 231 | displayLink.invalidate() 232 | displayLink = nil 233 | progressBar.removeFromSuperview() 234 | } 235 | else{ 236 | currentValue = currentValue + 0.005; 237 | progressBar.passValue(currentValue: currentValue, allValue: 1.0) 238 | } 239 | } 240 | } 241 | extension ViewController{ 242 | @objc func oneBtnClick(btn:UIButton){ 243 | //先移除弹出来的图 244 | self.popImageView.removeFromSuperview() 245 | let oneVC: OneVC = OneVC() 246 | self.navigationController?.pushViewController(oneVC, animated: true) 247 | } 248 | @objc func otherBtnClick(btn:UIButton){ 249 | //先移除弹出来的图 250 | self.popImageView.removeFromSuperview() 251 | let twoVC: TwoVC = TwoVC() 252 | self.navigationController?.pushViewController(twoVC, animated: true) 253 | } 254 | @objc func oneBtn4Click(btn:UIButton){ 255 | self.dataMarr.replaceObject(at: 4, with: self.popTextView.textView.text as Any) 256 | self.popTextView.tapBtnAndcancelBtnClick() 257 | let indexPath: IndexPath = NSIndexPath.init(row: 4, section: 0) as IndexPath 258 | tableView.reloadRows(at: [indexPath], with: .none) 259 | } 260 | @objc func otherBtn4Click(btn:UIButton){ 261 | self.popTextView.tapBtnAndcancelBtnClick() 262 | } 263 | //弹出加载的产品图 264 | @objc func popGood(){ 265 | self.openBoxView = OpenBoxView() 266 | self.openBoxView.backgroundColor1 = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0) 267 | self.popAwayOpenView.addSubview(self.openBoxView.initPopBackGroundView()) 268 | self.openBoxView.addAnimate() 269 | } 270 | } 271 | extension ViewController:PopRadioButtonViewDelegate,PopCheckboxButtonViewDelegate,PopSomeColorViewDelegate,SlideWhiteViewSubViewDelegate{ 272 | //PopRadioButtonViewDelegate 273 | func selectBtnMessage(content: String) { 274 | self.dataMarr.replaceObject(at: 5, with: content) 275 | self.popRadioButtonView.tapBtnAndcancelBtnClick() 276 | let indexPath: IndexPath = NSIndexPath.init(row: 5, section: 0) as IndexPath 277 | tableView.reloadRows(at: [indexPath], with: .none) 278 | } 279 | //PopCheckboxButtonViewDelegate 280 | func selectMessage(contentMarr: NSMutableArray) { 281 | var content :String = "" 282 | for i in 0 ..< contentMarr.count { 283 | content.append(" \(contentMarr[i] as! String)") 284 | } 285 | self.dataMarr.replaceObject(at: 6, with: content) 286 | self.popCheckboxButtonView.tapBtnAndcancelBtnClick() 287 | let indexPath: IndexPath = NSIndexPath.init(row: 6, section: 0) as IndexPath 288 | tableView.reloadRows(at: [indexPath], with: .none) 289 | } 290 | //PopSomeColorViewDelegate 291 | func selectBtnTag(btnTag:NSInteger) { 292 | self.dataMarr.replaceObject(at: 9, with: "选中按钮的tag为\(btnTag)") 293 | let indexPath: IndexPath = NSIndexPath.init(row: 9, section: 0) as IndexPath 294 | tableView.reloadRows(at: [indexPath], with: .none) 295 | } 296 | //SlideWhiteViewSubViewDelegate 297 | func selectMessage(message: String) { 298 | let redVC: RedVC = RedVC() 299 | redVC.message = message 300 | self.navigationController?.pushViewController(redVC, animated: true) 301 | } 302 | } 303 | 304 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/CalendarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CalendarView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2019/2/21. 6 | // Copyright © 2019年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CalendarView: UpDownView, TBCalendarDataDelegate , TBCalendarDataSource { 12 | 13 | lazy var calender: TBCalendar = self.getCalendar() 14 | lazy var style: TBCalendarAppearStyle = self.getStyle() 15 | var titleLabel: UILabel! 16 | override func addAnimate() { 17 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 18 | self.isHidden = false 19 | //按钮不要在动画完成后初始化(否则按钮没点击效果) 20 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 21 | self.WhiteView.frame = self.whiteViewEndFrame 22 | }) { (_) in 23 | self.addWhiteVieSubView() 24 | } 25 | } 26 | //放一张展示图片 27 | func addWhiteVieSubView(){ 28 | self.WhiteView.addSubview(calender) 29 | } 30 | func getCalendar() -> TBCalendar { 31 | NotificationCenter.default.addObserver(self, selector: #selector(changeDate(noty:)), name: NSNotification.Name(rawValue: CHANGE_SELECT_DATE), object: nil) 32 | let calendar = TBCalendar.init(style: self.style, frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: 350)) 33 | calendar.dataSource = self; 34 | calendar.delegate = self; 35 | return calendar 36 | } 37 | func getStyle() -> TBCalendarAppearStyle { 38 | let style = TBCalendarAppearStyle.init() 39 | style.isNeedCustomHeihgt = true; 40 | return style 41 | } 42 | } 43 | extension CalendarView{ 44 | func calender(calender: TBCalendar, layoutCallBackHeight: CGFloat) { 45 | self.calender.frame = CGRect.init(x: 0, y: 64, width: self.frame.width, height: layoutCallBackHeight) 46 | } 47 | @objc func changeDate(noty: Notification){ 48 | let date: NSDate = noty.object as! NSDate 49 | let endDate = getMonthEnd(date: date) 50 | ZHFLog(message: endDate) 51 | let formatter = DateFormatter.init() 52 | formatter.dateFormat = "dd" 53 | let formatter1 = DateFormatter.init() 54 | formatter1.dateFormat = "yyyy-MM" 55 | let nowDate = formatter1.string(from: Date()) 56 | let changeDate = formatter1.string(from: date as Date) 57 | let str = formatter.string(from: endDate as Date) 58 | let count = Int(str)! 59 | let nowDay = Int(formatter.string(from: date as Date))! 60 | var dotViews = [UIView]() 61 | /* 62 | 原则上来说 这个地方是需要在viewDidLoad中直接设置self.calender.setDataArr(arr: dotViews) 63 | 这个dotView中可以放任何对象,在实际开发中可以根据后台返回的数据进行赋值,比如钉钉今日的签到情况, 64 | 可以放在一个模型中记录,然后放到该集合中,然后到TBCalender.swift中 65 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 66 | 方法304行,集合>0的判断中进行自己逻辑的书写,此处的创建只是为了效果 67 | */ 68 | for i in 0.. Bool { 15 | let count = mobile.count 16 | if count != 11 17 | { 18 | return false 19 | }else{ 20 | return true 21 | // let CM_NUM :NSString = "^((13[4-9])|(147)|(15[0-2,7-9])|(178)|(18[2-4,7-8]))\\d{8}|(1705)\\d{7}$"; 22 | // let CU_NUM :NSString = "^((13[0-2])|(145)|(15[5-6])|(176)|(18[5,6]))\\d{8}|(1709)\\d{7}$"; 23 | // let CT_NUM :NSString = "^((133)|(153)|(177)|(173)|(18[0,1,9]))\\d{8}$"; 24 | // let pred1: NSPredicate = NSPredicate(format: "SELF MATCHES %@", CM_NUM) 25 | // let isMatch1 :Bool = pred1.evaluate(with: mobile) 26 | // let pred2: NSPredicate = NSPredicate(format: "SELF MATCHES %@", CU_NUM) 27 | // let isMatch2 :Bool = pred2.evaluate(with: mobile) 28 | // let pred3: NSPredicate = NSPredicate(format: "SELF MATCHES %@", CT_NUM) 29 | // let isMatch3 :Bool = pred3.evaluate(with: mobile) 30 | // if (isMatch1 || isMatch2 || isMatch3) { 31 | // return true 32 | // }else{ 33 | // return false 34 | // } 35 | } 36 | } 37 | // 获取当前时间字符串 当天传入0, 前一天传1, 后一天传-1,以此类推 38 | class func initNowDateStr(number:NSInteger) -> String{ 39 | let date = Date.init(timeInterval: TimeInterval(-24*60*60*number), since: Date()) 40 | //输出格式 41 | let dformatter = DateFormatter.init() 42 | dformatter.dateFormat = "MM月dd日" 43 | let time = dformatter.string(from: date) 44 | return time 45 | } 46 | // 获取当前时间字符串 当天传入0, 前一天传1, 后一天传-1,以此类推 47 | class func initNowMonthStr(number:NSInteger) -> String{ 48 | let date = Date.init(timeInterval: TimeInterval(-24*60*60*number), since: Date()) 49 | //输出格式 50 | let dformatter = DateFormatter.init() 51 | dformatter.dateFormat = "yyyy年MM月" 52 | let time = dformatter.string(from: date) 53 | return time 54 | } 55 | //把当前时间时间转换成10位时间戳 56 | class func initNowDate() -> String{ 57 | let timeInterval = NSDate().timeIntervalSince1970 * 1000 58 | return (String(timeInterval) as NSString).substring(to: 10) 59 | } 60 | //时间戳转时间 61 | class func initTime(timeStamp:NSInteger) -> String{ 62 | let timeInterval:TimeInterval = TimeInterval(timeStamp) 63 | let date = Date.init(timeIntervalSince1970: timeInterval) 64 | //输出格式 65 | let dformatter = DateFormatter.init() 66 | dformatter.dateFormat = "yyyy\\MM\\dd" 67 | let time = dformatter.string(from: date) 68 | return time 69 | } 70 | //判断是否是邮箱 71 | class func initmailBox(email: String) -> Bool { 72 | let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" 73 | let emailTest:NSPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex) 74 | return emailTest.evaluate(with: email) 75 | } 76 | } 77 | extension NSString{ 78 | //2.Md5 字典加密 79 | class func initMd5(Arr: [String]) -> [String : AnyObject] { 80 | var string :String = "Surprisebox123" 81 | for str1 in Arr { 82 | let strArr = str1.components(separatedBy: "=") 83 | string.append("\(strArr[0])\(strArr[1])") 84 | } 85 | let str = string.cString(using: String.Encoding.utf8) 86 | let strLen = CUnsignedInt(string.lengthOfBytes(using: String.Encoding.utf8)) 87 | let digestLen = Int(CC_MD5_DIGEST_LENGTH) 88 | let result = UnsafeMutablePointer.allocate(capacity: digestLen) 89 | CC_MD5(str!, strLen, result) 90 | let hash = NSMutableString() 91 | for i in 0 ..< digestLen { 92 | hash.appendFormat("%02x", result[i]) 93 | } 94 | result.deallocate() 95 | let strMd5 = String(format: hash as String).uppercased() 96 | let parameters :NSMutableDictionary = ["sign":strMd5] 97 | for i in 0 ..< Arr.count { 98 | let str = Arr[i] 99 | let strArray = str.components(separatedBy: "=") 100 | parameters.setObject( strArray[1], forKey: strArray[0] as NSCopying) 101 | } 102 | return parameters as! [String : AnyObject] 103 | } 104 | //2.Md5 字符串加密 105 | class func initMd5Str(string: String) -> String { 106 | let string1 :String = "Surprisebox123\(string)" 107 | let str = string1.cString(using: String.Encoding.utf8) 108 | let strLen = CUnsignedInt(string1.lengthOfBytes(using: String.Encoding.utf8)) 109 | let digestLen = Int(CC_MD5_DIGEST_LENGTH) 110 | let result = UnsafeMutablePointer.allocate(capacity: digestLen) 111 | CC_MD5(str!, strLen, result) 112 | let hash = NSMutableString() 113 | for i in 0 ..< digestLen { 114 | hash.appendFormat("%02x", result[i]) 115 | } 116 | result.deallocate() 117 | let strMd5 = String(format: hash as String).uppercased() 118 | return strMd5 119 | } 120 | } 121 | extension NSString{ 122 | //字典转字符串 123 | class func initGetJsonString(dic: NSDictionary) -> String{ 124 | if (!JSONSerialization.isValidJSONObject(dic)) { 125 | // "无法解析" 126 | return "" 127 | } 128 | let data :NSData! = try? JSONSerialization.data(withJSONObject: dic, options: []) as NSData 129 | let jsonString = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue) 130 | return jsonString! as String 131 | } 132 | //字符串转字典 133 | class func getDictionaryFromJSONString(jsonString:String) ->NSDictionary{ 134 | 135 | let jsonData:Data = jsonString.data(using: .utf8)! 136 | 137 | let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) 138 | if dict != nil { 139 | return dict as! NSDictionary 140 | } 141 | return NSDictionary() 142 | } 143 | } 144 | extension NSString{ 145 | var removeAllSapce: String { 146 | if self.length != 11{ 147 | //过滤手机号中的 " " 和 "-" 和不是数字的东西 148 | return self.replacingOccurrences(of: "[^0-9]", with: "", options: NSString.CompareOptions.regularExpression, range: NSRange.init(location: 0, length: self.length)) 149 | } 150 | else{ 151 | return self as String 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopCheckboxButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopCheckboxButtonView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/10. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*弹出一个多选框*/ 14 | import UIKit 15 | protocol PopCheckboxButtonViewDelegate { 16 | func selectMessage(contentMarr: NSMutableArray) 17 | } 18 | class PopCheckboxButtonView: PopSmallChangeBigFatherView { 19 | var delegate:PopCheckboxButtonViewDelegate? 20 | let titleHeight: CGFloat = 75 21 | var contentArr : [String] = [String]() 22 | lazy var contentMarr: NSMutableArray = NSMutableArray() 23 | var trueBtn:UIButton = UIButton() 24 | override func addAnimate() { 25 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 26 | self.isHidden = false 27 | 28 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 29 | self.WhiteView.frame = self.whiteViewEndFrame 30 | }) { (_) in 31 | self.cancelBtn.frame.origin.y = self.WhiteView.frame.maxY + 20 32 | self.cancelBtn.isHidden = false 33 | self.addWhiteVieSubView1() 34 | } 35 | } 36 | //放一张展示图片 37 | func addWhiteVieSubView1(){ 38 | let titleLabel:UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: self.WhiteView.frame.width, height: titleHeight)) 39 | titleLabel.text = "请选择多个菜" 40 | titleLabel.textAlignment = NSTextAlignment.center 41 | titleLabel.font = UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.bold) 42 | titleLabel.textColor = ZHFColor.zhf_randomColor() 43 | self.WhiteView.addSubview(titleLabel) 44 | //添加按钮 45 | var x: CGFloat = 25 46 | var y: CGFloat = titleHeight 47 | for i in 0 ..< contentArr.count{ 48 | let name: String = contentArr[i] 49 | let nameLenth : CGFloat = CGFloat(name.count * 25) 50 | let btn : UIButton = UIButton.init(type: .custom) 51 | if x + nameLenth > ScreenWidth - 50{ 52 | x = 25 53 | y = y + 40 54 | } 55 | btn.frame = CGRect.init(x: x, y: y - 10, width: nameLenth, height: 30) 56 | btn.layer.masksToBounds = true 57 | btn.layer.cornerRadius = 15 58 | btn.layer.borderColor = ZHFColor.zhf88_contentTextColor.cgColor 59 | btn.layer.borderWidth = 0.5 60 | btn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: UIFont.Weight.ultraLight) 61 | btn.setTitle(name, for: .normal) 62 | btn.setTitleColor(ZHFColor.zhf88_contentTextColor, for: .normal) 63 | btn.setTitle(name, for: .selected) 64 | btn.setTitleColor(ZHFColor.zhf_selectColor, for: .selected) 65 | x = x + nameLenth + 15 66 | btn.tag = i 67 | btn.isSelected = false 68 | btn.addTarget(self, action: #selector(btnClick), for: .touchUpInside) 69 | self.WhiteView.addSubview(btn) 70 | } 71 | trueBtn = UIButton.init(type: .custom) 72 | trueBtn.frame = CGRect.init(x:25, y: self.WhiteView.frame.height - 55, width: self.WhiteView.frame.width - 50, height: 40) 73 | trueBtn.layer.masksToBounds = true 74 | trueBtn.layer.cornerRadius = 5 75 | trueBtn.backgroundColor = ZHFColor.orange 76 | trueBtn.setTitle("确定", for: .normal) 77 | trueBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 78 | trueBtn.setTitleColor(UIColor.white, for: .normal) 79 | trueBtn.addTarget(self, action: #selector(trueBtnClick), for: .touchUpInside) 80 | self.WhiteView.addSubview(trueBtn) 81 | } 82 | @objc func btnClick(btn:UIButton){ 83 | btn.isSelected = !btn.isSelected 84 | if btn.isSelected == true { 85 | btn.layer.borderColor = ZHFColor.zhf_selectColor.cgColor 86 | contentMarr.add((btn.titleLabel?.text)!) 87 | } 88 | else{ 89 | btn.layer.borderColor = ZHFColor.zhf88_contentTextColor.cgColor 90 | contentMarr.remove((btn.titleLabel?.text)!) 91 | } 92 | } 93 | @objc func trueBtnClick(btn:UIButton){ 94 | self.delegate?.selectMessage(contentMarr: (contentMarr)) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopDiseaseView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopDiseaseView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2019/3/13. 6 | // Copyright © 2019年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PopDiseaseView: UIView { 12 | //声明闭包 13 | typealias clickBtnClosure = (String?) -> Void 14 | //把申明的闭包设置成属性 15 | var clickClosure: clickBtnClosure? 16 | //为闭包设置调用函数 17 | func clickValueClosure(closure:clickBtnClosure?){ 18 | clickClosure = closure 19 | } 20 | //背景区域的颜色和透明度 21 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 22 | var radioBtn: UIButton! 23 | var okBtn: UIButton! 24 | //初始化视图 25 | func initPopDiseaseView() -> PopDiseaseView { 26 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 27 | self.backgroundColor = backgroundColor1 28 | return self 29 | } 30 | //弹出View 31 | func addAnimate(view:PopDiseaseView) { 32 | UIApplication.shared.keyWindow?.addSubview(view) 33 | } 34 | func addWhiteViewContent(arr: NSArray) { 35 | let whiteView:UIView = UIView() 36 | whiteView.backgroundColor = UIColor.white 37 | 38 | whiteView.frame = CGRect.init(x: 0, y: ScreenHeight - ScreenHeight*2/3, width: ScreenWidth, height: ScreenHeight*2/3) 39 | self.addSubview(whiteView) 40 | let scrollView: UIScrollView = UIScrollView.init(frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight*2/3 - 100)) 41 | scrollView.contentSize = CGSize.init(width: 0, height: CGFloat(arr.count+2)/3 * 50) 42 | scrollView.showsVerticalScrollIndicator = false 43 | whiteView.addSubview(scrollView) 44 | for i in 0 ..< arr.count { 45 | let name: String = arr[i] as! String 46 | let btn: UIButton = UIButton.init(type: .custom) 47 | let btnW: CGFloat = (ScreenWidth - 40)/3 48 | btn.frame = CGRect.init(x: 10 + CGFloat(i%3) * (btnW + 10), y: 15 + CGFloat(i/3 * 50), width: btnW, height: 44) 49 | btn.setTitle(name, for: .normal) 50 | btn.setTitleColor(ZHFColor.zhf33_titleTextColor, for: .normal) 51 | btn.layer.masksToBounds = true 52 | btn.layer.cornerRadius = 10 53 | btn.layer.borderWidth = 1 54 | btn.layer.borderColor = ZHFColor.zhf_lineColor.cgColor 55 | btn.titleLabel?.font = UIFont.systemFont(ofSize: 12) 56 | btn.addTarget(self, action: #selector(btnClick), for: .touchUpInside) 57 | scrollView.addSubview(btn) 58 | } 59 | 60 | let lineView: UIView = UIView() 61 | lineView.frame = CGRect.init(x: 0, y: scrollView.frame.maxY + 20, width: ScreenWidth, height: 1) 62 | lineView.backgroundColor = ZHFColor.zhfcc_lineColor 63 | whiteView.addSubview(lineView) 64 | let cancelBtn: UIButton = UIButton.init(type: .custom) 65 | cancelBtn.frame = CGRect.init(x: 25, y: lineView.frame.maxY + 10, width: ScreenWidth/2 - 37.5, height: 40) 66 | cancelBtn.setTitle("取消", for: .normal) 67 | cancelBtn.backgroundColor = UIColor.red 68 | cancelBtn.setTitleColor(ZHFColor.white, for: .normal) 69 | cancelBtn.layer.masksToBounds = true 70 | cancelBtn.layer.cornerRadius = 20 71 | cancelBtn.addTarget(self, action: #selector(tapBtnAndcancelBtnClick), for: .touchUpInside) 72 | whiteView.addSubview(cancelBtn) 73 | okBtn = UIButton.init(type: .custom) 74 | okBtn.frame = CGRect.init(x:ScreenWidth/2 + 12.5, y: lineView.frame.maxY + 10, width: ScreenWidth/2 - 37.5, height: 40) 75 | okBtn.setTitle("确认修改", for: .normal) 76 | okBtn.backgroundColor = UIColor.red 77 | okBtn.setTitleColor(ZHFColor.white, for: .normal) 78 | okBtn.layer.masksToBounds = true 79 | okBtn.isUserInteractionEnabled = false 80 | okBtn.alpha = 0.5 81 | okBtn.layer.cornerRadius = 20 82 | okBtn.addTarget(self, action: #selector(okBtnClick), for: .touchUpInside) 83 | whiteView.addSubview(okBtn) 84 | } 85 | @objc func btnClick(btn:UIButton){ 86 | if radioBtn != nil { 87 | radioBtn.backgroundColor = UIColor.white 88 | radioBtn.setTitleColor(ZHFColor.zhf33_titleTextColor, for: .normal) 89 | } 90 | okBtn.isUserInteractionEnabled = true 91 | okBtn.alpha = 1 92 | btn.backgroundColor = UIColor.red 93 | btn.setTitleColor(UIColor.white, for: .normal) 94 | radioBtn = btn 95 | } 96 | @objc func okBtnClick(btn:UIButton){ 97 | if radioBtn != nil { 98 | if clickClosure != nil{ 99 | clickClosure!(radioBtn.titleLabel!.text) 100 | } 101 | self.removeFromSuperview() 102 | } 103 | } 104 | //移除 105 | @objc func tapBtnAndcancelBtnClick() { 106 | self.removeFromSuperview() 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopGifOpenBox/OpenBoxView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OpenBoxView.swift 3 | // GifImageAndImageChange 4 | // 5 | // Created by 张海峰 on 2018/4/11. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | // 2.Gif播放一半,弹出自定义动画,循环播放Gif任意区间帧动画。 9 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 10 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 11 | https://github.com/FighterLightning/ZHFToolBox.git 12 | https://www.jianshu.com/p/88420bc4d32d 13 | */ 14 | import UIKit 15 | 16 | class OpenBoxView: PopBackGroundView { 17 | let titleHeight: CGFloat = 75 18 | override func addAnimate() { 19 | self.isHidden = false 20 | UIView.animate(withDuration:0.5, animations: { 21 | self.WhiteView.frame = CGRect.init(x: 40, y: 100, width: ScreenWidth - 80, height: ScreenHeight - 230) 22 | }) { (_) in 23 | self.cancelBtn.frame.origin.y = self.WhiteView.frame.maxY + 20 24 | self.cancelBtn.isHidden = false 25 | self.addWhiteViewSubView() 26 | } 27 | } 28 | func addWhiteViewSubView(){ 29 | let shadowpath :UIBezierPath = UIBezierPath.init(rect: self.WhiteView.bounds) 30 | self.WhiteView.layer.shadowColor = UIColor.yellow.cgColor 31 | self.WhiteView.layer.shadowOffset = CGSize.init(width:0, height: 1)//设置阴影的偏移量 32 | self.WhiteView.layer.shadowOpacity = 1 //设置阴影的透明度 33 | self.WhiteView.layer.shadowPath = shadowpath.cgPath 34 | self.WhiteView.layer.shadowRadius = 22 35 | self.WhiteView.layer.masksToBounds = false 36 | let titleLabel: UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: self.WhiteView.frame.width, height: titleHeight)) 37 | titleLabel.text = "恭喜你拆出下列产品" 38 | titleLabel.textAlignment = NSTextAlignment.center 39 | titleLabel.textColor = UIColor.gray 40 | titleLabel.font = UIFont.systemFont(ofSize: 14) 41 | self.WhiteView.addSubview(titleLabel) 42 | let imageView: UIImageView = UIImageView.init(frame: CGRect.init(x: 0, y: titleHeight, width: self.WhiteView.frame.width, height: self.WhiteView.frame.height - titleHeight)) 43 | imageView.image = UIImage.init(named: "test1") 44 | imageView.contentMode = .scaleAspectFill 45 | imageView.clipsToBounds = true 46 | self.WhiteView.addSubview(imageView) 47 | } 48 | override func tapBtnAndcancelBtnClick() { 49 | self.superview?.removeFromSuperview() 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopGifOpenBox/PopAwayOpenBackGroundView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopAwayOpenBackGroundView.swift 3 | // AmazedBox 4 | // 5 | // Created by 张海峰 on 2018/4/10. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 2.Gif播放一半,弹出自定义动画,循环播放Gif任意区间帧动画。 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | import UIKit 14 | import ImageIO 15 | class PopAwayOpenBackGroundView: UIView { 16 | 17 | var topView1 :UIImageView = UIImageView() 18 | lazy var frames: NSMutableArray = NSMutableArray() 19 | lazy var framesLast: NSMutableArray = NSMutableArray() 20 | //初始化视图 21 | func initPopAwayOpenBackGroundView() -> UIView { 22 | self.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0) 23 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 24 | let fileUrl :NSURL = Bundle.main.url(forResource: "open_boxA", withExtension: "gif")! as NSURL //加载GIF图片 25 | let gifSource : CGImageSource = CGImageSourceCreateWithURL(fileUrl, nil)! //将GIF图片转换成对应的图片源 26 | let frameCout : NSInteger = CGImageSourceGetCount(gifSource)//获取其中图片源个数,即由多少帧图片组成 27 | self.frames = NSMutableArray.init()//定义数组存储拆分出来的图片 28 | self.framesLast = NSMutableArray.init()//定义数组存储拆分出来的图片 29 | for i in 0 ..< frameCout{ 30 | let imageRef :CGImage = CGImageSourceCreateImageAtIndex(gifSource, i, nil)!//从GIF图片中取出源图片 31 | let image : UIImage = UIImage.init(cgImage: imageRef) 32 | self.frames.add(image) 33 | if i > frameCout*2/3{ 34 | //截取整个gif图的后面1/3 寸进数组以达到循环播放后半部分 35 | self.framesLast.add(image) 36 | } 37 | } 38 | topView1 = UIImageView.init(frame: CGRect.init(x: ScreenWidth/2 - 10, y: ScreenHeight/2 - 10, width: 20, height: 20)) 39 | topView1.image = self.frames.firstObject as? UIImage 40 | topView1.isUserInteractionEnabled = true 41 | topView1.contentMode = .scaleAspectFill 42 | self.addSubview(topView1) 43 | return self 44 | } 45 | func addAnimate() { 46 | UIApplication.shared.keyWindow?.addSubview(self.initPopAwayOpenBackGroundView()) 47 | UIView.animate(withDuration:0.2, animations: { 48 | self.topView1.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 49 | }) { (_) in 50 | let AnimationNtimer : NSInteger = 3 51 | self.topView1.animationImages = self.frames as? [UIImage]//将图片数组加入UIImageView动画数组中 52 | self.topView1.isUserInteractionEnabled = true 53 | self.topView1.contentMode = .scaleAspectFill 54 | self.topView1.animationDuration = TimeInterval(AnimationNtimer); //每次动画时长 55 | self.topView1.startAnimating() 56 | Timer.scheduledTimer(timeInterval: TimeInterval(AnimationNtimer), target: self, selector: #selector(self.ArrowAnimationPlay), userInfo: nil, repeats: false) 57 | } 58 | } 59 | //播放结束循环播放GIF图的后面1/3部分 60 | @objc func ArrowAnimationPlay(){ 61 | self.topView1.animationImages = self.framesLast as? [UIImage]//将图片数组加入UIImageView动画数组中 62 | self.topView1.animationDuration = 1 63 | self.topView1.startAnimating() 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopGifOpenBox/PopBackGroundView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopBackGroundVIew.swift 3 | // AmazedBox 4 | // 5 | // Created by 张海峰 on 2018/1/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | 14 | import UIKit 15 | class PopBackGroundView: UIView,UIGestureRecognizerDelegate { 16 | var WhiteView: UIView = UIView() 17 | var cancelBtn: UIButton = UIButton() 18 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 19 | //初始化视图 20 | func initPopBackGroundView() -> UIView { 21 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 22 | self.backgroundColor = backgroundColor1 23 | self.isHidden = true 24 | //设置添加地址的View 25 | self.WhiteView.frame = CGRect.init(x: ScreenWidth/2 - 10, y: ScreenHeight/2 - 10, width: 20, height: 20) 26 | WhiteView.backgroundColor = UIColor.white 27 | WhiteView.layer.masksToBounds = true 28 | WhiteView.layer.cornerRadius = 10 29 | self.addSubview(WhiteView) 30 | cancelBtn = UIButton.init(type: .custom) 31 | cancelBtn.frame = CGRect.init(x:ScreenWidth/2 - 20, y: WhiteView.frame.maxY + 20, width: 40, height: 40) 32 | cancelBtn.tag = 1 33 | cancelBtn.setImage(UIImage.init(named: "cancel_white"), for: .normal) 34 | cancelBtn.isHidden = true 35 | cancelBtn.addTarget(self, action: #selector(tapBtnAndcancelBtnClick), for: .touchUpInside) 36 | self.addSubview(cancelBtn) 37 | return self 38 | } 39 | //弹出的动画效果 40 | func addAnimate() { 41 | 42 | } 43 | //收回的动画效果 44 | @objc func tapBtnAndcancelBtnClick() { 45 | UIView.animate(withDuration: 0.2, animations: { 46 | self.cancelBtn.isHidden = true 47 | self.WhiteView.frame = CGRect.init(x: ScreenWidth/2 - 20, y: ScreenHeight/2 - 20, width: 40, height: 40) 48 | self.cancelBtn.frame.origin.y = self.WhiteView.frame.maxY + 20 49 | }) { (_) in 50 | self.isHidden = true 51 | for view in self.WhiteView.subviews{ 52 | view.removeFromSuperview() 53 | } 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopGifOpenBox/open_boxA.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FighterLightning/ZHFAlertView/7d7d19d3872ba337270bb2df0841a78138ad9a9b/ZHFToolBox/ZHFSubToolBox/PopGifOpenBox/open_boxA.gif -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopImageView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*弹出一个带图片的提示框*/ 14 | import UIKit 15 | 16 | class PopImageView: PopSmallChangeBigFatherView { 17 | let titleHeight: CGFloat = 75 18 | var oneBtn:UIButton = UIButton() 19 | var otherBtn:UIButton = UIButton() 20 | override func addAnimate() { 21 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 22 | self.isHidden = false 23 | //按钮不要在动画完成后初始化(否则按钮没点击效果) 24 | oneBtn = UIButton.init(type: .custom) 25 | otherBtn = UIButton.init(type: .custom) 26 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 27 | self.WhiteView.frame = self.whiteViewEndFrame 28 | }) { (_) in 29 | self.cancelBtn.frame.origin.y = self.WhiteView.frame.maxY + 20 30 | self.cancelBtn.isHidden = false 31 | self.addWhiteVieSubView1() 32 | } 33 | } 34 | //放一张展示图片 35 | func addWhiteVieSubView1(){ 36 | let titleLabel:UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: self.WhiteView.frame.width, height: titleHeight)) 37 | titleLabel.text = "带图片的弹框" 38 | titleLabel.textAlignment = NSTextAlignment.center 39 | titleLabel.font = UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.bold) 40 | titleLabel.textColor = ZHFColor.zhf_randomColor() 41 | self.WhiteView.addSubview(titleLabel) 42 | let imageView :UIImageView = UIImageView.init(frame: CGRect.init(x: 20, y: titleHeight, width: self.WhiteView.frame.width - 40, height: self.WhiteView.frame.height - titleHeight - 80)) 43 | imageView.layer.masksToBounds = true 44 | imageView.contentMode = .scaleAspectFill 45 | imageView.image = UIImage.init(named: "test1") 46 | self.WhiteView.addSubview(imageView) 47 | 48 | oneBtn.frame = CGRect.init(x:20, y: self.WhiteView.frame.height - 55, width: (self.WhiteView.frame.width - 50)/2, height: 40) 49 | oneBtn.layer.masksToBounds = true 50 | oneBtn.layer.cornerRadius = 5 51 | oneBtn.backgroundColor = ZHFColor.zhf_selectColor 52 | oneBtn.setTitle("按钮One", for: .normal) 53 | oneBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 54 | oneBtn.setTitleColor(UIColor.white, for: .normal) 55 | self.WhiteView.addSubview(oneBtn) 56 | 57 | otherBtn.frame = CGRect.init(x:oneBtn.frame.maxX + 10, y: self.WhiteView.frame.height - 55, width: (self.WhiteView.frame.width - 50)/2, height: 40) 58 | otherBtn.layer.masksToBounds = true 59 | otherBtn.layer.cornerRadius = 5 60 | otherBtn.backgroundColor = ZHFColor.zhf_selectColor 61 | otherBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 62 | otherBtn.setTitle("按钮Two", for: .normal) 63 | otherBtn.setTitleColor(UIColor.white, for: .normal) 64 | self.WhiteView.addSubview(otherBtn) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopProgressBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopProgressBar.swift 3 | // test 4 | // 5 | // Created by 张海峰 on 2019/3/4. 6 | // Copyright © 2019年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | 渐变进度条:单独简书连接https://www.jianshu.com/p/d985207dac6b 12 | */ 13 | import UIKit 14 | 15 | class PopProgressBar: UIView ,UIGestureRecognizerDelegate { 16 | //背景区域的颜色和透明度 17 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 18 | //进度条view 19 | var progressView: UIView = UIView() 20 | //提示按钮 21 | var hintBtn: UIButton! 22 | var beforeValue :CGFloat = 0 //前一个值 23 | var displayLink: CADisplayLink! //定时器 承接控制器里的定时器,删除view时保证定时器关闭 24 | var path: UIBezierPath! 25 | var progressLayer :CAShapeLayer! 26 | //初始化视图 27 | func initPopBackGroundView() -> PopProgressBar { 28 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 29 | self.backgroundColor = backgroundColor1 30 | let tap:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(tapBtnAndcancelBtnClick)) 31 | tap.delegate = self 32 | self.addGestureRecognizer(tap) 33 | return self 34 | } 35 | //弹出View 36 | func addAnimate(view:PopProgressBar) { 37 | self.addProgressView() 38 | UIApplication.shared.keyWindow?.addSubview(view) 39 | } 40 | //添加进度条 41 | func addProgressView() { 42 | progressView = UIView.init(frame: CGRect.init(x: 25, y: 290, width: ScreenWidth - 50, height: 15)) 43 | progressView.layer.masksToBounds = true 44 | progressView.layer.cornerRadius = 7.5 45 | progressView.backgroundColor = UIColor.white 46 | self.addSubview(progressView) 47 | hintBtn = UIButton.init(type: UIButton.ButtonType.custom) 48 | hintBtn.frame = CGRect.init(x: 8, y: progressView.frame.minY - 30, width: 34, height: 20) 49 | hintBtn.setBackgroundImage(UIImage.init(named: "progressHint"), for: UIControl.State.normal) 50 | hintBtn.setTitle("0.0%", for: UIControl.State.normal) 51 | hintBtn.titleLabel?.font = UIFont.systemFont(ofSize: 8) 52 | hintBtn.setTitleColor(UIColor.white, for: UIControl.State.normal) 53 | self.addSubview(hintBtn) 54 | self.gradentWith(frame: progressView.frame) 55 | } 56 | //为进度条添加遮罩,及layer 57 | @objc func gradentWith(frame:CGRect) { 58 | path = UIBezierPath.init() 59 | path.stroke()//添加遮罩 60 | progressLayer = CAShapeLayer.init() 61 | progressLayer.frame = progressView.bounds 62 | progressLayer.strokeColor = ZHFColor.initString(hex: "0x23D7DE").cgColor 63 | progressLayer.lineCap = CAShapeLayerLineCap.init(rawValue: "kCALineCapRound") 64 | progressLayer.lineWidth = progressView.frame.size.height //渐变图层 65 | let grain:CALayer = CALayer.init() 66 | let gradientLayer: CAGradientLayer = CAGradientLayer.init() 67 | let fixColor: UIColor = ZHFColor.initString(hex: "0x71FFB7") 68 | let preColor: UIColor = ZHFColor.initString(hex: "0x23D7DE") 69 | gradientLayer.frame = CGRect.init(x: 0, y: 0, width: progressView.frame.size.width, height: progressView.frame.size.height) 70 | gradientLayer.colors = [preColor.cgColor,fixColor.cgColor] 71 | // 开始点 72 | gradientLayer.startPoint = CGPoint.init(x: 0, y: 0) 73 | // 结束点 74 | gradientLayer.endPoint = CGPoint.init(x: 1, y: 1) 75 | grain.addSublayer(gradientLayer) 76 | grain.mask = progressLayer 77 | progressView.layer.addSublayer(grain)//增加动画 78 | let pathAnimation : CABasicAnimation = CABasicAnimation.init(keyPath: "strokeEnd") 79 | pathAnimation.duration = 0; 80 | pathAnimation.timingFunction = CAMediaTimingFunction.init(name: .linear) 81 | pathAnimation.fromValue = NSNumber.init(value: 0.0) 82 | pathAnimation.toValue = NSNumber.init(value: 1.0) 83 | pathAnimation.autoreverses = false 84 | pathAnimation.repeatCount = 1 85 | progressLayer.add(pathAnimation, forKey: "strokeEndAnimation") 86 | } 87 | //当前进度 88 | func passValue(currentValue: CGFloat,allValue: CGFloat) { 89 | if currentValue < allValue { 90 | //当前比例 91 | let currentProportion : CGFloat = currentValue/allValue 92 | hintBtn.frame = CGRect.init(x: 8 + currentProportion * progressView.frame.size.width, y: progressView.frame.minY - 30, width: 34, height: 20) 93 | hintBtn.setTitle("\(NSInteger(currentProportion*100))%", for: UIControl.State.normal) 94 | path.move(to: CGPoint.init(x: progressView.frame.size.width * (beforeValue/allValue), y: progressView.frame.size.height/2)) 95 | path.addLine(to: CGPoint.init(x: progressView.frame.size.width * currentProportion, y: progressView.frame.size.height/2)) 96 | progressLayer.path = path.cgPath 97 | } 98 | else{ 99 | //上传/下载成功 隐藏当前状态 100 | self.tapBtnAndcancelBtnClick() 101 | } 102 | beforeValue = currentValue 103 | } 104 | //移除或者中断进度 105 | @objc func tapBtnAndcancelBtnClick() { 106 | self.removeFromSuperview() 107 | displayLink.invalidate() 108 | displayLink = nil 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopRadioButtonView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopButtonView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/10. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*弹出一个单选框*/ 14 | import UIKit 15 | protocol PopRadioButtonViewDelegate { 16 | func selectBtnMessage(content: String) 17 | } 18 | class PopRadioButtonView: PopSmallChangeBigFatherView { 19 | var delegate:PopRadioButtonViewDelegate? 20 | let titleHeight: CGFloat = 75 21 | var contentArr : [String] = [String]() 22 | var radioBtn:UIButton = UIButton() 23 | var trueBtn:UIButton = UIButton() 24 | override func addAnimate() { 25 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 26 | self.isHidden = false 27 | 28 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 29 | self.WhiteView.frame = self.whiteViewEndFrame 30 | }) { (_) in 31 | self.cancelBtn.frame.origin.y = self.WhiteView.frame.maxY + 20 32 | self.cancelBtn.isHidden = false 33 | self.addWhiteVieSubView1() 34 | } 35 | } 36 | //放一张展示图片 37 | func addWhiteVieSubView1(){ 38 | let titleLabel:UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: self.WhiteView.frame.width, height: titleHeight)) 39 | titleLabel.text = "请选择一个菜" 40 | titleLabel.textAlignment = NSTextAlignment.center 41 | titleLabel.font = UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.bold) 42 | titleLabel.textColor = ZHFColor.zhf_randomColor() 43 | self.WhiteView.addSubview(titleLabel) 44 | //添加按钮 45 | var x: CGFloat = 25 46 | var y: CGFloat = titleHeight 47 | for i in 0 ..< contentArr.count{ 48 | let name: String = contentArr[i] 49 | let nameLenth : CGFloat = CGFloat(name.count * 25) 50 | let btn : UIButton = UIButton.init(type: .custom) 51 | if x + nameLenth > ScreenWidth - 50{ 52 | x = 25 53 | y = y + 40 54 | } 55 | btn.frame = CGRect.init(x: x, y: y - 10, width: nameLenth, height: 30) 56 | btn.layer.masksToBounds = true 57 | btn.layer.cornerRadius = 15 58 | btn.layer.borderColor = ZHFColor.zhf88_contentTextColor.cgColor 59 | btn.layer.borderWidth = 0.5 60 | btn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: UIFont.Weight.ultraLight) 61 | btn.setTitle(name, for: .normal) 62 | btn.setTitleColor(ZHFColor.zhf88_contentTextColor, for: .normal) 63 | btn.setTitle(name, for: .selected) 64 | btn.setTitleColor(ZHFColor.zhf_selectColor, for: .selected) 65 | x = x + nameLenth + 15 66 | btn.tag = i 67 | btn.isSelected = false 68 | btn.addTarget(self, action: #selector(btnClick), for: .touchUpInside) 69 | self.WhiteView.addSubview(btn) 70 | } 71 | trueBtn = UIButton.init(type: .custom) 72 | trueBtn.frame = CGRect.init(x:25, y: self.WhiteView.frame.height - 55, width: self.WhiteView.frame.width - 50, height: 40) 73 | trueBtn.layer.masksToBounds = true 74 | trueBtn.layer.cornerRadius = 5 75 | trueBtn.backgroundColor = ZHFColor.orange 76 | trueBtn.setTitle("确定", for: .normal) 77 | trueBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 78 | trueBtn.setTitleColor(UIColor.white, for: .normal) 79 | trueBtn.addTarget(self, action: #selector(trueBtnClick), for: .touchUpInside) 80 | self.WhiteView.addSubview(trueBtn) 81 | } 82 | @objc func btnClick(btn:UIButton){ 83 | radioBtn.isSelected = false 84 | radioBtn.layer.borderColor = ZHFColor.zhf88_contentTextColor.cgColor 85 | btn.layer.borderColor = ZHFColor.zhf_selectColor.cgColor 86 | btn.isSelected = true 87 | radioBtn = btn 88 | } 89 | @objc func trueBtnClick(btn:UIButton){ 90 | self.delegate?.selectBtnMessage(content: (radioBtn.titleLabel?.text)!) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopSmallChangeBigFatherView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FatherView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路,相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 9 | https://github.com/FighterLightning/ZHFToolBox.git 10 | https://www.jianshu.com/p/88420bc4d32d 11 | */ 12 | /*弹框的基础图*/ 13 | import UIKit 14 | class PopSmallChangeBigFatherView: UIView ,UIGestureRecognizerDelegate{ 15 | //白色view用来装一些控件 16 | var WhiteView: UIView = UIView() 17 | var whiteViewStartFrame: CGRect = CGRect.init(x: ScreenWidth/2 - 10, y: ScreenHeight/2 - 10, width: 20, height: 20) 18 | var whiteViewEndFrame: CGRect = CGRect.init(x: 40, y: 100, width: ScreenWidth - 80, height: ScreenHeight - 230) 19 | //取消按钮 20 | var cancelBtn: UIButton = UIButton() 21 | //背景区域的颜色和透明度 22 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 23 | var defaultTime:CGFloat = 0.5 24 | 25 | //初始化视图 26 | func initPopBackGroundView() -> UIView { 27 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 28 | self.backgroundColor = backgroundColor1 29 | self.isHidden = true 30 | //设置添加地址的View 31 | self.WhiteView.frame = whiteViewStartFrame 32 | WhiteView.backgroundColor = UIColor.white 33 | WhiteView.layer.masksToBounds = true 34 | WhiteView.layer.cornerRadius = 10 35 | self.addSubview(WhiteView) 36 | cancelBtn = UIButton.init(type: .custom) 37 | cancelBtn.frame = CGRect.init(x:ScreenWidth/2 - 20, y: WhiteView.frame.maxY + 20, width: 40, height: 40) 38 | cancelBtn.tag = 1 39 | cancelBtn.setImage(UIImage.init(named: "cancel_white"), for: .normal) 40 | cancelBtn.isHidden = true 41 | cancelBtn.addTarget(self, action: #selector(tapBtnAndcancelBtnClick), for: .touchUpInside) 42 | self.addSubview(cancelBtn) 43 | return self 44 | } 45 | //弹出的动画效果 46 | func addAnimate() { 47 | 48 | } 49 | //收回的动画效果 50 | @objc func tapBtnAndcancelBtnClick() { 51 | for view in WhiteView.subviews { 52 | view.removeFromSuperview() 53 | } 54 | UIView.animate(withDuration: TimeInterval(defaultTime), animations: { 55 | self.cancelBtn.isHidden = true 56 | self.WhiteView.frame = self.whiteViewStartFrame 57 | self.cancelBtn.frame.origin.y = self.WhiteView.frame.maxY + 20 58 | }) { (_) in 59 | self.isHidden = true 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopSomeColorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopSelectColorView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/30. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*弹出一堆小视图,带回弹*/ 14 | import UIKit 15 | protocol PopSomeColorViewDelegate { 16 | func selectBtnTag(btnTag: NSInteger) 17 | } 18 | //定义闭包类型(特定的函数类型函数类型) 19 | typealias InputClosureType = (String) -> Void 20 | class PopSomeColorView: UIView { 21 | 22 | var delegate:PopSomeColorViewDelegate? 23 | //接收上个页面传过来的闭包块 24 | var backClosure: InputClosureType? 25 | var animateTime:TimeInterval = 0.9 //动画总时长 26 | var delyTime:CGFloat = 0.1 //每两个动画间隔时长 27 | var cancelBtn :UIButton = UIButton() 28 | var Y :CGFloat = ScreenHeight/2 + 100 //每个按钮上移的距离 29 | let colors: NSArray = [UIColor.green,UIColor.yellow,UIColor.blue,UIColor.red,UIColor.purple,UIColor.orange]; 30 | let btnWH: CGFloat = (ScreenWidth - 120)/3 31 | lazy var btnMarr: NSMutableArray = NSMutableArray() 32 | //背景区域的颜色和透明度 33 | var backgroundColor1:UIColor = UIColor.init(red: 0 , green: 0, blue: 0, alpha: 0.5) //初始化视图 34 | func initPopSelectColorView() -> UIView { 35 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 36 | self.backgroundColor = backgroundColor1 37 | self.isHidden = true 38 | for j in 0 ..< colors.count { 39 | let btn :UIButton = UIButton.init(type: .custom) 40 | btn.frame = CGRect.init(x: 50 + (10 + btnWH) * CGFloat(j%3), y: ScreenHeight + CGFloat(j/3) * (btnWH + 40), width: btnWH, height:btnWH) 41 | btn.layer.borderColor = ZHFColor.zhff9_backGroundColor.cgColor 42 | btn.layer.borderWidth = 4 43 | btn.backgroundColor = colors[j] as? UIColor; 44 | btn.tag = j 45 | btn.addTarget(self, action: #selector(cancelBtnClick), for: .touchUpInside) 46 | self.btnMarr.add(btn) 47 | self.addSubview(btn) 48 | if j == colors.count - 1{ 49 | self.cancelBtn = UIButton.init(type: .custom) 50 | self.cancelBtn.frame = CGRect.init(x:ScreenWidth/2 - 20, y: btn.frame.maxY + 40, width: 40, height: 40) 51 | self.cancelBtn.setImage(UIImage.init(named: "cancel_white"), for: .normal) 52 | self.cancelBtn.addTarget(self, action: #selector(cancelBtnClick), for: .touchUpInside) 53 | self.addSubview(cancelBtn) 54 | } 55 | } 56 | return self 57 | } 58 | func addAnimate(){ 59 | UIApplication.shared.keyWindow?.addSubview(self.initPopSelectColorView()) 60 | self.isHidden = false 61 | for i in 0 ..< self.btnMarr.count { 62 | let btn: UIButton = self.btnMarr[i] as! UIButton 63 | let btnY : CGFloat = btn.frame.origin.y 64 | let cancelBtnY :CGFloat = self.cancelBtn.frame.origin.y 65 | UIView.animate(withDuration: self.animateTime, delay: TimeInterval(self.delyTime * CGFloat(i)) , usingSpringWithDamping: 0.7, initialSpringVelocity: 0.2, options: .curveEaseInOut, animations: { 66 | btn.frame.origin.y = btnY - self.Y 67 | }, completion: { (_) in 68 | self.cancelBtn.transform = CGAffineTransform.init(rotationAngle:0) 69 | UIView.animate(withDuration: self.animateTime, animations: { 70 | self.cancelBtn.frame.origin.y = cancelBtnY - self.Y 71 | self.cancelBtn.transform = CGAffineTransform.init(rotationAngle:.pi/2) 72 | }) 73 | }) 74 | } 75 | } 76 | @objc func cancelBtnClick(btn: UIButton){ 77 | if btn != cancelBtn { 78 | self.delegate?.selectBtnTag(btnTag: btn.tag) 79 | } 80 | self.isHidden = false 81 | UIView.animate(withDuration: self.animateTime, animations: { 82 | self.cancelBtn.frame.origin.y += self.Y 83 | self.cancelBtn.transform = CGAffineTransform.init(rotationAngle:0) 84 | }) { (_) in 85 | for i in 0 ..< self.btnMarr.count { 86 | let btn: UIButton = self.btnMarr[self.btnMarr.count - i - 1] as! UIButton; 87 | let btnY : CGFloat = btn.frame.origin.y; 88 | UIView.animate(withDuration: self.animateTime, delay: TimeInterval(self.delyTime * CGFloat(i)) , usingSpringWithDamping: 0.7, initialSpringVelocity: 0.2, options: .curveEaseInOut, animations: { 89 | btn.frame.origin.y = btnY + self.Y 90 | }, completion: { (_) in 91 | self.btnMarr = NSMutableArray.init() 92 | self.removeFromSuperview() 93 | }) 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopTextView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopTextView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/10. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*弹出一个输入框*/ 14 | import UIKit 15 | 16 | class PopTextView: PopSmallChangeBigFatherView { 17 | let titleHeight: CGFloat = 75 18 | var placeHoldLable: UILabel = UILabel() 19 | var textView:UITextView = UITextView() 20 | var textStr : String = "请输入内容" 21 | var oneBtn:UIButton = UIButton() 22 | var otherBtn:UIButton = UIButton() 23 | override func addAnimate() { 24 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 25 | self.isHidden = false 26 | //按钮不要在动画完成后初始化(否则按钮没点击效果) 27 | oneBtn = UIButton.init(type: .custom) 28 | otherBtn = UIButton.init(type: .custom) 29 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 30 | self.WhiteView.frame = self.whiteViewEndFrame 31 | }) { (_) in 32 | self.addWhiteVieSubView1() 33 | } 34 | } 35 | //放一个输入框 36 | func addWhiteVieSubView1(){ 37 | let titleLabel:UILabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: self.WhiteView.frame.width, height: titleHeight)) 38 | titleLabel.text = "修改cell内容" 39 | titleLabel.textAlignment = NSTextAlignment.center 40 | titleLabel.font = UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.bold) 41 | titleLabel.textColor = ZHFColor.zhf_randomColor() 42 | self.WhiteView.addSubview(titleLabel) 43 | 44 | //占位Label的位置自行调整 45 | placeHoldLable = UILabel.init(frame: CGRect.init(x: 25, y: titleHeight + 8, width: self.WhiteView.frame.width - 50, height: 20)) 46 | placeHoldLable.text = textStr 47 | placeHoldLable.textColor = ZHFColor.black 48 | placeHoldLable.font = UIFont.systemFont(ofSize: 15)//大小和textView字体大小一致 49 | self.WhiteView.addSubview(placeHoldLable) 50 | 51 | textView = UITextView.init(frame: CGRect.init(x: 20, y: titleHeight, width: self.WhiteView.frame.width - 40, height: self.WhiteView.frame.height - titleHeight - 80)) 52 | textView.layer.masksToBounds = true 53 | textView.layer.borderColor = ZHFColor.zhfcc_lineColor.cgColor 54 | textView.layer.borderWidth = 1 55 | textView.layer.cornerRadius = 5 56 | textView.backgroundColor = UIColor.white 57 | textView.alpha = 0.5 58 | textView.delegate = self 59 | textView.returnKeyType = UIReturnKeyType.done 60 | textView.font = UIFont.systemFont(ofSize: 15) 61 | self.WhiteView.addSubview(textView) 62 | 63 | oneBtn.frame = CGRect.init(x:20, y: self.WhiteView.frame.height - 55, width: (self.WhiteView.frame.width - 50)/2, height: 40) 64 | oneBtn.layer.masksToBounds = true 65 | oneBtn.layer.cornerRadius = 5 66 | oneBtn.backgroundColor = ZHFColor.orange 67 | oneBtn.setTitle("确定", for: .normal) 68 | oneBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 69 | oneBtn.setTitleColor(UIColor.white, for: .normal) 70 | self.WhiteView.addSubview(oneBtn) 71 | 72 | otherBtn.frame = CGRect.init(x:oneBtn.frame.maxX + 10, y: self.WhiteView.frame.height - 55, width: (self.WhiteView.frame.width - 50)/2, height: 40) 73 | otherBtn.layer.masksToBounds = true 74 | otherBtn.layer.cornerRadius = 5 75 | otherBtn.backgroundColor = ZHFColor.orange 76 | otherBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 77 | otherBtn.setTitle("取消", for: .normal) 78 | otherBtn.setTitleColor(UIColor.white, for: .normal) 79 | self.WhiteView.addSubview(otherBtn) 80 | } 81 | } 82 | extension PopTextView:UITextViewDelegate{ 83 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 84 | self.endEditing(true); 85 | textView.resignFirstResponder() 86 | } 87 | func textViewDidChange(_ textView: UITextView) { 88 | if textView.text == ""{ 89 | placeHoldLable.isHidden = false 90 | textView.alpha = 0.5 91 | } 92 | else{ 93 | placeHoldLable.isHidden = true 94 | textView.alpha = 1 95 | } 96 | } 97 | //监听return 按钮被点击 98 | func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { 99 | if text == "\n" { 100 | self.endEditing(true); 101 | textView.resignFirstResponder() 102 | return false; 103 | } 104 | return true; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/PopTopOrBottomOutView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopTopOrBottomOutFatherView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/10. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*从底部或顶部弹出卡片,带回弹*/ 14 | import UIKit 15 | 16 | class PopTopOrBottomOutView: UIView { 17 | var cancelBtn :UIButton = UIButton() 18 | var outerImage:UIImageView = UIImageView() 19 | var whiteView :UIView = UIView() 20 | //背景区域的颜色和透明度 21 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 22 | var topOrBottomViewStartFrame = CGRect.init(x: 25, y: ScreenHeight, width: ScreenWidth - 50, height: 500) 23 | //初始化视图 24 | func initPopBackGroundView() -> UIView { 25 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 26 | self.backgroundColor = backgroundColor1 27 | self.isHidden = true 28 | //为落下的视图添加背景图 29 | let innerImage:UIImageView = UIImageView.init(frame: CGRect.init(x: 0, y: ScreenHeight - 210, width: ScreenWidth, height: 210)) 30 | innerImage.image = UIImage.init(named: "inner_layerImage") 31 | self.addSubview(innerImage) 32 | 33 | outerImage = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight)) 34 | outerImage.image = UIImage.init(named: "outer_layerImage") 35 | self.addSubview(outerImage) 36 | return self 37 | } 38 | //为白色视图添加子视图 39 | func addWhiteViewSubView() { 40 | let imageView: UIImageView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: whiteView.frame.size.width, height: whiteView.frame.size.height)) 41 | imageView.layer.masksToBounds = true 42 | imageView.contentMode = .scaleAspectFill 43 | imageView.image = UIImage.init(named: "bmw_image") 44 | whiteView.addSubview(imageView) 45 | let titleLabel: UILabel = UILabel.init(frame: CGRect.init(x: 5, y: 0, width: whiteView.frame.size.width - 10, height: 50)) 46 | titleLabel.textColor = UIColor.white 47 | titleLabel.font = UIFont.systemFont(ofSize: 20) 48 | titleLabel.text = "恭喜你获得一台 “别摸我”!!!!" 49 | imageView.addSubview(titleLabel) 50 | let contentLabel: UILabel = UILabel.init(frame: CGRect.init(x: 20, y: titleLabel.frame.maxY, width: whiteView.frame.size.width - 40, height: 70)) 51 | contentLabel.textColor = UIColor.orange 52 | contentLabel.font = UIFont.systemFont(ofSize: 15) 53 | contentLabel.numberOfLines = 0 54 | contentLabel.textAlignment = NSTextAlignment.right 55 | contentLabel.text = "别摸我是一款超级牛逼的车,据说上天都不用梯子,全靠空气动力支撑,能上天,能下海,我只不过是瞎说的。" 56 | imageView.addSubview(contentLabel) 57 | } 58 | //从下面弹出来 59 | func addAnimateFromBottom() { 60 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 61 | self.isHidden = false 62 | self.cancelBtn.isHidden = true 63 | self.whiteView.frame = topOrBottomViewStartFrame 64 | self.whiteView.backgroundColor = ZHFColor.zhf_colorAlpha(withHex: 0xffffff, alpha: 0) 65 | self.addSubview(self.whiteView) 66 | addWhiteViewSubView() 67 | 68 | self.cancelBtn = UIButton.init(type: .custom) 69 | UIView.animate(withDuration:0.5, animations: { 70 | self.whiteView.frame.origin.y = ScreenHeight - 670 71 | self.bringSubviewToFront(self.outerImage) 72 | }) { (_) in 73 | UIView.animate(withDuration: 0.2, animations: { 74 | self.whiteView.frame.origin.y = ScreenHeight - 530 75 | }, completion: { (_) in 76 | UIView.animate(withDuration: 0.2, animations: { 77 | self.whiteView.frame.origin.y = ScreenHeight - 570 78 | }, completion: { (_) in 79 | self.cancelBtn.isHidden = false 80 | self.cancelBtn.frame = CGRect.init(x:self.frame.maxX - 60, y:ScreenHeight - 610, width: 40, height: 40) 81 | self.cancelBtn.tag = 1 82 | self.cancelBtn.setImage(UIImage.init(named: "cancel_white"), for: .normal) 83 | self.cancelBtn.addTarget(self, action: #selector(self.cancelBtnClickBottom), for: .touchUpInside) 84 | self.addSubview(self.cancelBtn) 85 | }) 86 | }) 87 | } 88 | } 89 | //从上面弹出来 90 | func addAnimateFromTop() { 91 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 92 | self.isHidden = false 93 | self.cancelBtn.isHidden = true 94 | self.whiteView.frame = topOrBottomViewStartFrame 95 | self.whiteView.backgroundColor = ZHFColor.zhf_colorAlpha(withHex: 0xffffff, alpha: 0.5) 96 | self.addSubview(self.whiteView) 97 | addWhiteViewSubView() 98 | 99 | self.cancelBtn = UIButton.init(type: .custom) 100 | UIView.animate(withDuration:0.5, animations: { 101 | self.whiteView.frame.origin.y = ScreenHeight - 470 102 | self.bringSubviewToFront(self.outerImage) 103 | }) { (_) in 104 | UIView.animate(withDuration: 0.2, animations: { 105 | self.whiteView.frame.origin.y = ScreenHeight - 610 106 | }, completion: { (_) in 107 | UIView.animate(withDuration: 0.2, animations: { 108 | self.whiteView.frame.origin.y = ScreenHeight - 570 109 | }, completion: { (_) in 110 | self.cancelBtn.isHidden = false 111 | self.cancelBtn.frame = CGRect.init(x:self.frame.maxX - 60, y:ScreenHeight - 610, width: 40, height: 40) 112 | self.cancelBtn.setImage(UIImage.init(named: "cancel_white"), for: .normal) 113 | self.cancelBtn.addTarget(self, action: #selector(self.cancelBtnClickTop), for: .touchUpInside) 114 | self.addSubview(self.cancelBtn) 115 | }) 116 | }) 117 | } 118 | } 119 | @objc func cancelBtnClickTop(btn:UIButton){ 120 | self.cancelBtn.isHidden = true 121 | UIView.animate(withDuration: 0.5, animations: { 122 | self.whiteView.frame.origin.y = -ScreenHeight 123 | }) { (_) in 124 | self.removeFromSuperview() 125 | } 126 | } 127 | @objc func cancelBtnClickBottom(btn:UIButton){ 128 | self.cancelBtn.isHidden = true 129 | UIView.animate(withDuration: 0.5, animations: { 130 | self.whiteView.frame.origin.y = ScreenHeight 131 | }) { (_) in 132 | self.removeFromSuperview() 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/SlideView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlideView.swift 3 | // SlideViewTest 4 | // 5 | // Created by 张海峰 on 2018/11/8. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*侧滑视图主框架*/ 14 | import UIKit 15 | enum SlideDirection: NSInteger { 16 | case left 17 | case right 18 | } 19 | class SlideView: UIView,UIGestureRecognizerDelegate { 20 | var isfromLeft: Bool = true 21 | var currentPanDirection: SlideDirection? 22 | //白色view用来装一些控件 23 | var WhiteView: UIView = UIView() 24 | var whiteViewStartFrame: CGRect = CGRect.init(x: -ScreenWidth*4/5, y: 0, width: ScreenWidth*4/5, height: ScreenHeight) 25 | var whiteViewEndFrame: CGRect = CGRect.init(x: 0, y: 0, width: ScreenWidth*4/5, height: ScreenHeight) 26 | //背景区域的颜色和透明度 27 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 28 | var defaultTime:CGFloat = 0.5 29 | //初始化视图 30 | func initPopBackGroundView() -> UIView { 31 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 32 | self.backgroundColor = backgroundColor1 33 | self.isHidden = true 34 | //设置添加地址的View 35 | self.WhiteView.frame = whiteViewStartFrame 36 | WhiteView.backgroundColor = UIColor.white 37 | self.addSubview(WhiteView) 38 | //添加点击手势 39 | let tap: UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(tapBtnAndbackBtnClick)) 40 | tap.delegate = self 41 | self.addGestureRecognizer(tap) 42 | //添加侧滑手势 43 | let pan: UIPanGestureRecognizer = UIPanGestureRecognizer.init(target: self, action: #selector(self.didPanEvent)) 44 | pan.delegate = self 45 | self.addGestureRecognizer(pan) 46 | return self 47 | } 48 | //弹出的动画效果 49 | func addAnimate() { 50 | 51 | } 52 | //收回的动画效果 53 | @objc func tapBtnAndbackBtnClick() { 54 | UIView.animate(withDuration: TimeInterval(defaultTime), animations: { 55 | self.WhiteView.frame = self.whiteViewStartFrame 56 | }) { (_) in 57 | for view in self.WhiteView.subviews { 58 | view.removeFromSuperview() 59 | } 60 | self.isHidden = true 61 | } 62 | } 63 | //通过手势收回的动画效果 64 | @objc func didPanEvent(recognizer: UIPanGestureRecognizer){ 65 | //拿到手势在移动过程中当前位置(相对于其实位置为(0,0)) 66 | let translation: CGPoint = recognizer.translation(in: self) 67 | if (translation.x != 0){ 68 | //确定移动(并判断手势方向) 69 | currentPanDirection = translation.x > 0 ? SlideDirection.right : SlideDirection.left 70 | } 71 | //位置归0 72 | recognizer.setTranslation(CGPoint.zero, in: self) 73 | //根据手势操作 74 | switch recognizer.state { 75 | case .began: break 76 | case .changed: 77 | let tempX :CGFloat = self.WhiteView.frame.minX + translation.x 78 | //从左边出来 79 | if isfromLeft == true{ 80 | //可移动的条件 左滑||右滑 小于打开时的minX 81 | if translation.x < 0 || (translation.x > 0 && tempX < 0){ 82 | self.WhiteView.frame = CGRect.init(x: tempX, y: (ScreenHeight - WhiteView.frame.height)/2, width: WhiteView.frame.width, height: WhiteView.frame.height) 83 | } 84 | } 85 | //从右边出来 86 | if isfromLeft == false{ 87 | //可移动的条件 右滑||左滑 大于打开时的minX 88 | if translation.x > 0 || (translation.x < 0 && tempX > (ScreenWidth - WhiteView.frame.width)){ 89 | self.WhiteView.frame = CGRect.init(x: tempX, y: (ScreenHeight - WhiteView.frame.height)/2, width: WhiteView.frame.width, height: WhiteView.frame.height) 90 | } 91 | } 92 | case .cancelled: break 93 | case .ended: 94 | if isfromLeft == true{ 95 | if self.currentPanDirection == SlideDirection.left{ 96 | self.tapBtnAndbackBtnClick() 97 | } 98 | if self.currentPanDirection == SlideDirection.right{ 99 | self.WhiteView.frame = CGRect.init(x: 0, y: (ScreenHeight - WhiteView.frame.height)/2, width: WhiteView.frame.width, height: WhiteView.frame.height) 100 | } 101 | } 102 | if isfromLeft == false{ 103 | if self.currentPanDirection == SlideDirection.right{ 104 | self.tapBtnAndbackBtnClick() 105 | } 106 | if self.currentPanDirection == SlideDirection.left{ 107 | self.WhiteView.frame = CGRect.init(x: ScreenWidth - WhiteView.frame.width, y: (ScreenHeight - WhiteView.frame.height)/2, width: WhiteView.frame.width, height: WhiteView.frame.height) 108 | } 109 | } 110 | default: 111 | break 112 | } 113 | } 114 | //防止侧滑视图手势与列表点击起冲突 115 | func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { 116 | /** 117 | *判断如果点击的是tableView的cell,就把手势给关闭了 不是点击cell手势开启 118 | **/ 119 | if NSStringFromClass((touch.view?.classForCoder)!) == "UITableViewCellContentView" { 120 | return false 121 | } 122 | return true 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/SlideWhiteViewSubView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlideWhiteViewSubView.swift 3 | // SlideViewTest 4 | // 5 | // Created by 张海峰 on 2018/11/14. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | /*侧滑视图为白色视图添加内容*/ 14 | import UIKit 15 | //添加一个列表点击代理 16 | protocol SlideWhiteViewSubViewDelegate { 17 | func selectMessage(message: String) 18 | } 19 | class SlideWhiteViewSubView: SlideView { 20 | var delegate:SlideWhiteViewSubViewDelegate? 21 | lazy var dataMarr:NSMutableArray = NSMutableArray() 22 | override func addAnimate() { 23 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 24 | self.isHidden = false 25 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 26 | self.WhiteView.frame = self.whiteViewEndFrame 27 | }) { (_) in 28 | //添加白色视图内容 29 | self.addWhiteViewSubViews() 30 | } 31 | } 32 | func addWhiteViewSubViews(){ 33 | //添加头部内容 34 | let imageView: UIImageView = UIImageView.init(frame: CGRect.init(x: (WhiteView.frame.width - 100)/2, y: 50, width: 100, height: 100)) 35 | imageView.image = UIImage.init(named: "test1") 36 | imageView.layer.masksToBounds = true 37 | imageView.layer.cornerRadius = 50 38 | WhiteView.addSubview(imageView) 39 | //添加一个列表 40 | self.dataMarr = ["视图标题一","视图标题二","视图标题三","视图标题四","视图标题五"] 41 | addTableView() 42 | //添加底部按钮(底部按钮点击响应可以1.通过代理方法(类似列表的代理实现)2.也可以把按钮定义成全局的,在VC中直接 WhiteView.setBtn1.addTarget(self, action: #selector(setBtn1Click), for: UIControlEvents.touchUpInside)) 43 | let setBtn1: UIButton = UIButton.init(type: UIButton.ButtonType.custom) 44 | setBtn1.frame = CGRect.init(x: 40, y: WhiteView.frame.height - 100, width: 50, height: 30) 45 | setBtn1.setTitle("设置1", for: UIControl.State.normal) 46 | setBtn1.backgroundColor = UIColor.orange 47 | 48 | WhiteView.addSubview(setBtn1) 49 | let setBtn2: UIButton = UIButton.init(type: UIButton.ButtonType.custom) 50 | setBtn2.frame = CGRect.init(x: setBtn1.frame.maxX + 30, y: WhiteView.frame.height - 100, width: 50, height: 30) 51 | setBtn2.setTitle("设置2", for: UIControl.State.normal) 52 | setBtn2.backgroundColor = UIColor.red 53 | WhiteView.addSubview(setBtn2) 54 | } 55 | func addTableView(){ 56 | let tableView = UITableView.init(frame: CGRect.init(x: 0, y: 200, width: WhiteView.frame.width, height: WhiteView.frame.height - 300), style: UITableView.Style.plain) 57 | WhiteView.addSubview(tableView) 58 | tableView.backgroundColor = UIColor.white 59 | tableView.separatorColor = UIColor.black 60 | tableView.separatorStyle = UITableViewCell.SeparatorStyle.none 61 | tableView.separatorInset = UIEdgeInsets.init(top: 0, left: 0, bottom: 0, right: 0) 62 | tableView.delegate = self 63 | tableView.dataSource = self 64 | } 65 | 66 | } 67 | extension SlideWhiteViewSubView :UITableViewDataSource,UITableViewDelegate 68 | { 69 | func numberOfSections(in tableView: UITableView) -> Int { 70 | return 1 71 | } 72 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 73 | return self.dataMarr.count 74 | } 75 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 76 | let alertCellIdentifier = "alertCellIdentifier" 77 | var cell = tableView.dequeueReusableCell(withIdentifier: alertCellIdentifier) 78 | if cell == nil { 79 | cell = UITableViewCell(style:.default, reuseIdentifier: alertCellIdentifier) 80 | } 81 | cell?.textLabel?.text = self.dataMarr[indexPath.row] as? String 82 | cell?.textLabel?.font = UIFont.systemFont(ofSize: 13) 83 | cell?.textLabel?.textColor = UIColor.lightGray 84 | cell?.selectionStyle = UITableViewCell.SelectionStyle.none 85 | return cell! 86 | } 87 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 88 | let message = self.dataMarr[indexPath.row] as! String 89 | //先回收再传值 90 | UIView.animate(withDuration: 0.5, animations: { 91 | self.tapBtnAndbackBtnClick() 92 | }) { (_) in 93 | self.delegate?.selectMessage(message:message) 94 | } 95 | } 96 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 97 | return 40 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/UpDownView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpDownView.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2019/2/21. 6 | // Copyright © 2019年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class UpDownView: UIView ,UIGestureRecognizerDelegate{ 12 | //白色view用来装一些控件 13 | var WhiteView: UIView = UIView() 14 | var whiteViewStartFrame: CGRect = CGRect.init(x: 0, y: ScreenHeight, width: ScreenWidth, height: 420) 15 | var whiteViewEndFrame: CGRect = CGRect.init(x: 0, y: ScreenHeight - 420, width: ScreenWidth, height: 420) 16 | //确定按钮 17 | var okBtn: UIButton = UIButton() 18 | //背景区域的颜色和透明度 19 | var backgroundColor1:UIColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4) 20 | var defaultTime:CGFloat = 0.5 21 | 22 | //初始化视图 23 | func initPopBackGroundView() -> UIView { 24 | self.frame = CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight) 25 | self.backgroundColor = backgroundColor1 26 | self.isHidden = true 27 | //设置添加地址的View 28 | self.WhiteView.frame = whiteViewStartFrame 29 | WhiteView.backgroundColor = UIColor.white 30 | self.addSubview(WhiteView) 31 | //添加点击手势 32 | let tap: UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(tapBtnAndcancelBtnClick)) 33 | tap.delegate = self 34 | self.addGestureRecognizer(tap) 35 | okBtn = UIButton.init(type: .custom) 36 | okBtn.frame = CGRect.init(x:ScreenWidth - 80, y: 10, width: 60, height: 40) 37 | okBtn.tag = 1 38 | okBtn.setTitle("确定", for: .normal) 39 | okBtn.setTitleColor(ZHFColor.green, for: .normal) 40 | okBtn.addTarget(self, action: #selector(tapBtnAndcancelBtnClick), for: .touchUpInside) 41 | WhiteView.addSubview(okBtn) 42 | return self 43 | } 44 | //弹出的动画效果 45 | func addAnimate() { 46 | 47 | } 48 | //收回的动画效果 49 | @objc func tapBtnAndcancelBtnClick() { 50 | for view in WhiteView.subviews { 51 | view.removeFromSuperview() 52 | } 53 | UIView.animate(withDuration: TimeInterval(defaultTime), animations: { 54 | self.WhiteView.frame = self.whiteViewStartFrame 55 | }) { (_) in 56 | self.isHidden = true 57 | } 58 | } 59 | func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { 60 | //点击WhiteView不回收 61 | if (touch.view?.isDescendant(of: self.WhiteView))!{ 62 | return false 63 | } 64 | return true 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/ZHFAlertControllerTool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZHFAlertControllerTool.swift 3 | // ZHFToolBox 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中自定义各种弹框的思路,用来支撑自己项目的使用,无论什么样的弹框,只要有思路, 9 | 相信大家都能完美实现。感觉我这个demo对你有启发或者帮助,不妨给个星星吧 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | https://www.jianshu.com/p/88420bc4d32d 12 | */ 13 | import Foundation 14 | import UIKit 15 | /* 16 | - parameter currentVC: 当前控制器 17 | - parameter title: 标题 18 | - parameter meg: 提示消息 19 | - parameter cancelBtn: 取消按钮 20 | - parameter otherBtn: 其他按钮 21 | - parameter handler: 其他按钮处理事件 22 | */ 23 | class ZHFAlertControllerTool { 24 | /** 25 | alterController 一个按钮 不处理事件,简单实用 26 | */ 27 | static func showAlert(currentVC:UIViewController, title:String,meg:String, cancelBtn:String){ 28 | var title1 = "" 29 | if title == "" || title == nil { 30 | title1 = "温馨提示"} 31 | else{ 32 | title1 = title 33 | } 34 | let alertController = UIAlertController(title:title1,message:meg , preferredStyle: .alert) 35 | let cancelAction = UIAlertAction(title:cancelBtn, style: .cancel, handler:nil) 36 | alertController.addAction(cancelAction) 37 | currentVC.present(alertController, animated: true, completion: nil) 38 | } 39 | /** 40 | alterController 一个按钮 处理事件 41 | */ 42 | static func showAlert(currentVC:UIViewController, title:String, meg:String, okBtn:String, handler:((UIAlertAction) -> Void)?){ 43 | var title1 = "" 44 | if title == "" || title == nil { 45 | title1 = "温馨提示"} 46 | else{ 47 | title1 = title 48 | } 49 | let alertController = UIAlertController(title:title1,message:meg , preferredStyle: .alert) 50 | if okBtn != nil{ 51 | let settingsAction = UIAlertAction(title: okBtn, style: .default, handler: { (action) -> Void in 52 | handler?(action) 53 | }) 54 | alertController.addAction(settingsAction) 55 | } 56 | currentVC.present(alertController, animated: true, completion: nil) 57 | } 58 | /** 59 | 两个按钮 都处理事件 60 | **/ 61 | static func showAlert(currentVC:UIViewController, title:String, meg:String, oneBtn:String, otherBtn:String?,oneHandler:((UIAlertAction) -> Void)?, otherHandler:((UIAlertAction) -> Void)?){ 62 | var title1 = "" 63 | if title == "" || title == nil { 64 | title1 = "温馨提示"} 65 | else{ 66 | title1 = title 67 | } 68 | let alertController = UIAlertController(title:title1, 69 | message:meg , 70 | preferredStyle: .alert) 71 | let cancelAction = UIAlertAction(title:oneBtn, style: .cancel, handler:{ (action) -> Void in 72 | oneHandler?(action) 73 | }) 74 | alertController.addAction(cancelAction) 75 | if otherBtn != nil{ 76 | let settingsAction = UIAlertAction(title: otherBtn, style: .default, handler: { (action) -> Void in 77 | otherHandler?(action) 78 | }) 79 | alertController.addAction(settingsAction) 80 | } 81 | currentVC.present(alertController, animated: true, completion: nil) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/ZHFCalendarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZHFCalendarView.swift 3 | // 日历弹窗 4 | // 5 | // Created by 张海峰 on 2019/4/5. 6 | // Copyright © 2019年 张海峰. All rights reserved. 7 | // 8 | /*该demo是和大家分享一下,在项目中集成一个日历弹窗,用自己可想到的最少代码实现日历弹窗 9 | 当然这个弹窗也是我自定义弹窗的极小部分,对Swift弹窗感兴趣的帅哥美女,可戳下面链接 10 | https://github.com/FighterLightning/ZHFToolBox.git 11 | */ 12 | import UIKit 13 | 14 | class ZHFCalendarView: UpDownView { 15 | var pointColor: UIColor = ZHFColor.zhf_color(withHex: 0x42D2BE) 16 | //声明闭包 17 | typealias clickBtnClosure = (String?) -> Void 18 | //把申明的闭包设置成属性 19 | var clickClosure: clickBtnClosure? 20 | //为闭包设置调用函数 21 | func clickValueClosure(closure:clickBtnClosure?){ 22 | clickClosure = closure 23 | } 24 | var bigGreenPoints:[NSInteger] = [5,7,10] 25 | var smallGreenPoints:[NSInteger] = [3,7,8,10,25] 26 | var nowMonth: NSInteger = 1 //现在时间 27 | var nowYear: NSInteger = 2019 //现在时间 28 | var monthNumber: NSInteger = 1 // 可变化的时间 29 | var yearNumber: NSInteger = 2019 // 可变化的时间 30 | let topMargin :CGFloat = 10; 31 | let leftMargin :CGFloat = 25;//靠边数字距离左边和右边距离 32 | let bothMargin :CGFloat = 10;//两个数字间距离 33 | let viewWH :CGFloat = (ScreenWidth - 25*2 - 10*6)/7; //每个数字的宽高 34 | var titleLabel1: UILabel = UILabel() 35 | var rightBtn:UIButton = UIButton() 36 | var calendarView: UIView = UIView() 37 | override func addAnimate() { 38 | UIApplication.shared.keyWindow?.addSubview(self.initPopBackGroundView()) 39 | self.isHidden = false 40 | //按钮不要在动画完成后初始化(否则按钮没点击效果) 41 | UIView.animate(withDuration:TimeInterval(defaultTime), animations: { 42 | self.WhiteView.frame = self.whiteViewEndFrame 43 | }) { (_) in 44 | self.addWhiteVieSubView() 45 | } 46 | } 47 | //放一张展示图片 48 | func addWhiteVieSubView(){ 49 | monthNumber = convertDateToMonth(date: NSDate.init()) 50 | yearNumber = convertDateToYear(date: NSDate.init()) 51 | nowMonth = convertDateToMonth(date: NSDate.init()) 52 | nowYear = convertDateToYear(date: NSDate.init()) 53 | calendarViewHeader() 54 | test(month: monthNumber) 55 | } 56 | //日历头 57 | func calendarViewHeader(){ 58 | let headerView: UIView = UIView.init(frame: CGRect.init(x: 0, y: 50, width: ScreenWidth, height: 80)) 59 | WhiteView.addSubview(headerView) 60 | let leftBtn:UIButton = UIButton.init(type: UIButton.ButtonType.custom) 61 | leftBtn.frame = CGRect.init(x: 25, y: 0, width: 60, height: 40) 62 | leftBtn.setImage(UIImage.init(named: "left"), for: UIControl.State.normal) 63 | leftBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 64 | leftBtn.setTitleColor(UIColor.gray, for: UIControl.State.normal) 65 | leftBtn.addTarget(self, action: #selector(leftBtnClick), for: UIControl.Event.touchUpInside) 66 | headerView.addSubview(leftBtn) 67 | titleLabel1 = UILabel.init(frame: CGRect.init(x: ScreenWidth/2 - 80, y: 0, width: 160, height: 40)) 68 | titleLabel1.textAlignment = NSTextAlignment.center 69 | titleLabel1.textColor = ZHFColor.zhf_color(withHex: 0x333333) 70 | titleLabel1.font = UIFont.systemFont(ofSize: 17) 71 | headerView.addSubview(titleLabel1) 72 | rightBtn = UIButton.init(type: UIButton.ButtonType.custom) 73 | rightBtn.frame = CGRect.init(x: ScreenWidth - 85, y: 0, width: 60, height: 40) 74 | rightBtn.setImage(UIImage.init(named: "right"), for: UIControl.State.normal) 75 | rightBtn.titleLabel?.font = UIFont.systemFont(ofSize: 14) 76 | rightBtn.setTitleColor(UIColor.gray, for: UIControl.State.normal) 77 | rightBtn.addTarget(self, action: #selector(rightBtnClick), for: UIControl.Event.touchUpInside) 78 | headerView.addSubview(rightBtn) 79 | let arr = ["S","M","T","W","T","F","S"] 80 | for i in 0 ..< 7 { 81 | let textLabel: UILabel = UILabel.init(frame: CGRect.init(x: leftMargin + (viewWH+bothMargin)*CGFloat(i), y: 40, width: viewWH, height: 40)) 82 | textLabel.text = arr[i] 83 | textLabel.font = UIFont.systemFont(ofSize: 13) 84 | textLabel.textAlignment = NSTextAlignment.center 85 | textLabel.textColor = ZHFColor.zhf_color(withHex: 0x999999); 86 | headerView.addSubview(textLabel) 87 | } 88 | calendarView = UIView.init(frame: CGRect.init(x: 0, y: headerView.frame.maxY, width: ScreenWidth, height: WhiteView.frame.size.height - headerView.frame.maxY)) 89 | WhiteView.addSubview(calendarView) 90 | } 91 | //上个月 92 | @objc func leftBtnClick(){ 93 | monthNumber = monthNumber - 1 94 | test(month: monthNumber) 95 | } 96 | //下个月 97 | @objc func rightBtnClick(){ 98 | monthNumber = monthNumber + 1 99 | test(month: monthNumber) 100 | } 101 | //是否隐藏右按钮 102 | func isHiddenRightBtn() { 103 | if nowYear > yearNumber { 104 | rightBtn.isHidden = false 105 | } 106 | else{ 107 | if nowMonth > monthNumber{ 108 | rightBtn.isHidden = false 109 | } 110 | else{ 111 | rightBtn.isHidden = true 112 | } 113 | } 114 | } 115 | func test(month:NSInteger){ 116 | for view1 in calendarView.subviews { 117 | view1.removeFromSuperview() 118 | } 119 | if (monthNumber > 12) { 120 | monthNumber = 1; 121 | yearNumber = yearNumber + 1; 122 | } 123 | if (monthNumber <= 0) { 124 | monthNumber = 12; 125 | yearNumber = yearNumber - 1; 126 | } 127 | let dateFormatter: DateFormatter = DateFormatter.init() 128 | dateFormatter.dateFormat = "yyyy-MM" 129 | var string:String = "\(yearNumber)-\(monthNumber)" 130 | if monthNumber < 10 { 131 | string = "\(yearNumber)-0\(monthNumber)" 132 | } 133 | isHiddenRightBtn() 134 | titleLabel1.text = string 135 | let date: NSDate = dateFormatter.date(from: string)! as NSDate 136 | logCalendarWith(date: date, day: 5, isHiden: false) 137 | } 138 | func logCalendarWith(date:NSDate,day:NSInteger,isHiden:Bool) { 139 | let firstWeekDay :NSInteger = convertDateToFirstWeekDay(date: date) //本月第一天是周几 140 | let totalDays: NSInteger = convertDateToTotalDays(date: date)//本月总天数 141 | var available: NSInteger = 1//本月第一天 142 | var nextMonthDay: NSInteger = 1//下月第一天 143 | let lastMonthDate: NSDate = getDateFrom(date: date, offsetMonths: -1)//上月月数 144 | let lastMonthTotalDays :NSInteger = convertDateToTotalDays(date: lastMonthDate) //上月总天数 145 | let line :NSInteger = (totalDays + firstWeekDay + 6)/7; //计算行数 146 | let column: NSInteger = 7 //一共从周日到周一7列 147 | for i in 0 ..< line { 148 | for j in 0 ..< column { 149 | //尾 150 | if (available > totalDays) { 151 | if (isHiden == true) { 152 | // print("\t"); 153 | } 154 | else{ 155 | //print("\t%ld",nextMonthDay); 156 | let view: UIView = UIView.init(frame: CGRect.init(x: leftMargin + (bothMargin+viewWH)*CGFloat(j) , y: topMargin+(bothMargin+viewWH)*CGFloat(i), width: viewWH, height: viewWH)) 157 | calendarView.addSubview(view) 158 | view.tag = nextMonthDay; 159 | // self.isSelect(isSelect: false, isHavePoint: false, fatherView: view) 160 | } 161 | nextMonthDay = nextMonthDay + 1; 162 | continue; 163 | } 164 | //头 165 | if (i == 0 && j < firstWeekDay) { 166 | //根据当月第一天是周几,回推出上个月最后几天对应的位置。 167 | let lastMonthDay :NSInteger = lastMonthTotalDays - firstWeekDay + j + 1; //j从0开始,所以这里+1 168 | if (isHiden == true) { 169 | // print("\t"); 170 | } 171 | else{ 172 | // print("\t%ld",lastMonthDay); 173 | let view: UIView = UIView.init(frame: CGRect.init(x: leftMargin + (bothMargin+viewWH)*CGFloat(j), y: topMargin, width: viewWH, height: viewWH)) 174 | calendarView.addSubview(view) 175 | view.tag = lastMonthDay; 176 | // self.isSelect(isSelect: false, isHavePoint: false, fatherView: view) 177 | } 178 | }else { 179 | //打印当月数据 180 | let view: UIView = UIView.init(frame: CGRect.init(x: leftMargin + (bothMargin+viewWH)*CGFloat(j), y: topMargin+(bothMargin+viewWH)*CGFloat(i), width: viewWH, height: viewWH)) 181 | calendarView.addSubview(view) 182 | view.tag = available 183 | if (bigGreenPoints.contains(available)&&smallGreenPoints.contains(available)){ 184 | self.isSelect(isSelect: true, isHavePoint: true, fatherView: view) 185 | } 186 | else if (bigGreenPoints.contains(available)&&(smallGreenPoints.contains(available)==false)){ 187 | self.isSelect(isSelect: true, isHavePoint: false, fatherView: view) 188 | } 189 | else if (smallGreenPoints.contains(available)&&(bigGreenPoints.contains(available)==false)){ 190 | self.isSelect(isSelect: false, isHavePoint: true, fatherView: view) 191 | } 192 | else{ 193 | self.isSelect(isSelect: false, isHavePoint: false, fatherView: view) 194 | } 195 | available = available + 1; 196 | } 197 | } 198 | } 199 | } 200 | func isSelect(isSelect:Bool,isHavePoint:Bool,fatherView:UIView){ 201 | let tap:UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(tapClick)) 202 | fatherView.addGestureRecognizer(tap) 203 | let textLabel:UILabel = UILabel.init(frame: CGRect.init(x: 5, y: 0, width: viewWH-10, height: viewWH-10)) 204 | textLabel.layer.masksToBounds = true 205 | textLabel.layer.cornerRadius = (viewWH-10)/2 206 | textLabel.text = "\(fatherView.tag)" 207 | textLabel.font = UIFont.systemFont(ofSize: 12) 208 | textLabel.textAlignment = NSTextAlignment.center 209 | textLabel.backgroundColor = UIColor.white 210 | textLabel.textColor = UIColor.black 211 | fatherView.addSubview(textLabel) 212 | if (isSelect == true) { 213 | textLabel.backgroundColor = pointColor 214 | } 215 | else{ 216 | textLabel.backgroundColor = UIColor.white 217 | } 218 | if (isHavePoint == true) { 219 | let pointView:UIView = UIView.init(frame: CGRect.init(x: viewWH/2-4, y: viewWH-8, width: 6, height: 6)) 220 | pointView.backgroundColor = pointColor 221 | pointView.layer.masksToBounds = true 222 | pointView.layer.cornerRadius = 3 223 | fatherView.addSubview(pointView) 224 | } 225 | } 226 | @objc func tapClick(tap:UITapGestureRecognizer) { 227 | if clickClosure != nil{ 228 | tapBtnAndcancelBtnClick() 229 | clickClosure!("\(yearNumber)-\(monthNumber)-\(tap.view!.tag)") 230 | } 231 | } 232 | //根据date获取日 233 | func convertDateToDay(date: NSDate) -> NSInteger { 234 | let calendar:NSCalendar = NSCalendar.current as NSCalendar 235 | let components:NSDateComponents = calendar.components(NSCalendar.Unit(rawValue: NSCalendar.Unit.day.rawValue), from: date as Date) as NSDateComponents 236 | return components.day; 237 | } 238 | 239 | //根据date获取月 240 | func convertDateToMonth(date: NSDate) -> NSInteger { 241 | let calendar:NSCalendar = NSCalendar.current as NSCalendar 242 | let components:NSDateComponents = calendar.components(NSCalendar.Unit(rawValue: NSCalendar.Unit.month.rawValue), from: date as Date) as NSDateComponents 243 | return components.month; 244 | } 245 | //根据date获取年 246 | func convertDateToYear(date: NSDate) -> NSInteger { 247 | let calendar:NSCalendar = NSCalendar.current as NSCalendar 248 | let components:NSDateComponents = calendar.components(NSCalendar.Unit(rawValue: NSCalendar.Unit.year.rawValue), from: date as Date) as NSDateComponents 249 | return components.year; 250 | } 251 | //根据date获取当月周几 252 | func convertDateToFirstWeekDay(date:NSDate) -> NSInteger { 253 | let calendar:NSCalendar = NSCalendar.current as NSCalendar 254 | calendar.firstWeekday = 1//1.Sun. 2.Mon. 3.Thes. 4.Wed. 5.Thur. 6.Fri. 7.Sat. 255 | let comp :NSDateComponents = calendar.components(NSCalendar.Unit(rawValue: NSCalendar.Unit.year.rawValue | NSCalendar.Unit.month.rawValue | NSCalendar.Unit.day.rawValue), from: date as Date) as NSDateComponents 256 | comp.day = 1 257 | let firstDayOfMonthDate:NSDate = calendar.date(from: comp as DateComponents)! as NSDate 258 | let firstWeekday :UInt = UInt(calendar.ordinality(of: NSCalendar.Unit.weekday, in:NSCalendar.Unit.weekOfMonth, for: firstDayOfMonthDate as Date)) 259 | let firstWeekday1 = firstWeekday - 1 260 | return NSInteger(firstWeekday1); //美国时间周日为星期的第一天,所以周日-周六为1-7,改为0-6方便计算 261 | } 262 | //根据date获取当月总天数 263 | func convertDateToTotalDays(date: NSDate) -> NSInteger { 264 | let calendar = Calendar(identifier:Calendar.Identifier.gregorian) 265 | let daysInOfMonth:NSRange = ((calendar as NSCalendar?)?.range(of: NSCalendar.Unit.day, in: NSCalendar.Unit.month, for: date as Date))! 266 | return daysInOfMonth.length 267 | } 268 | //根据date获取偏移指定月数的date 269 | func getDateFrom(date: NSDate,offsetMonths: NSInteger) -> NSDate { 270 | let formatter: DateFormatter = DateFormatter.init() 271 | formatter.dateFormat = "yyyy-MM" 272 | let calendar:NSCalendar = NSCalendar.current as NSCalendar 273 | let lastMonthComps:NSDateComponents = NSDateComponents.init() 274 | lastMonthComps.month = offsetMonths //year = 1表示1年后的时间 year = -1为1年前的日期,month day 类推 275 | let newdate:NSDate = calendar.date(byAdding: lastMonthComps as DateComponents, to: date as Date, options: NSCalendar.Options.init(rawValue: 0))! as NSDate 276 | return newdate; 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /ZHFToolBox/ZHFSubToolBox/ZHFColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZHFColor.swift 3 | // AmazedBox 4 | // 5 | // Created by lantian on 2017/12/4. 6 | // Copyright © 2017年 张海峰. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ZHFColor: UIColor { 12 | /// 主题色(及选中颜色) 13 | open class var zhf_selectColor: UIColor { 14 | //橙色 15 | get { 16 | return self.zhf_color(withHex: 0xF98507) 17 | } 18 | } 19 | /// 标题字体颜色 20 | open class var zhf33_titleTextColor: UIColor { 21 | 22 | get { 23 | return self.zhf_color(withHex: 0x333333) 24 | } 25 | } 26 | /// 内容字体颜色 27 | open class var zhf88_contentTextColor: UIColor { 28 | 29 | get { 30 | return self.zhf_color(withHex: 0x888888) 31 | } 32 | } 33 | open class var zhf66_contentTextColor: UIColor { 34 | 35 | get { 36 | return self.zhf_color(withHex: 0x666666) 37 | } 38 | } 39 | open class var zhfe8_backGroundColor: UIColor { 40 | get { 41 | return self.zhf_color(withHex: 0xe8e8e8) 42 | } 43 | } 44 | open class var zhff9_backGroundColor: UIColor { 45 | get { 46 | return self.zhf_color(withHex: 0xf9f9f9) 47 | } 48 | } 49 | open class var zhfcc_lineColor: UIColor { 50 | get { 51 | return self.zhf_color(withHex: 0xcccccc) 52 | } 53 | } 54 | //分割线的颜色 55 | open class var zhf_lineColor: UIColor { 56 | get { 57 | return self.zhf_color(withHex: 0xebf0f5) 58 | } 59 | } 60 | 61 | /// 随机色 62 | /// 63 | /// - Returns: 随机的颜色 64 | class func zhf_randomColor() -> UIColor { 65 | 66 | let r = CGFloat(arc4random() % 256) / 255.0 67 | let g = CGFloat(arc4random() % 256) / 255.0 68 | let b = CGFloat(arc4random() % 256) / 255.0 69 | 70 | return UIColor(red: r, green: g, blue: b, alpha: 1.0) 71 | } 72 | 73 | /// 十六进制颜色 74 | /// 75 | /// - Parameter withHex: 0xFFFFFF 76 | /// - Returns: color 77 | class func zhf_color(withHex: UInt32) -> UIColor { 78 | 79 | let r = ((CGFloat)((withHex & 0xFF0000) >> 16)) / 255.0 80 | let g = ((CGFloat)((withHex & 0xFF00) >> 8)) / 255.0 81 | let b = ((CGFloat)(withHex & 0xFF)) / 255.0 82 | 83 | return UIColor(red: r, green: g, blue: b, alpha: 1.0) 84 | } 85 | 86 | class func zhf_colorAlpha(withHex: UInt32,alpha: CGFloat) -> UIColor { 87 | 88 | let r = ((CGFloat)((withHex & 0xFF0000) >> 16)) / 255.0 89 | let g = ((CGFloat)((withHex & 0xFF00) >> 8)) / 255.0 90 | let b = ((CGFloat)(withHex & 0xFF)) / 255.0 91 | 92 | return UIColor(red: r, green: g, blue: b, alpha: alpha) 93 | } 94 | 95 | /// 0~255 颜色 96 | /// 97 | /// - Parameters: 98 | /// - withRed: red(0~255) 99 | /// - green: green(0~255) 100 | /// - blue: blue(0~255) 101 | /// - Returns: color 102 | class func zhf_color(withRed: UInt8, green: UInt8, blue: UInt8) -> UIColor { 103 | 104 | let r = CGFloat(withRed) / 255.0 105 | let g = CGFloat(green) / 255.0 106 | let b = CGFloat(blue) / 255.0 107 | 108 | return UIColor(red: r, green: g, blue: b, alpha: 1.0) 109 | } 110 | class func initString(hex: String) -> UIColor { 111 | let scanner = Scanner(string: hex) 112 | scanner.scanLocation = 0 113 | var rgbValue: UInt64 = 0 114 | scanner.scanHexInt64(&rgbValue) 115 | let r = ((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255.0 116 | let g = ((CGFloat)((rgbValue & 0xFF00) >> 8)) / 255.0 117 | let b = ((CGFloat)(rgbValue & 0xFF)) / 255.0 118 | return UIColor(red: r, green: g, blue: b, alpha: 1.0) 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /ZHFToolBoxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ZHFToolBoxTests/ZHFToolBoxTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZHFToolBoxTests.swift 3 | // ZHFToolBoxTests 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import ZHFToolBox 11 | 12 | class ZHFToolBoxTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /ZHFToolBoxUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ZHFToolBoxUITests/ZHFToolBoxUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZHFToolBoxUITests.swift 3 | // ZHFToolBoxUITests 4 | // 5 | // Created by 张海峰 on 2018/5/9. 6 | // Copyright © 2018年 张海峰. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class ZHFToolBoxUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------