├── README.md ├── Swift-Animations.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── YouXianMing.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── YouXianMing1987@iCloud.com.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── YouXianMing.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── Swift-Animations.xcscheme │ │ └── xcschememanagement.plist │ └── YouXianMing1987@iCloud.com.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── Swift-Animations.xcscheme │ └── xcschememanagement.plist └── Swift-Animations ├── AlertView.swift ├── AlertViewCollectionViewCell.swift ├── AlertViewController.swift ├── AnimationsListViewController.swift ├── AppDelegate.swift ├── AppleSystemService.swift ├── Assets.xcassets ├── AppIcon.appiconset │ ├── App_Store_iOS_1024pt.png │ ├── Contents.json │ ├── iPhone_App_iOS_7-11_60pt@2x.png │ ├── iPhone_App_iOS_7-11_60pt@3x.png │ ├── iPhone_Notification_iOS_7-11_20pt@2x.png │ ├── iPhone_Notification_iOS_7-11_20pt@3x.png │ ├── iPhone_Settings_iOS_5-11_29pt@2x.png │ ├── iPhone_Settings_iOS_5-11_29pt@3x.png │ ├── iPhone_Spotlight_iOS_7-11_40pt@2x.png │ └── iPhone_Spotlight_iOS_7-11_40pt@3x.png ├── Brand Assets.launchimage │ ├── 1242x2208.png │ ├── 640x1136.png │ ├── 640x960.png │ ├── 750x1334.png │ ├── Contents.json │ └── iPhoneX_bg@3x.png ├── Contents.json ├── 菜单图片 │ ├── Contents.json │ ├── arrows_next.imageset │ │ ├── Contents.json │ │ └── arrows_next.png │ ├── backIcon.imageset │ │ ├── Contents.json │ │ └── NodeModelViewControllerBack_black@3x.png │ ├── backIconTypeTwo.imageset │ │ ├── Contents.json │ │ └── NodeModelViewControllerBack_black_typeTwo@3x.png │ ├── backIconTypeTwo_pre.imageset │ │ ├── Contents.json │ │ └── NodeModelViewControllerBack_black_typeTwo_pre@3x.png │ └── backIcon_pre.imageset │ │ ├── Contents.json │ │ └── NodeModelViewControllerBack_black_pre@3x.png └── 项目图片 │ ├── 1.imageset │ ├── 1.jpg │ └── Contents.json │ ├── 2.imageset │ ├── 2.jpg │ └── Contents.json │ ├── 3.imageset │ ├── 3.jpg │ └── Contents.json │ ├── 4.imageset │ ├── 4.jpg │ └── Contents.json │ ├── 5.imageset │ ├── 5.jpg │ └── Contents.json │ ├── Contents.json │ ├── colors.imageset │ ├── Contents.json │ └── colors@2x.png │ ├── pic_1.imageset │ ├── Contents.json │ └── pic_1@2x.png │ ├── pic_2.imageset │ ├── Contents.json │ └── pic_2@2x.png │ ├── pic_3.imageset │ ├── Contents.json │ └── pic_3@2x.png │ ├── pic_4.imageset │ ├── Contents.json │ └── pic_4@2x.png │ └── plane.imageset │ ├── Contents.json │ └── plane.png ├── BackgroundLineView.swift ├── BaseCustomNavigationController.swift ├── BaseCustomViewController.swift ├── BaseMessageView.swift ├── CATransform3DM34Controller.swift ├── CellDataAdapter.swift ├── CircleAnimationViewController.swift ├── CircleView.swift ├── ClassHeaderView.swift ├── ClassModel.swift ├── ComplexEasingValue.swift ├── ControllerBaseViewConfig.swift ├── ControllerItem.swift ├── CountDownTimeCell.swift ├── CountDownTimerController.swift ├── CustomCell.swift ├── CustomCollectionViewCell.swift ├── CustomHeaderFooterView.swift ├── DefaultNotificationCenter.swift ├── Easing.swift ├── EasingValue.swift ├── FontCell.swift ├── FontFamilyHeaderView.swift ├── FontFamilyModel.swift ├── FullTitleVisualEffectViewController.swift ├── GCDGroup.swift ├── GCDQueue.swift ├── GCDQueuePriority.swift ├── GCDSemaphore.swift ├── GCDTimer.swift ├── HeaderViewTapAnimationController.swift ├── Info.plist ├── ListItemCell.swift ├── LiveImageView.swift ├── LiveImageViewController.swift ├── Math.swift ├── MessageView.swift ├── MixedColorProgressViewController.swift ├── MoreInfoView.swift ├── NormalTitleViewController.swift ├── NotificationEvent.swift ├── PageFlipEffectController.swift ├── RootNavigationViewController.swift ├── RotateView.swift ├── ScrollImageViewController.swift ├── ShowLoadingView.swift ├── ShowTextCell.swift ├── ShowTextModel.swift ├── StoredValueTypeIs.swift ├── String+StringHeight.swift ├── StudentInfoCell.swift ├── StudentModel.swift ├── SystemFontInfoController.swift ├── TableViewTapAnimationCell.swift ├── TableViewTapAnimationController.swift ├── TapAnimationModel.swift ├── TapCellAnimationController.swift ├── TimeModel.swift ├── TranformFadeView.swift ├── TransformFadeViewController.swift ├── UIColor+Convenience.swift ├── UIColor+HexColor.swift ├── UIFont+extension.swift ├── UILabel+SizeToFit.swift ├── UIView+AnimationProperty.swift ├── UIView+CreateFrame.swift ├── UIView+Glow.swift ├── UIView+ScreensShot.swift ├── UIView+SetRect.swift └── UIWindow+keyWindow.swift /README.md: -------------------------------------------------------------------------------- 1 | # Swift-Animations 2 | 3 | Support Swift 3 4 | 5 | > Project [YoCelsius](https://github.com/YouXianMing/YoCelsius) in [AppStore](https://itunes.apple.com/us/app/yocelsius/id967721892?l=zh&ls=1&mt=8) 6 | 7 | ![oneAnimations.gif](http://images.cnitblog.com/blog2015/607542/201504/211608037347783.gif) ![twoAnimations.gif](http://images.cnitblog.com/blog2015/607542/201504/211608153124546.gif) 8 | 9 | > Project [Animations](https://github.com/YouXianMing/Animations) 10 | 11 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201604/607542-20160419090223820-1448725903.gif) 12 | 13 | ## The Swift Animation Collection (Long-term Updates) . 14 | 15 | > TableViewTapAnimationController 16 | 17 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160807105426965-81586755.gif) 18 | 19 | > HeaderViewTapAnimationController 20 | 21 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160809234008496-1397243204.gif) 22 | 23 | > CircleAnimationViewController 24 | 25 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160816221026062-1763963823.gif) 26 | 27 | > LiveImageViewController 28 | 29 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160817221622078-423278683.gif) 30 | 31 | > ScrollImageViewController 32 | 33 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160818223221953-1452409372.gif) 34 | 35 | > CATransform3DM34Controller 36 | 37 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160819135653140-1119271580.gif) 38 | 39 | > TransformFadeViewController 40 | 41 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160821151851980-77360350.gif) 42 | 43 | > MixedColorProgressViewController 44 | 45 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160821204937167-1897716495.gif) 46 | 47 | > PageFlipEffectController 48 | 49 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201608/607542-20160822142825151-534854387.gif) 50 | 51 | > TapCellAnimationController 52 | 53 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201609/607542-20160901180633574-730564160.gif) 54 | 55 | > CountDownTimerController 56 | 57 | ![demo.gif](http://images2015.cnblogs.com/blog/607542/201609/607542-20160904171759124-116858550.gif) 58 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/project.xcworkspace/xcuserdata/YouXianMing.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations.xcodeproj/project.xcworkspace/xcuserdata/YouXianMing.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/project.xcworkspace/xcuserdata/YouXianMing1987@iCloud.com.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations.xcodeproj/project.xcworkspace/xcuserdata/YouXianMing1987@iCloud.com.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/xcuserdata/YouXianMing.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/xcuserdata/YouXianMing.xcuserdatad/xcschemes/Swift-Animations.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/xcuserdata/YouXianMing.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Swift-Animations.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | C57007EF1D5330B2003BFB5E 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/xcuserdata/YouXianMing1987@iCloud.com.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/xcuserdata/YouXianMing1987@iCloud.com.xcuserdatad/xcschemes/Swift-Animations.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Swift-Animations.xcodeproj/xcuserdata/YouXianMing1987@iCloud.com.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Swift-Animations.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | C57007EF1D5330B2003BFB5E 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Swift-Animations/AlertViewCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertViewCollectionViewCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/13. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AlertViewCollectionViewCell: CustomCollectionViewCell { 12 | 13 | fileprivate var rightLineView : UIView! 14 | fileprivate var labelContentView : UIView! 15 | fileprivate var label : UILabel! 16 | fileprivate var highlightLabel : UILabel! 17 | 18 | override func buildSubview() { 19 | 20 | self.addSubview(UIView.CreateLine(CGRect.init(x: 0, y: height - 0.5, width: width, height: 0.5), lineColor: UIColor.gray.alpha(0.2))) 21 | 22 | rightLineView = UIView.CreateLine(CGRect.init(x: width - 0.5, y: 0, width: 0.5, height: height), lineColor: UIColor.gray.alpha(0.2)) 23 | rightLineView.isHidden = true 24 | self.addSubview(rightLineView!) 25 | 26 | labelContentView = UIView.init(frame: self.bounds) 27 | self.addSubview(labelContentView) 28 | 29 | label = UILabel.init(frame : self.bounds) 30 | label.textAlignment = .center 31 | label.font = UIFont.HeitiSC(15) 32 | label.textColor = UIColor.black 33 | label.angle = CGFloat(Double.pi / 4) 34 | labelContentView.addSubview(label) 35 | 36 | highlightLabel = UILabel.init(frame : self.bounds) 37 | highlightLabel.textAlignment = .center 38 | highlightLabel.font = UIFont.HeitiSC(15) 39 | highlightLabel.textColor = UIColor.red 40 | highlightLabel.angle = CGFloat(Double.pi / 4) 41 | highlightLabel.alpha = 0 42 | labelContentView.addSubview(highlightLabel) 43 | } 44 | 45 | override func loadContent() { 46 | 47 | rightLineView.isHidden = ((indexPath?.row)! % 2 == 0 ? false : true) 48 | 49 | label.text = data as? String 50 | highlightLabel.text = data as? String 51 | } 52 | 53 | override func selectedEvent() { 54 | 55 | delegate?.customCollectionViewCell(self, event: data) 56 | } 57 | 58 | override var isHighlighted: Bool { 59 | 60 | get { return super.isHighlighted} 61 | set(newVal) { 62 | 63 | super.isHighlighted = newVal 64 | 65 | UIView.animate(withDuration: 0.25, delay: 0, options: .beginFromCurrentState, animations: { 66 | 67 | self.backgroundColor = (newVal ? UIColor.lightGray.alpha(0.1) : UIColor.white) 68 | self.label.alpha = (newVal ? 0 : 1) 69 | self.highlightLabel.alpha = (newVal ? 1 : 0) 70 | self.labelContentView.scale = (newVal ? 0.95 : 1) 71 | 72 | }, completion: nil) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Swift-Animations/AlertViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlertViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/13. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AlertViewController: NormalTitleViewController, UICollectionViewDelegate, UICollectionViewDataSource, CustomCollectionViewCellDelegate, BaseMessageViewDelegate { 12 | 13 | fileprivate var collectionView : UICollectionView! 14 | fileprivate var layout : UICollectionViewFlowLayout! 15 | fileprivate var adapters : [CellDataAdapter] = [] 16 | 17 | override func viewDidLoad() { 18 | 19 | super.viewDidLoad() 20 | 21 | // Layout. 22 | layout = UICollectionViewFlowLayout.init() 23 | layout.minimumLineSpacing = 0 24 | layout.minimumInteritemSpacing = 0 25 | layout.itemSize = CGSize.init(width: Screen.Width / 2, height: Screen.Width / 2) 26 | 27 | // CollectionView. 28 | collectionView = UICollectionView.init(frame: (contentView?.bounds)!, collectionViewLayout: layout!) 29 | collectionView.backgroundColor = UIColor.clear 30 | collectionView.delegate = self 31 | collectionView.dataSource = self 32 | contentView?.addSubview(collectionView!) 33 | AlertViewCollectionViewCell.RegisterTo(collectionView!) 34 | 35 | if #available(iOS 11.0, *) { 36 | 37 | collectionView?.contentInsetAdjustmentBehavior = .never 38 | } 39 | 40 | // Adapters. 41 | adapters.append(AlertViewCollectionViewCell.Adapter(data: "MessageView" as AnyObject)) 42 | adapters.append(AlertViewCollectionViewCell.Adapter(data: "AlertView" as AnyObject)) 43 | } 44 | 45 | // MARK: UICollectionViewDelegate, UICollectionViewDataSource 46 | 47 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 48 | 49 | return adapters.count 50 | } 51 | 52 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 53 | 54 | return collectionView.dequeueCellAndLoadContentFromAdapter(adapters[indexPath.row], indexPath: indexPath, delegate: self) 55 | } 56 | 57 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 58 | 59 | collectionView.selectedEventWithIndexPath(indexPath) 60 | } 61 | 62 | // MARK: CustomCollectionViewCellDelegate 63 | 64 | func customCollectionViewCell(_ cell: CustomCollectionViewCell?, event: Any?) { 65 | 66 | if event is String { 67 | 68 | let name = event as! String 69 | 70 | if name == "MessageView" { 71 | 72 | MessageView.Setup(messageObject : "If you find this post helpful, please recommend it for others to read." as AnyObject, 73 | contentView : UIWindow.getKeyWindow(), 74 | delegate : self).show() 75 | 76 | } else if name == "AlertView" { 77 | 78 | let messageObject = AlertViewMessageObject.init(title : "警告", 79 | content : "不要轻信陌生电话,短信;不要轻易点击信息中的链接;不要按陌生电话,短信要求转账汇款;不要安装不了解的软件.", 80 | buttonTitles : ["关闭", "更多信息"], 81 | buttonTitlesState : [AlertViewButtonType.Black, AlertViewButtonType.Red]) 82 | 83 | AlertView.Setup(messageObject : messageObject as AnyObject, 84 | contentView : UIWindow.getKeyWindow(), 85 | delegate : self, 86 | autoHiden : false).show() 87 | } 88 | } 89 | } 90 | 91 | // MARK: BaseMessageViewDelegate 92 | 93 | func baseMessageView(_ messageView : BaseMessageView, event : AnyObject?) { 94 | 95 | if messageView.isKind(of: AlertView.classForCoder()) { 96 | 97 | print(event ?? "None") 98 | } 99 | } 100 | 101 | func baseMessageViewWillAppear(_ messageView : BaseMessageView) { 102 | 103 | print("baseMessageViewWillAppear") 104 | } 105 | 106 | func baseMessageViewDidAppear(_ messageView : BaseMessageView) { 107 | 108 | print("baseMessageViewDidAppear") 109 | } 110 | 111 | func baseMessageViewWillDisappear(_ messageView : BaseMessageView) { 112 | 113 | print("baseMessageViewWillDisappear") 114 | } 115 | 116 | func baseMessageViewDidDisappear(_ messageView : BaseMessageView) { 117 | 118 | print("baseMessageViewDidDisappear") 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Swift-Animations/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/4. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window : UIWindow? 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | 19 | /* 20 | Lateast no warning version : Xcode 9.4.1 (9F2000) 21 | */ 22 | 23 | window = UIWindow(frame: UIScreen.main.bounds) 24 | 25 | if let window = window { 26 | 27 | window.backgroundColor = UIColor.white 28 | let controller = AnimationsListViewController() 29 | let rootViewController = RootNavigationViewController(rootViewController: controller, hideNavBar: true) 30 | window.rootViewController = rootViewController 31 | window.makeKeyAndVisible() 32 | } 33 | 34 | return true 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Swift-Animations/AppleSystemService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppleSystemService.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/11. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AppleSystemService : NSObject { 12 | 13 | /// Get the lauch image. 14 | class var LaunchImage : UIImage { 15 | 16 | get { 17 | 18 | var lauchImage : UIImage! 19 | var viewOrientation : String! 20 | let viewSize = UIScreen.main.bounds.size 21 | let orientation = UIApplication.shared.statusBarOrientation 22 | 23 | if orientation == .landscapeLeft || orientation == .landscapeRight { 24 | 25 | viewOrientation = "Landscape" 26 | 27 | } else { 28 | 29 | viewOrientation = "Portrait" 30 | } 31 | 32 | let imagesInfoArray = Bundle.main.infoDictionary!["UILaunchImages"] 33 | for dict : Dictionary in imagesInfoArray as! Array { 34 | 35 | let imageSize = NSCoder.cgSize(for: dict["UILaunchImageSize"]!) 36 | if imageSize.equalTo(viewSize) && viewOrientation == dict["UILaunchImageOrientation"]! as String { 37 | 38 | lauchImage = UIImage(named: dict["UILaunchImageName"]!) 39 | } 40 | } 41 | 42 | return lauchImage 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/App_Store_iOS_1024pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/App_Store_iOS_1024pt.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "iPhone_Notification_iOS_7-11_20pt@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "iPhone_Notification_iOS_7-11_20pt@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "iPhone_Settings_iOS_5-11_29pt@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "iPhone_Settings_iOS_5-11_29pt@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "iPhone_Spotlight_iOS_7-11_40pt@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "iPhone_Spotlight_iOS_7-11_40pt@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "iPhone_App_iOS_7-11_60pt@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "iPhone_App_iOS_7-11_60pt@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "1024x1024", 53 | "idiom" : "ios-marketing", 54 | "filename" : "App_Store_iOS_1024pt.png", 55 | "scale" : "1x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_App_iOS_7-11_60pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_App_iOS_7-11_60pt@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_App_iOS_7-11_60pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_App_iOS_7-11_60pt@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Notification_iOS_7-11_20pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Notification_iOS_7-11_20pt@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Notification_iOS_7-11_20pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Notification_iOS_7-11_20pt@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Settings_iOS_5-11_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Settings_iOS_5-11_29pt@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Settings_iOS_5-11_29pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Settings_iOS_5-11_29pt@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Spotlight_iOS_7-11_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Spotlight_iOS_7-11_40pt@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Spotlight_iOS_7-11_40pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/AppIcon.appiconset/iPhone_Spotlight_iOS_7-11_40pt@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Brand Assets.launchimage/1242x2208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/Brand Assets.launchimage/1242x2208.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Brand Assets.launchimage/640x1136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/Brand Assets.launchimage/640x1136.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Brand Assets.launchimage/640x960.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/Brand Assets.launchimage/640x960.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Brand Assets.launchimage/750x1334.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/Brand Assets.launchimage/750x1334.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Brand Assets.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "2436h", 7 | "filename" : "iPhoneX_bg@3x.png", 8 | "minimum-system-version" : "11.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "extent" : "full-screen", 14 | "idiom" : "iphone", 15 | "subtype" : "736h", 16 | "filename" : "1242x2208.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "portrait", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "extent" : "full-screen", 23 | "idiom" : "iphone", 24 | "subtype" : "667h", 25 | "filename" : "750x1334.png", 26 | "minimum-system-version" : "8.0", 27 | "orientation" : "portrait", 28 | "scale" : "2x" 29 | }, 30 | { 31 | "orientation" : "portrait", 32 | "idiom" : "iphone", 33 | "filename" : "640x960.png", 34 | "extent" : "full-screen", 35 | "minimum-system-version" : "7.0", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "extent" : "full-screen", 40 | "idiom" : "iphone", 41 | "subtype" : "retina4", 42 | "filename" : "640x1136.png", 43 | "minimum-system-version" : "7.0", 44 | "orientation" : "portrait", 45 | "scale" : "2x" 46 | } 47 | ], 48 | "info" : { 49 | "version" : 1, 50 | "author" : "xcode" 51 | } 52 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Brand Assets.launchimage/iPhoneX_bg@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/Brand Assets.launchimage/iPhoneX_bg@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/arrows_next.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "arrows_next.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/arrows_next.imageset/arrows_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/菜单图片/arrows_next.imageset/arrows_next.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "NodeModelViewControllerBack_black@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIcon.imageset/NodeModelViewControllerBack_black@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/菜单图片/backIcon.imageset/NodeModelViewControllerBack_black@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIconTypeTwo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "NodeModelViewControllerBack_black_typeTwo@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIconTypeTwo.imageset/NodeModelViewControllerBack_black_typeTwo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/菜单图片/backIconTypeTwo.imageset/NodeModelViewControllerBack_black_typeTwo@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIconTypeTwo_pre.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "NodeModelViewControllerBack_black_typeTwo_pre@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIconTypeTwo_pre.imageset/NodeModelViewControllerBack_black_typeTwo_pre@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/菜单图片/backIconTypeTwo_pre.imageset/NodeModelViewControllerBack_black_typeTwo_pre@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIcon_pre.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "NodeModelViewControllerBack_black_pre@3x.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/菜单图片/backIcon_pre.imageset/NodeModelViewControllerBack_black_pre@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/菜单图片/backIcon_pre.imageset/NodeModelViewControllerBack_black_pre@3x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/1.imageset/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/1.imageset/1.jpg -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "1.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/2.imageset/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/2.imageset/2.jpg -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "2.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/3.imageset/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/3.imageset/3.jpg -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "3.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/4.imageset/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/4.imageset/4.jpg -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "4.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/5.imageset/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/5.imageset/5.jpg -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "5.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/colors.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "colors@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/colors.imageset/colors@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/colors.imageset/colors@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pic_1@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_1.imageset/pic_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/pic_1.imageset/pic_1@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pic_2@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_2.imageset/pic_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/pic_2.imageset/pic_2@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pic_3@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_3.imageset/pic_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/pic_3.imageset/pic_3@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pic_4@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/pic_4.imageset/pic_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/pic_4.imageset/pic_4@2x.png -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/plane.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "plane.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 | } -------------------------------------------------------------------------------- /Swift-Animations/Assets.xcassets/项目图片/plane.imageset/plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouXianMing/Swift-Animations/b793f1224dd5d5a01ddfb3fe9cfa24a93212fa6d/Swift-Animations/Assets.xcassets/项目图片/plane.imageset/plane.png -------------------------------------------------------------------------------- /Swift-Animations/BackgroundLineView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundLineView.swift 3 | // LineBackgroundView 4 | // 5 | // Created by YouXianMing on 16/8/14. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: Public class : BackgroundLineView 12 | 13 | class BackgroundLineView: UIView { 14 | 15 | // MARK: Properties. 16 | 17 | /// Line width, default is 5. 18 | var lineWidth : CGFloat { 19 | 20 | get {return backgroundView.lineWidth} 21 | 22 | set(newVal) { 23 | 24 | backgroundView.lineWidth = newVal 25 | backgroundView.setNeedsDisplay() 26 | } 27 | } 28 | 29 | /// Line gap, default is 3. 30 | var lineGap : CGFloat { 31 | 32 | get {return backgroundView.lineGap} 33 | 34 | set(newVal) { 35 | 36 | backgroundView.lineGap = newVal 37 | backgroundView.setNeedsDisplay() 38 | } 39 | } 40 | 41 | /// Line color, default is grayColor. 42 | var lineColor : UIColor { 43 | 44 | get {return backgroundView.lineColor} 45 | 46 | set(newVal) { 47 | 48 | backgroundView.lineColor = newVal 49 | backgroundView.setNeedsDisplay() 50 | } 51 | } 52 | 53 | /// Rotate value, default is 0. 54 | var rotate : CGFloat { 55 | 56 | get {return backgroundView.rotate} 57 | 58 | set(newVal) { 59 | 60 | backgroundView.rotate = newVal 61 | backgroundView.setNeedsDisplay() 62 | } 63 | } 64 | 65 | convenience init(frame: CGRect, lineWidth : CGFloat, lineGap : CGFloat, lineColor : UIColor, rotate : CGFloat) { 66 | 67 | self.init(frame : frame) 68 | self.lineWidth = lineWidth 69 | self.lineGap = lineGap 70 | self.lineColor = lineColor 71 | self.rotate = rotate 72 | } 73 | 74 | // MARK: Override system method. 75 | 76 | override func layoutSubviews() { 77 | 78 | super.layoutSubviews() 79 | setupBackgroundView() 80 | } 81 | 82 | override init(frame: CGRect) { 83 | 84 | super.init(frame: frame) 85 | 86 | self.layer.masksToBounds = true 87 | self.addSubview(backgroundView) 88 | } 89 | 90 | required init?(coder aDecoder: NSCoder) { 91 | 92 | fatalError("init(coder:) has not been implemented") 93 | } 94 | 95 | // MARK: Private value & func. 96 | 97 | fileprivate let backgroundView = LineBackground(length: 0) 98 | 99 | fileprivate func setupBackgroundView() { 100 | 101 | let drawLength = sqrt(self.bounds.size.width * self.bounds.size.width + self.bounds.size.height * self.bounds.size.height) 102 | backgroundView.frame = CGRect(x: 0, y: 0, width: drawLength, height: drawLength) 103 | backgroundView.center = CGPoint(x: self.bounds.size.width / 2.0, y: self.bounds.size.height / 2.0) 104 | backgroundView.setNeedsDisplay() 105 | } 106 | } 107 | 108 | // MARK: Private class : LineBackground 109 | 110 | private class LineBackground : UIView { 111 | 112 | fileprivate var rotate : CGFloat = 0 113 | fileprivate var lineWidth : CGFloat = 5 114 | fileprivate var lineGap : CGFloat = 3 115 | fileprivate var lineColor : UIColor = UIColor.gray 116 | 117 | override init(frame: CGRect) { 118 | 119 | super.init(frame: frame) 120 | self.backgroundColor = UIColor.clear 121 | } 122 | 123 | required init?(coder aDecoder: NSCoder) { 124 | 125 | fatalError("init(coder:) has not been implemented") 126 | } 127 | 128 | convenience init(length : CGFloat) { 129 | 130 | self.init(frame : CGRect(x: 0, y: 0, width: length, height: length)) 131 | } 132 | 133 | override func draw(_ rect: CGRect) { 134 | 135 | super.draw(rect) 136 | 137 | guard self.bounds.size.width > 0 && self.bounds.size.height > 0 else { 138 | 139 | return 140 | } 141 | 142 | let context = UIGraphicsGetCurrentContext() 143 | let width = self.bounds.size.width 144 | let height = self.bounds.size.height 145 | let drawLength = sqrt(width * width + height * height) 146 | let outerX = (drawLength - width) / 2.0 147 | let outerY = (drawLength - height) / 2.0 148 | let tmpLineWidth = lineWidth <= 0 ? 5 : lineWidth 149 | let tmpLineGap = lineGap <= 0 ? 3 : lineGap 150 | 151 | var red : CGFloat = 0 152 | var green : CGFloat = 0 153 | var blue : CGFloat = 0 154 | var alpha : CGFloat = 0 155 | 156 | context?.translateBy(x: 0.5 * drawLength, y: 0.5 * drawLength) 157 | context?.rotate(by: rotate) 158 | context?.translateBy(x: -0.5 * drawLength, y: -0.5 * drawLength) 159 | 160 | lineColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha) 161 | context?.setFillColor(red: red, green: green, blue: blue, alpha: alpha) 162 | 163 | var currentX = -outerX 164 | 165 | while currentX < drawLength { 166 | 167 | context?.addRect(CGRect(x: currentX, y: -outerY, width: tmpLineWidth, height: drawLength)) 168 | currentX += tmpLineWidth + tmpLineGap 169 | } 170 | 171 | context?.fillPath() 172 | } 173 | } 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Swift-Animations/BaseCustomNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseCustomNavigationController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/6/29. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseCustomNavigationController: UINavigationController { 12 | 13 | /// Init with rootViewController. 14 | /// 15 | /// - Parameters: 16 | /// - rootViewController: An UIViewController used as rootViewController. 17 | /// - hideTabBar: Navigation bar hide or not. 18 | convenience init(rootViewController: BaseCustomViewController, hideNavBar : Bool) { 19 | 20 | self.init(rootViewController : rootViewController) 21 | rootViewController.useInteractivePopGestureRecognizer() 22 | setNavigationBarHidden(hideNavBar, animated: false) 23 | } 24 | 25 | // MARK: -- System method && Debug message -- 26 | 27 | deinit { 28 | 29 | print("[❌] '[NAV] " + String(describing: self.classForCoder) + "' is released.") 30 | } 31 | 32 | override func viewDidAppear(_ animated: Bool) { 33 | 34 | super.viewDidAppear(animated) 35 | print("[➡️] enter to --> '[NAV] " + String(describing: self.classForCoder) + "'.") 36 | } 37 | 38 | override func viewDidDisappear(_ animated: Bool) { 39 | 40 | super.viewDidDisappear(animated) 41 | print("[🕒] leave from <-- '[NAV] " + String(describing: self.classForCoder) + "'.") 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Swift-Animations/BaseMessageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseMessageView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/13. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: protocol CustomCellDelegate 12 | 13 | protocol BaseMessageViewDelegate : class { 14 | 15 | func baseMessageView(_ messageView : BaseMessageView, event : AnyObject?) 16 | func baseMessageViewWillAppear(_ messageView : BaseMessageView) 17 | func baseMessageViewDidAppear(_ messageView : BaseMessageView) 18 | func baseMessageViewWillDisappear(_ messageView : BaseMessageView) 19 | func baseMessageViewDidDisappear(_ messageView : BaseMessageView) 20 | } 21 | 22 | class BaseMessageView: UIView { 23 | 24 | // MARK: Properties 25 | 26 | /// The delegate. 27 | weak var delegate : BaseMessageViewDelegate? 28 | 29 | /// The message object. 30 | var messageObject : AnyObject? 31 | 32 | /// The contentView. 33 | var contentView : UIView? { 34 | 35 | get { return private_ContentView} 36 | set(newVal) { 37 | 38 | self.frame = (newVal != nil ? (newVal?.bounds)! : CGRect.zero) 39 | private_ContentView = newVal 40 | } 41 | } 42 | private weak var private_ContentView : UIView? 43 | 44 | /// Auto hiden or not, default is YES. 45 | var autoHiden : Bool = true 46 | 47 | /// If The autoHiden is YES, you should set the delay hiden duration, default is 2.0. 48 | var delayAutoHidenDuration : TimeInterval { 49 | 50 | get { return private_DelayAutoHidenDuration} 51 | set(newVal) { 52 | 53 | private_DelayAutoHidenDuration = (newVal <= 0 ? 0 : newVal) 54 | } 55 | } 56 | private var private_DelayAutoHidenDuration : TimeInterval = 2.0 57 | 58 | // MARK: Init related. 59 | 60 | required override init(frame : CGRect) { 61 | 62 | super.init(frame: CGRect.zero) 63 | } 64 | 65 | required convenience init() { 66 | 67 | self.init(frame: CGRect.zero) 68 | } 69 | 70 | required init?(coder aDecoder: NSCoder) { 71 | 72 | fatalError("init(coder:) has not been implemented") 73 | } 74 | 75 | deinit { 76 | 77 | print(String(describing: self.classForCoder) + " is released.") 78 | } 79 | 80 | class func Setup(messageObject : AnyObject? = nil, 81 | contentView : UIView? = nil, 82 | delegate : BaseMessageViewDelegate? = nil, 83 | autoHiden : Bool = true, 84 | delayAutoHidenDuration : TimeInterval = 2.0) -> Self { 85 | 86 | let messageView = self.init(frame: CGRect.zero) 87 | 88 | messageView.messageObject = messageObject 89 | messageView.contentView = contentView 90 | messageView.delegate = delegate 91 | messageView.autoHiden = autoHiden 92 | messageView.delayAutoHidenDuration = delayAutoHidenDuration 93 | 94 | return messageView 95 | } 96 | 97 | // MARK: Useful methods. 98 | 99 | /// Show the MessageView. 100 | final func show() { 101 | 102 | if (self.contentView != nil) { 103 | 104 | self.contentView?.addSubview(self) 105 | setupSubViews() 106 | beginShowAnimation() 107 | 108 | if autoHiden { 109 | 110 | let dispatchTime = DispatchTime.now() + delayAutoHidenDuration 111 | DispatchQueue.main.asyncAfter( deadline: dispatchTime ) { 112 | 113 | self.hide() 114 | } 115 | } 116 | } 117 | } 118 | 119 | /// Hide the MessageView. 120 | final func hide() { 121 | 122 | beginHideAnimation() 123 | } 124 | 125 | // MARK: Overwrite by subClass. 126 | 127 | /// Begin show animation. 128 | func beginShowAnimation() { 129 | 130 | beforeStartShowValueConfig() 131 | delegate?.baseMessageViewWillAppear(self) 132 | UIView.animate(withDuration: 0.3, delay: 0, options: .beginFromCurrentState, animations: { 133 | 134 | self.startShowAnimated() 135 | 136 | }) { (success) in 137 | 138 | self.delegate?.baseMessageViewDidAppear(self) 139 | } 140 | } 141 | 142 | /// Begin hide animation. 143 | func beginHideAnimation() { 144 | 145 | delegate?.baseMessageViewWillDisappear(self) 146 | UIView.animate(withDuration: 0.3, delay: 0, options: .beginFromCurrentState, animations: { 147 | 148 | self.startHideAnimated() 149 | 150 | }) { (success) in 151 | 152 | self.afterHideShowValueConfig() 153 | self.delegate?.baseMessageViewDidDisappear(self) 154 | self.removeFromSuperview() 155 | } 156 | } 157 | 158 | /// Add subviews to self. 159 | func setupSubViews() { 160 | 161 | } 162 | 163 | /// Before start show animated, you can do sth value config. 164 | func beforeStartShowValueConfig() { 165 | 166 | } 167 | 168 | /// Start show animated. 169 | func startShowAnimated() { 170 | 171 | } 172 | 173 | /// Start hide animated. 174 | func startHideAnimated() { 175 | 176 | } 177 | 178 | /// After hide animation is complete, you can do sth value config. 179 | func afterHideShowValueConfig() { 180 | 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Swift-Animations/CATransform3DM34Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CATransform3DM34Controller.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/19. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CATransform3DM34Controller: NormalTitleViewController { 12 | 13 | fileprivate var timer : Timer! 14 | fileprivate var layer : CALayer! 15 | fileprivate var transformState : Bool = false 16 | 17 | override func viewDidLoad() { 18 | 19 | super.viewDidLoad() 20 | 21 | initLayer() 22 | 23 | // Init timer. 24 | timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(CATransform3DM34Controller.timerEvent), userInfo: nil, repeats: true) 25 | } 26 | 27 | fileprivate func initLayer() { 28 | 29 | let image = UIImage(named: "1") 30 | layer = CALayer() 31 | layer.frame = CGRect(x: 0, y: 0, width: image!.size.width / 2, height: image!.size.height / 2) 32 | layer.position = (contentView?.middlePoint)! 33 | layer.borderWidth = 4 34 | layer.borderColor = UIColor.black.cgColor 35 | layer.contents = image?.cgImage 36 | contentView?.layer.addSublayer(layer) 37 | } 38 | 39 | @objc func timerEvent() { 40 | 41 | if transformState == false { 42 | 43 | transformState = true 44 | transformStateEvent() 45 | 46 | } else { 47 | 48 | transformState = false 49 | normalStateEvent() 50 | } 51 | } 52 | 53 | fileprivate func transformStateEvent() { 54 | 55 | var perspectiveTransform = CATransform3DIdentity 56 | perspectiveTransform.m34 = -1.0 / 500.0 57 | perspectiveTransform = CATransform3DTranslate(perspectiveTransform, 30, -35, 0) 58 | perspectiveTransform = CATransform3DRotate(perspectiveTransform, Math.RadianFromDegree(30), 0.75, 1, -0.5) 59 | perspectiveTransform = CATransform3DScale(perspectiveTransform, 0.75, 0.75, 0.75) 60 | 61 | layer.transform = perspectiveTransform 62 | layer.allowsEdgeAntialiasing = true 63 | layer.speed = 0.5 64 | } 65 | 66 | fileprivate func normalStateEvent() { 67 | 68 | let perspectiveTransform = CATransform3DIdentity 69 | layer.transform = perspectiveTransform 70 | layer.speed = 0.5 71 | } 72 | 73 | override func viewDidDisappear(_ animated: Bool) { 74 | 75 | super.viewDidDisappear(animated) 76 | timer.invalidate() 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Swift-Animations/CellDataAdapter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CellDataAdapter.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/5. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CellDataAdapter: NSObject { 12 | 13 | // MARK: property 14 | 15 | /// Cell's reused identifier. 16 | var cellReuseIdentifier : String? 17 | 18 | /// Data, can be nil. 19 | var data : AnyObject? 20 | 21 | /// Cell's height, only used for UITableView's cell. 22 | var cellHeight : CGFloat? 23 | 24 | /// Cell's type (The same cell, but maybe have different types). 25 | var cellType : Int? 26 | 27 | // MARK: convenience init 28 | 29 | convenience init(cellReuseIdentifier: String?, data: AnyObject?, cellHeight: CGFloat?, cellType: Int?) { 30 | 31 | self.init() 32 | self.cellReuseIdentifier = cellReuseIdentifier 33 | self.data = data 34 | self.cellHeight = cellHeight 35 | self.cellType = cellType 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Swift-Animations/CircleAnimationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircleAnimationViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/16. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CircleAnimationViewController: NormalTitleViewController { 12 | 13 | fileprivate var circleView1 : CircleView! 14 | fileprivate var circleView2 : CircleView! 15 | fileprivate var circleView3 : CircleView! 16 | fileprivate var circleView4 : CircleView! 17 | fileprivate var timer : GCDTimer! 18 | 19 | override func viewDidLoad() { 20 | 21 | super.viewDidLoad() 22 | 23 | let gapFromTop : CGFloat = 64.0 + 20.0 24 | let width : CGFloat = Screen.Width 25 | let halfWidth : CGFloat = width / 2.0 26 | let radius : CGFloat = width / 3.0 + 20 27 | let bounds : CGRect = CGRect(x: 0, y: 0, width: radius, height: radius) 28 | 29 | let point1 = CGPoint(x: halfWidth / 2, y: gapFromTop + halfWidth / 2) 30 | let point2 = CGPoint(x: halfWidth / 2 + halfWidth, y: gapFromTop + halfWidth / 2) 31 | let point3 = CGPoint(x: halfWidth / 2, y: gapFromTop + halfWidth / 2 + halfWidth) 32 | let point4 = CGPoint(x: halfWidth / 2 + halfWidth, y: gapFromTop + halfWidth / 2 + halfWidth) 33 | 34 | circleView1 = CircleView(frame: bounds, lineWidth: 2, lineColor: UIColor.gray, clockWise: true, startDegree: 0) 35 | circleView1.center = point1 36 | contentView?.addSubview(circleView1) 37 | 38 | circleView2 = CircleView(frame: bounds, lineWidth: radius / 2, lineColor: UIColor.black, clockWise: true, startDegree: 0) 39 | circleView2.center = point2 40 | contentView?.addSubview(circleView2) 41 | 42 | circleView3 = CircleView(frame: bounds, lineWidth: 2, lineColor: UIColor.black, clockWise: true, startDegree: 0) 43 | circleView3.center = point3 44 | contentView?.addSubview(circleView3) 45 | 46 | circleView4 = CircleView(frame: bounds, lineWidth: radius / 2, lineColor: UIColor.black, clockWise: true, startDegree: 0) 47 | let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: radius, height: radius)) 48 | imageView.image = UIImage(named: "colors") 49 | imageView.center = point4 50 | imageView.layer.mask = self.circleView4.layer 51 | contentView?.addSubview(imageView) 52 | 53 | weak var weakSelf = self 54 | timer = GCDTimer(in: GCDQueue.Main, delay: 0.6, interval: 1.5) 55 | timer.setTimerEventHandler { _ in 56 | 57 | let percent = Double(arc4random() % 100) / 100.0 58 | let anotherPercent = Double(arc4random() % 100) / 100.0 59 | let smallPercent = (percent < anotherPercent ? percent : anotherPercent) 60 | let largePercent = (percent < anotherPercent ? anotherPercent : percent) 61 | 62 | weakSelf?.circleView1.strokeEnd(largePercent, easingFunction: .elasticEaseInOut, animated: true, duration: 1.0) 63 | weakSelf?.circleView2.strokeEnd(largePercent, easingFunction: .exponentialEaseInOut, animated: true, duration: 1.0) 64 | weakSelf?.circleView3.strokeStart(smallPercent, easingFunction: .exponentialEaseInOut, animated: true, duration: 1.0) 65 | weakSelf?.circleView3.strokeEnd(largePercent, easingFunction: .exponentialEaseInOut, animated: true, duration: 1.0) 66 | weakSelf?.circleView4.strokeEnd(largePercent, easingFunction: .exponentialEaseOut, animated: true, duration: 1.0) 67 | } 68 | 69 | timer.start() 70 | } 71 | 72 | override func viewDidDisappear(_ animated: Bool) { 73 | 74 | super.viewDidDisappear(animated) 75 | timer.destroy() 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Swift-Animations/ClassHeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ClassHeaderView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/9. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ClassHeaderView: CustomHeaderFooterView { 12 | 13 | fileprivate var normalClassNameLabel : UILabel! 14 | fileprivate var highClassNameLabel : UILabel! 15 | fileprivate var rotateView : RotateView! 16 | 17 | override func setupHeaderFooterView() { 18 | 19 | setHeaderFooterViewBackgroundColor(UIColor.white) 20 | } 21 | 22 | override func buildSubview() { 23 | 24 | let contentView = UIView.CreateLine(CGRect(x: 0, y: 2, width: Screen.Width, height: 26), lineColor: UIColor.gray.alpha(0.05)) 25 | self.addSubview(contentView) 26 | contentView.addSubview(UIView.CreateLine(CGRect(x: 0, y: 0, width: Screen.Width, height: 0.5), lineColor: UIColor.gray.alpha(0.25))) 27 | contentView.addSubview(UIView.CreateLine(CGRect(x: 0, y: 25.5, width: Screen.Width, height: 0.5), lineColor: UIColor.gray.alpha(0.25))) 28 | 29 | let button = UIButton(frame: CGRect(x: 0, y: 0, width: Screen.Width, height: 30)) 30 | button.addTarget(self, action: #selector(ClassHeaderView.buttonEvent), for: .touchUpInside) 31 | self.addSubview(button) 32 | 33 | normalClassNameLabel = UILabel(frame: CGRect(x: 10, y: 0, width: 100, height: 26)) 34 | normalClassNameLabel.font = UIFont.AppleSDGothicNeoThin(12) 35 | contentView.addSubview(normalClassNameLabel) 36 | 37 | highClassNameLabel = UILabel(frame: normalClassNameLabel.frame) 38 | highClassNameLabel.font = normalClassNameLabel.font 39 | highClassNameLabel.textColor = UIColor.red 40 | contentView.addSubview(highClassNameLabel) 41 | 42 | rotateView = RotateView(frame: CGRect(x: Screen.Width - 25, y: 5, width: 20, height: 20)) 43 | self.addSubview(rotateView) 44 | 45 | let arrowImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20 / 3.0, height: 36 / 3.0)) 46 | arrowImageView.image = UIImage(named: "arrows_next") 47 | arrowImageView.center = rotateView.middlePoint 48 | rotateView.addSubview(arrowImageView) 49 | } 50 | 51 | override func loadContent() { 52 | 53 | let model = data as! ClassModel 54 | 55 | normalClassNameLabel.text = model.className 56 | highClassNameLabel.text = model.className 57 | 58 | if model.expend == true { 59 | 60 | extendStateAnimated(false) 61 | 62 | } else { 63 | 64 | normalStateAnimated(false) 65 | } 66 | } 67 | 68 | @objc func buttonEvent() { 69 | 70 | let model = data as! ClassModel 71 | 72 | if model.expend == true { 73 | 74 | model.expend = false 75 | normalStateAnimated(true) 76 | 77 | var indexPaths = [IndexPath]() 78 | let index = model.students.count 79 | for i in 0 ..< index { 80 | 81 | indexPaths.append(IndexPath(item: i, section: section!)) 82 | } 83 | tableView?.deleteRows(at: indexPaths, with: .automatic) 84 | 85 | } else { 86 | 87 | model.expend = true 88 | extendStateAnimated(true) 89 | 90 | var indexPaths = [IndexPath]() 91 | let index = model.students.count 92 | for i in 0 ..< index { 93 | 94 | indexPaths.append(IndexPath(item: i, section: section!)) 95 | } 96 | tableView?.insertRows(at: indexPaths, with: .automatic) 97 | } 98 | } 99 | 100 | func normalStateAnimated(_ animated : Bool) { 101 | 102 | UIView.animate(withDuration: animated == true ? 0.5 : 0, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: .allowUserInteraction, animations: { 103 | 104 | self.normalClassNameLabel.alpha = 1; 105 | self.normalClassNameLabel.frame = CGRect(x: 10, y: 0, width: 100, height: 26); 106 | self.highClassNameLabel.alpha = 0; 107 | self.highClassNameLabel.frame = CGRect(x: 10, y: 0, width: 100, height: 26); 108 | 109 | }, completion: nil) 110 | 111 | rotateView.changeToUpAnimated(animated) 112 | } 113 | 114 | func extendStateAnimated(_ animated : Bool) { 115 | 116 | UIView.animate(withDuration: animated == true ? 0.5 : 0, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: .allowUserInteraction, animations: { 117 | 118 | self.normalClassNameLabel.alpha = 0; 119 | self.normalClassNameLabel.frame = CGRect(x: 10 + 10, y: 0, width: 100, height: 26); 120 | self.highClassNameLabel.alpha = 1; 121 | self.highClassNameLabel.frame = CGRect(x: 10 + 10, y: 0, width: 100, height: 26); 122 | 123 | }, completion: nil) 124 | 125 | rotateView.changeToRightAnimated(animated) 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Swift-Animations/ClassModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ClassModel.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/9. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ClassModel: NSObject { 12 | 13 | var className : String = "" 14 | var students : [StudentModel] = [StudentModel]() 15 | var expend : Bool = false 16 | 17 | convenience init(className : String) { 18 | 19 | self.init() 20 | self.className = className 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Swift-Animations/ComplexEasingValue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ComplexEasingValue.swift 3 | // Swift-EasingAnimation 4 | // 5 | // Created by YouXianMing on 15/10/21. 6 | // 7 | // https://github.com/YouXianMing 8 | // http://home.cnblogs.com/u/YouXianMing/ 9 | // 10 | 11 | import UIKit 12 | 13 | class ComplexEasingValue: EasingValue { 14 | 15 | /// 点A的动画函数(如果是 size,则点 A 表示 width;如果是 point,则点 A 表示 x) 16 | var easingA : EasingFunction! 17 | 18 | /// 点B的动画函数(如果是 size,则点 B 表示 height;如果是 point,则点 B 表示 y) 19 | var easingB : EasingFunction! 20 | 21 | // MARK: init 22 | override init() { 23 | 24 | super.init() 25 | 26 | easingA = EasingFunction.sineEaseIn 27 | easingB = EasingFunction.sineEaseIn 28 | frameCount = 60 29 | } 30 | 31 | init(withFunctionA : EasingFunction, FunctionB : EasingFunction, frameCount : size_t) { 32 | 33 | super.init() 34 | 35 | easingA = withFunctionA 36 | easingB = FunctionB 37 | self.frameCount = frameCount 38 | } 39 | 40 | /** 41 | 计算关键帧 42 | 43 | - parameter fromValue: 起始值 44 | - parameter toValue: 结束值 45 | 46 | - returns: 关键帧值数组 47 | */ 48 | override func pointValueWith(fromPoint : CGPoint, toPoint : CGPoint) -> [AnyObject] { 49 | 50 | let values = NSMutableArray(capacity: frameCount) 51 | 52 | var t : Double = 0.0 53 | let dt : Double = 1.0 / (Double(frameCount) - 1) 54 | 55 | for _ in 0 ..< frameCount { 56 | 57 | let x : Double = Double(fromPoint.x) + easingA.function(t) * (Double(toPoint.x) - Double(fromPoint.x)) 58 | let y : Double = Double(fromPoint.y) + easingB.function(t) * (Double(toPoint.y) - Double(fromPoint.y)) 59 | let point : CGPoint = CGPoint(x : x, y : y) 60 | values.add(NSValue(cgPoint: point)) 61 | 62 | t += dt 63 | } 64 | 65 | return values as [AnyObject] 66 | } 67 | 68 | /** 69 | 计算关键帧点 70 | 71 | - parameter fromPoint: 起始点 72 | - parameter toPoint: 结束点 73 | 74 | - returns: 关键帧点数组 75 | */ 76 | override func sizeValueWith(fromSize : CGSize, toSize : CGSize) -> [AnyObject] { 77 | 78 | let values = NSMutableArray(capacity: frameCount) 79 | 80 | var t : Double = 0.0 81 | let dt : Double = 1.0 / (Double(frameCount) - 1) 82 | 83 | for _ in 0 ..< frameCount { 84 | 85 | let width : Double = Double(fromSize.width) + easingA.function(t) * (Double(toSize.width) - Double(fromSize.width)) 86 | let height : Double = Double(fromSize.height) + easingB.function(t) * (Double(toSize.height) - Double(fromSize.height)) 87 | let size : CGSize = CGSize(width: width, height: height) 88 | values.add(NSValue(cgSize : size)) 89 | 90 | t += dt 91 | } 92 | 93 | return values as [AnyObject] 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Swift-Animations/ControllerBaseViewConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ControllerBaseViewConfig.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/6/29. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ControllerBaseViewConfig: NSObject { 12 | 13 | var backgroundColor : UIColor? 14 | var frame : CGRect? 15 | var exist : Bool = true 16 | } 17 | -------------------------------------------------------------------------------- /Swift-Animations/ControllerItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ControllerItem.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ControllerItem: NSObject { 12 | 13 | var controllerClass : AnyClass? 14 | var name : String? 15 | 16 | convenience init(controllerClass : AnyClass, name : String) { 17 | 18 | self.init() 19 | self.controllerClass = controllerClass 20 | self.name = name 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Swift-Animations/CountDownTimeCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CountDownTimeCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/9/4. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CountDownTimeCell: CustomCell, DefaultNotificationCenterDelegate { 12 | 13 | fileprivate var titleLabel : UILabel! 14 | fileprivate var countdownLabel : UILabel! 15 | fileprivate var notificationCenter : DefaultNotificationCenter = DefaultNotificationCenter() 16 | 17 | override func setupCell() { 18 | 19 | super.setupCell() 20 | notificationCenter.addNotificationName(NotificationEvent.countDownTimeCellCountDown.notificationName) 21 | notificationCenter.delegate = self 22 | } 23 | 24 | override func buildSubview() { 25 | 26 | titleLabel = UILabel(frame: CGRect(x: 15, y: 10, width: Screen.Width - 20, height: 40)) 27 | titleLabel.textColor = UIColor.gray 28 | titleLabel.font = UIFont.AvenirLight(20.0) 29 | addSubview(titleLabel) 30 | 31 | countdownLabel = UILabel(frame: CGRect(x: 10, y: 10, width: Screen.Width - 20, height: 40)) 32 | countdownLabel.textColor = UIColor.gray 33 | countdownLabel.font = UIFont.AvenirLight(15.0) 34 | countdownLabel.textAlignment = .right 35 | addSubview(countdownLabel) 36 | } 37 | 38 | override func loadContent() { 39 | 40 | if let model = dataAdapter?.data as? TimeModel { 41 | 42 | titleLabel.text = model.title 43 | countdownLabel.text = model.currentTimeString 44 | } 45 | } 46 | 47 | func defaultNotificationCenter(_ notificationName: String, object: AnyObject?) { 48 | 49 | if display == true && notificationName == NotificationEvent.countDownTimeCellCountDown.notificationName { 50 | 51 | loadContent() 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Swift-Animations/CountDownTimerController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CountDownTimerController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/9/4. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CountDownTimerController: NormalTitleViewController, UITableViewDelegate, UITableViewDataSource { 12 | 13 | fileprivate var timesArray : [CellDataAdapter] = [CellDataAdapter]() 14 | fileprivate var tableView : UITableView! 15 | fileprivate var timer : Timer! 16 | 17 | override func viewDidLoad() { 18 | 19 | super.viewDidLoad() 20 | 21 | func add(title : String, countdownTime : Int) { 22 | 23 | timesArray.append(CountDownTimeCell.Adapter(data: TimeModel(title: title, countdownTime: countdownTime))) 24 | } 25 | 26 | add(title: "YouXianMing", countdownTime: 20034) 27 | add(title: "Aaron", countdownTime: 31) 28 | add(title: "Nicholas", countdownTime: 1003) 29 | add(title: "Quentin", countdownTime: 394) 30 | add(title: "Samirah", countdownTime: 345345) 31 | add(title: "Serafina", countdownTime: 233) 32 | add(title: "Shanon", countdownTime: 4649) 33 | add(title: "Sophie", countdownTime: 3454) 34 | add(title: "Steven", countdownTime: 54524) 35 | add(title: "Saadiya", countdownTime: 235) 36 | 37 | // Create TableView. 38 | tableView = UITableView(frame: (contentView?.bounds)!) 39 | tableView.delegate = self 40 | tableView.dataSource = self 41 | tableView.separatorStyle = .none 42 | tableView.rowHeight = 60 43 | contentView?.addSubview(tableView) 44 | 45 | if #available(iOS 11.0, *) { 46 | 47 | tableView.contentInsetAdjustmentBehavior = .never 48 | } 49 | 50 | // Register cell. 51 | CountDownTimeCell.RegisterTo(tableView) 52 | 53 | // Init timer. 54 | timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(CountDownTimerController.timerEvent), userInfo: nil, repeats: true) 55 | } 56 | 57 | @objc func timerEvent() { 58 | 59 | for (_, dataAdapter) in timesArray.enumerated() { 60 | 61 | if let model = dataAdapter.data as? TimeModel { 62 | 63 | model.countDown() 64 | } 65 | } 66 | 67 | DefaultNotificationCenter.PostMessageTo(NotificationEvent.countDownTimeCellCountDown.notificationName) 68 | } 69 | 70 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 71 | 72 | return timesArray.count 73 | } 74 | 75 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 76 | 77 | return tableView.dequeueCellAndLoadContentFromAdapter(timesArray[(indexPath as NSIndexPath).row], indexPath: indexPath) 78 | } 79 | 80 | func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { 81 | 82 | (cell as! CustomCell).display = true 83 | } 84 | 85 | func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { 86 | 87 | (cell as! CustomCell).display = false 88 | } 89 | 90 | override func viewDidDisappear(_ animated: Bool) { 91 | 92 | super.viewDidDisappear(animated) 93 | timer.invalidate() 94 | } 95 | } 96 | 97 | 98 | -------------------------------------------------------------------------------- /Swift-Animations/CustomCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/6. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: extension UITableView 12 | 13 | extension UITableView { 14 | 15 | /** 16 | Dequeue and load content from adapter. 17 | 18 | - parameter adapter: The CellDataAdapter. 19 | - parameter indexPath: The indexPath. 20 | - parameter tableView: The TableView. 21 | - parameter delegate: The CustomCell's delegate. 22 | - parameter controller: The controller. 23 | 24 | - returns: The CustomCell instance. 25 | */ 26 | func dequeueCellAndLoadContentFromAdapter(_ adapter : CellDataAdapter, 27 | indexPath : IndexPath, 28 | tableView : UITableView? = nil, 29 | delegate : CustomCellDelegate? = nil, 30 | controller : UIViewController? = nil) -> CustomCell { 31 | 32 | let cell = self.dequeueReusableCell(withIdentifier: adapter.cellReuseIdentifier!) as! CustomCell 33 | cell.indexPath = indexPath 34 | cell.dataAdapter = adapter 35 | cell.data = adapter.data 36 | cell.tableView = tableView 37 | cell.delegate = delegate 38 | cell.controller = controller 39 | cell.loadContent() 40 | 41 | return cell 42 | } 43 | 44 | func selectedEventWithIndexPath(_ indexPath : IndexPath) { 45 | 46 | let cell = self.cellForRow(at: indexPath) as! CustomCell 47 | 48 | // Make sure the cell is kind of CustomCell. 49 | guard cell.isKind(of: CustomCell.classForCoder()) == true else { 50 | 51 | return 52 | } 53 | 54 | cell.selectedEvent() 55 | } 56 | } 57 | 58 | // MARK: protocol CustomCellDelegate 59 | 60 | protocol CustomCellDelegate : class { 61 | 62 | /** 63 | CustomCell's event. 64 | 65 | - parameter cell: CustomCell type class. 66 | - parameter event: Event data. 67 | */ 68 | func customCell(_ cell: CustomCell?, event: Any?) 69 | } 70 | 71 | // MARK: CustomCell 72 | 73 | class CustomCell: UITableViewCell { 74 | 75 | weak var delegate : CustomCellDelegate? 76 | weak var dataAdapter : CellDataAdapter? 77 | weak var data : AnyObject? 78 | var indexPath : IndexPath? 79 | weak var tableView : UITableView? 80 | weak var controller : UIViewController? 81 | var display : Bool? 82 | 83 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 84 | 85 | super.init(style: style, reuseIdentifier: reuseIdentifier) 86 | self.setupCell() 87 | self.buildSubview() 88 | } 89 | 90 | required init?(coder aDecoder: NSCoder) { 91 | 92 | fatalError("init(coder:) has not been implemented") 93 | } 94 | 95 | /** 96 | Setup cell, override by subclass. 97 | */ 98 | func setupCell() { 99 | 100 | self.selectionStyle = .none 101 | } 102 | 103 | /** 104 | Build subview, override by subclass. 105 | */ 106 | func buildSubview() {} 107 | 108 | /** 109 | Load content, override by subclass. 110 | */ 111 | func loadContent() {} 112 | 113 | /** 114 | Selected event, you should use this method in 'tableView:didSelectRowAtIndexPath:' to make it effective. 115 | */ 116 | func selectedEvent() {} 117 | 118 | /** 119 | Calculate the cell's height from data, override by subclass. 120 | 121 | - parameter data: Data. 122 | 123 | - returns: Cell's height. 124 | */ 125 | class func HeightWithData(_ data : AnyObject? = nil) -> CGFloat { return 0} 126 | 127 | /** 128 | Create the CustomCell type data adapter. 129 | 130 | - parameter reuseIdentifier: The reuseIdentifier. 131 | - parameter data: The data. 132 | - parameter cellHeight: The cell's height. 133 | - parameter type: The cell's type. 134 | 135 | - returns: The cellDataAdapter. 136 | */ 137 | class func Adapter(_ reuseIdentifier: String? = nil, 138 | data: AnyObject? = nil, 139 | cellHeight: CGFloat? = 0, 140 | type: Int? = nil) -> CellDataAdapter { 141 | 142 | return CellDataAdapter.init(cellReuseIdentifier: reuseIdentifier ?? "\(self.classForCoder())", 143 | data: data, 144 | cellHeight: cellHeight, 145 | cellType: type) 146 | } 147 | 148 | /** 149 | Register cell to tableView with cell reuse identifier. 150 | 151 | - parameter tableView: UITableView. 152 | - parameter cellReuseIdentifier: Cell reuse identifier. 153 | */ 154 | class func RegisterTo(_ tableView : UITableView, 155 | cellReuseIdentifier : String? = nil) { 156 | 157 | tableView.register(self.classForCoder(), forCellReuseIdentifier: cellReuseIdentifier ?? "\(self.classForCoder())") 158 | } 159 | 160 | /** 161 | Update the cell's height with animated or not, before you use this method, you should have the weak reference 'tableView' and 'dataAdapter', and this method will update the weak reference dataAdapter's property cellHeight. 162 | 163 | - parameter height: The new cell height. 164 | - parameter animated: Animated or not, default is true. 165 | */ 166 | func updateWithNewCellHeight(_ height : CGFloat, animated : Bool = true) { 167 | 168 | guard tableView != nil && dataAdapter != nil else { 169 | 170 | return 171 | } 172 | 173 | if animated { 174 | 175 | dataAdapter?.cellHeight = height 176 | if #available(iOS 11.0, *) { 177 | 178 | tableView?.performBatchUpdates(nil, completion: nil) 179 | 180 | } else { 181 | 182 | tableView?.beginUpdates() 183 | tableView?.endUpdates() 184 | } 185 | 186 | } else { 187 | 188 | dataAdapter?.cellHeight = height 189 | tableView?.reloadData() 190 | } 191 | } 192 | } 193 | 194 | -------------------------------------------------------------------------------- /Swift-Animations/CustomCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomCollectionViewCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/13. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: extension UITableView 12 | 13 | extension UICollectionView { 14 | 15 | /** 16 | Dequeue and load content from adapter. 17 | 18 | - parameter adapter: The CellDataAdapter. 19 | - parameter indexPath: The indexPath. 20 | - parameter collectionView: The CollectionView. 21 | - parameter delegate: The CustomCollectionViewCell's delegate. 22 | - parameter controller: The controller. 23 | 24 | - returns: The CustomCell instance. 25 | */ 26 | func dequeueCellAndLoadContentFromAdapter(_ adapter : CellDataAdapter, 27 | indexPath : IndexPath, 28 | collectionView : UICollectionView? = nil, 29 | delegate : CustomCollectionViewCellDelegate? = nil, 30 | controller : UIViewController? = nil) -> CustomCollectionViewCell { 31 | 32 | let cell = self.dequeueReusableCell(withReuseIdentifier: adapter.cellReuseIdentifier!, for: indexPath) as! CustomCollectionViewCell 33 | cell.indexPath = indexPath 34 | cell.dataAdapter = adapter 35 | cell.data = adapter.data 36 | cell.collectionView = collectionView 37 | cell.delegate = delegate 38 | cell.controller = controller 39 | cell.loadContent() 40 | 41 | return cell 42 | } 43 | 44 | func selectedEventWithIndexPath(_ indexPath : IndexPath) { 45 | 46 | let cell = self.cellForItem(at: indexPath) as! CustomCollectionViewCell 47 | 48 | // Make sure the cell is kind of CustomCell. 49 | guard cell.isKind(of: CustomCollectionViewCell.classForCoder()) == true else { 50 | 51 | return 52 | } 53 | 54 | cell.selectedEvent() 55 | } 56 | } 57 | 58 | // MARK: protocol CustomCellDelegate 59 | 60 | protocol CustomCollectionViewCellDelegate : class { 61 | 62 | /** 63 | CustomCell's event. 64 | 65 | - parameter cell: CustomCollectionViewCell type class. 66 | - parameter event: Event data. 67 | */ 68 | func customCollectionViewCell(_ cell: CustomCollectionViewCell?, event: Any?) 69 | } 70 | 71 | class CustomCollectionViewCell: UICollectionViewCell { 72 | 73 | weak var delegate : CustomCollectionViewCellDelegate? 74 | weak var dataAdapter : CellDataAdapter? 75 | weak var data : AnyObject? 76 | var indexPath : IndexPath? 77 | weak var collectionView : UICollectionView? 78 | weak var controller : UIViewController? 79 | var display : Bool? 80 | 81 | override init(frame: CGRect) { 82 | 83 | super.init(frame: frame) 84 | setupCell() 85 | buildSubview() 86 | } 87 | 88 | required init?(coder aDecoder: NSCoder) { 89 | 90 | fatalError("init(coder:) has not been implemented") 91 | } 92 | 93 | /** 94 | Setup cell, override by subclass. 95 | */ 96 | func setupCell() {} 97 | 98 | /** 99 | Build subview, override by subclass. 100 | */ 101 | func buildSubview() {} 102 | 103 | /** 104 | Load content, override by subclass. 105 | */ 106 | func loadContent() {} 107 | 108 | /** 109 | Selected event, you should use this method in 'tableView:didSelectRowAtIndexPath:' to make it effective. 110 | */ 111 | func selectedEvent() {} 112 | 113 | /** 114 | Register cell to tableView with cell reuse identifier. 115 | 116 | - parameter collectionView: UICollectionView. 117 | - parameter cellReuseIdentifier: Cell reuse identifier. 118 | */ 119 | class func RegisterTo(_ collectionView: UICollectionView, cellReuseIdentifier: String? = nil) { 120 | 121 | collectionView.register(self.classForCoder(), 122 | forCellWithReuseIdentifier: cellReuseIdentifier ?? "\(self.classForCoder())") 123 | } 124 | 125 | /** 126 | Create the CustomCell type data adapter. 127 | 128 | - parameter reuseIdentifier: The reuseIdentifier. 129 | - parameter data: The data. 130 | - parameter type: The cell's type. 131 | 132 | - returns: The cellDataAdapter. 133 | */ 134 | class func Adapter(_ reuseIdentifier: String? = nil, data: AnyObject? = nil, type: Int? = nil) -> CellDataAdapter { 135 | 136 | return CellDataAdapter.init(cellReuseIdentifier: reuseIdentifier ?? "\(self.classForCoder())", 137 | data: data, 138 | cellHeight: 0, cellType: type) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Swift-Animations/CustomHeaderFooterView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomHeaderFooterView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/9. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: protocol CustomCellDelegate 12 | 13 | protocol CustomHeaderFooterViewDelegate : class { 14 | 15 | /** 16 | CustomCell's event. 17 | 18 | - parameter cell: CustomCell type class. 19 | - parameter event: Event data. 20 | */ 21 | func customHeaderFooterView(_ headerFooterView: CustomHeaderFooterView?, event: AnyObject?) 22 | } 23 | 24 | class CustomHeaderFooterView: UITableViewHeaderFooterView { 25 | 26 | weak var delegate : CustomHeaderFooterViewDelegate? 27 | weak var data : AnyObject? 28 | weak var tableView : UITableView? 29 | weak var controller : UIViewController? 30 | var section : Int? 31 | 32 | override init(reuseIdentifier: String?) { 33 | 34 | super.init(reuseIdentifier: reuseIdentifier) 35 | setupHeaderFooterView() 36 | buildSubview() 37 | } 38 | 39 | required init?(coder aDecoder: NSCoder) { 40 | 41 | fatalError("init(coder:) has not been implemented") 42 | } 43 | 44 | /** 45 | Setup headerFooterView, override by subclass. 46 | */ 47 | func setupHeaderFooterView() {} 48 | 49 | /** 50 | Build subview, override by subclass. 51 | */ 52 | func buildSubview() {} 53 | 54 | /** 55 | Load content, override by subclass. 56 | */ 57 | func loadContent() {} 58 | 59 | /** 60 | Calculate the cell's height from data, override by subclass. 61 | 62 | - parameter data: Data. 63 | 64 | - returns: Cell's height. 65 | */ 66 | class func HeightWithData(_ data : AnyObject? = nil) -> CGFloat { return 0} 67 | 68 | /** 69 | Set HeaderFooterView backgroundColor. 70 | 71 | - parameter color: Color. 72 | */ 73 | func setHeaderFooterViewBackgroundColor(_ color : UIColor) { 74 | 75 | self.contentView.backgroundColor = color 76 | } 77 | 78 | /** 79 | Register headerFooterView to tableView with reuse identifier. 80 | 81 | - parameter tableView: UITableView. 82 | - parameter cellReuseIdentifier: HeaderFooterView reuse identifier. 83 | */ 84 | class func RegisterTo(_ tableView: UITableView, reuseIdentifier: String? = nil) { 85 | 86 | tableView.register(self.classForCoder(), forHeaderFooterViewReuseIdentifier: (reuseIdentifier != nil) ? reuseIdentifier! : String(describing: self.classForCoder())) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Swift-Animations/DefaultNotificationCenter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultNotificationCenter.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/19. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: protocol DefaultNotificationCenterDelegate 12 | 13 | protocol DefaultNotificationCenterDelegate : class { 14 | 15 | /** 16 | DefaultNotificationCenter's event. 17 | 18 | - parameter notificationName: Event name. 19 | - parameter object: Event object, maybe nil. 20 | */ 21 | func defaultNotificationCenter(_ notificationName : String, object : AnyObject?) 22 | } 23 | 24 | // MARK: protocol DefaultNotificationCenter 25 | 26 | class DefaultNotificationCenter: NSObject { 27 | 28 | // MARK: Properties & funcs. 29 | 30 | /// DefaultNotificationCenter's delegate. 31 | weak var delegate : DefaultNotificationCenterDelegate? 32 | 33 | /** 34 | Post message to specified notification name. 35 | 36 | - parameter name: Notification name. 37 | - parameter object: Data. 38 | */ 39 | class func PostMessageTo(_ name : String, object : AnyObject? = nil) { 40 | 41 | NotificationCenter.default.post(name: Notification.Name(rawValue: name), object: object) 42 | } 43 | 44 | convenience init(delegate: DefaultNotificationCenterDelegate, notificationNames : [String]? = nil) { 45 | 46 | self.init() 47 | self.delegate = delegate 48 | 49 | if notificationNames != nil { 50 | 51 | for name in notificationNames! { 52 | 53 | self.addNotificationName(name) 54 | } 55 | } 56 | } 57 | 58 | /** 59 | Add notification name. 60 | 61 | - parameter name: Notification name. 62 | */ 63 | func addNotificationName(_ name : String) { 64 | 65 | var haveTheSameName = false 66 | 67 | // Check have the same name or not. 68 | for model in notificationModels { 69 | 70 | if model.name == name { 71 | 72 | haveTheSameName = true 73 | break 74 | } 75 | } 76 | 77 | // Add notification. 78 | if haveTheSameName == false { 79 | 80 | let model = DefaultNotificationCenterModel() 81 | model.name = name 82 | notificationModels.append(model) 83 | 84 | NotificationCenter.default.addObserver(self, selector: #selector(DefaultNotificationCenter.notificationEvent), name: NSNotification.Name(rawValue: model.name), object: nil) 85 | } 86 | } 87 | 88 | /** 89 | Delete notification name. 90 | 91 | - parameter name: Notification name. 92 | */ 93 | func deleteNotificationName(_ name : String) { 94 | 95 | var haveTheSameName = false 96 | var index : Int = 0 97 | var model : DefaultNotificationCenterModel! 98 | 99 | // Check have the same name or not. 100 | for tmpModel in notificationModels { 101 | 102 | if tmpModel.name == name { 103 | 104 | haveTheSameName = true 105 | model = tmpModel 106 | break 107 | } 108 | 109 | index = index + 1 110 | } 111 | 112 | // Remove notification. 113 | if haveTheSameName == true { 114 | 115 | NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: model.name), object: nil) 116 | notificationModels.remove(at: index) 117 | } 118 | } 119 | 120 | /** 121 | Remove all notifications. 122 | */ 123 | func removeAllNotifications() { 124 | 125 | for model in notificationModels { 126 | 127 | NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: model.name), object: nil) 128 | } 129 | } 130 | 131 | /** 132 | Get all the notification names. 133 | 134 | - returns: Notification names's array. 135 | */ 136 | func notificationNames() -> [String] { 137 | 138 | var names = [String]() 139 | 140 | for model in notificationModels { 141 | 142 | names.append(model.name) 143 | } 144 | 145 | return names 146 | } 147 | 148 | /** 149 | Notification's event. 150 | 151 | - parameter obj: The NSNotification object. 152 | */ 153 | @objc func notificationEvent(_ obj : AnyObject?) { 154 | 155 | let notification = obj as! Notification 156 | delegate?.defaultNotificationCenter(notification.name.rawValue, object: notification.object as AnyObject?) 157 | } 158 | 159 | // MARK: Private properties & func. 160 | 161 | /// Store the Notification's infomation. 162 | fileprivate var notificationModels : [DefaultNotificationCenterModel] = [DefaultNotificationCenterModel]() 163 | 164 | deinit { 165 | 166 | removeAllNotifications() 167 | } 168 | } 169 | 170 | // MARK: private DefaultNotificationCenterModel 171 | 172 | private class DefaultNotificationCenterModel : NSObject { 173 | 174 | var name : String! 175 | } 176 | 177 | 178 | -------------------------------------------------------------------------------- /Swift-Animations/EasingValue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EasingValue.swift 3 | // Swift-EasingAnimation 4 | // 5 | // Created by YouXianMing on 15/10/21. 6 | // 7 | // https://github.com/YouXianMing 8 | // http://home.cnblogs.com/u/YouXianMing/ 9 | // 10 | 11 | import UIKit 12 | 13 | class EasingValue: NSObject { 14 | 15 | // MARK: var 16 | 17 | /// 动画函数 18 | var easing : EasingFunction! 19 | 20 | /// 关键帧点数 21 | var frameCount : size_t! 22 | 23 | // MARK: init 24 | override init() { 25 | 26 | super.init() 27 | 28 | easing = EasingFunction.sineEaseIn 29 | frameCount = 60 30 | } 31 | 32 | init(withFunction : EasingFunction, frameCount : size_t) { 33 | 34 | super.init() 35 | 36 | self.easing = withFunction 37 | self.frameCount = frameCount 38 | } 39 | 40 | // MARK: func 41 | 42 | /** 43 | 计算关键帧 44 | 45 | - parameter fromValue: 起始值 46 | - parameter toValue: 结束值 47 | 48 | - returns: 关键帧值数组 49 | */ 50 | func frameValueWith(fromValue : Double, toValue : Double) -> [AnyObject] { 51 | 52 | let values = NSMutableArray(capacity: frameCount) 53 | 54 | var t : Double = 0.0 55 | let dt : Double = 1.0 / (Double(frameCount) - 1) 56 | 57 | for _ in 0 ..< frameCount { 58 | 59 | let value = fromValue + easing.function(t) * (toValue - fromValue) 60 | values.add(value) 61 | 62 | t += dt 63 | } 64 | 65 | return values as [AnyObject] 66 | } 67 | 68 | /** 69 | 计算关键帧点 70 | 71 | - parameter fromPoint: 起始点 72 | - parameter toPoint: 结束点 73 | 74 | - returns: 关键帧点数组 75 | */ 76 | func pointValueWith(fromPoint : CGPoint, toPoint : CGPoint) -> [AnyObject] { 77 | 78 | let values = NSMutableArray(capacity: frameCount) 79 | 80 | var t : Double = 0.0 81 | let dt : Double = 1.0 / (Double(frameCount) - 1) 82 | 83 | for _ in 0 ..< frameCount { 84 | 85 | let x : Double = Double(fromPoint.x) + easing.function(t) * (Double(toPoint.x) - Double(fromPoint.x)) 86 | let y : Double = Double(fromPoint.y) + easing.function(t) * (Double(toPoint.y) - Double(fromPoint.y)) 87 | let point : CGPoint = CGPoint(x : x, y : y) 88 | values.add(NSValue(cgPoint: point)) 89 | 90 | t += dt 91 | } 92 | 93 | return values as [AnyObject] 94 | } 95 | 96 | /** 97 | 计算关键帧尺寸 98 | 99 | - parameter fromSize: 起始尺寸 100 | - parameter toSize: 结束尺寸 101 | 102 | - returns: 关键帧尺寸数组 103 | */ 104 | func sizeValueWith(fromSize : CGSize, toSize : CGSize) -> [AnyObject] { 105 | 106 | let values = NSMutableArray(capacity: frameCount) 107 | 108 | var t : Double = 0.0 109 | let dt : Double = 1.0 / (Double(frameCount) - 1) 110 | 111 | for _ in 0 ..< frameCount { 112 | 113 | let width : Double = Double(fromSize.width) + easing.function(t) * (Double(toSize.width) - Double(fromSize.width)) 114 | let height : Double = Double(fromSize.height) + easing.function(t) * (Double(toSize.height) - Double(fromSize.height)) 115 | let size : CGSize = CGSize(width: width, height: height) 116 | values.add(NSValue(cgSize : size)) 117 | 118 | t += dt 119 | } 120 | 121 | return values as [AnyObject] 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Swift-Animations/FontCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FontCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/15. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FontCell: CustomCell { 12 | 13 | fileprivate var label : UILabel! 14 | 15 | override func buildSubview() { 16 | 17 | label = UILabel.init(frame: CGRect.zero) 18 | self.addSubview(label) 19 | } 20 | 21 | override func loadContent() { 22 | 23 | let model = data as! FontModel 24 | 25 | label.text = model.fontName 26 | label.font = UIFont.init(name: model.fontName!, size: 16) 27 | label.sizeToFit() 28 | 29 | label.x = 15 30 | label.centerY = FontCell.HeightWithData() / 2 31 | } 32 | 33 | override class func HeightWithData(_ data : AnyObject? = nil) -> CGFloat { 34 | 35 | return 50 36 | } 37 | 38 | override func selectedEvent() { 39 | 40 | delegate?.customCell(self, event: data) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Swift-Animations/FontFamilyHeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FontFamilyHeaderView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/15. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FontFamilyHeaderView: CustomHeaderFooterView { 12 | 13 | fileprivate var label : UILabel! 14 | 15 | override func setupHeaderFooterView() { 16 | 17 | setHeaderFooterViewBackgroundColor(UIColor.white) 18 | } 19 | 20 | override func buildSubview() { 21 | 22 | self.addSubview(BackgroundLineView(frame : CGRect.init(x: 0, y: 0, width: Screen.Width, height: FontFamilyHeaderView.HeightWithData()), 23 | lineWidth : 4, 24 | lineGap : 4, 25 | lineColor : UIColor.black.alpha(0.015), 26 | rotate : CGFloat(Double.pi / 4))) 27 | 28 | self.addSubview(UIView.CreateLine(CGRect.init(x: 0, y: 0, width: Screen.Width, height: 0.5), 29 | lineColor: UIColor.black.alpha(0.05))) 30 | self.addSubview(UIView.CreateLine(CGRect.init(x: 0, y: FontFamilyHeaderView.HeightWithData() - 0.5, width: Screen.Width, height: 0.5), 31 | lineColor: UIColor.black.alpha(0.05))) 32 | 33 | label = UILabel.init(frame: CGRect.zero) 34 | self.addSubview(label) 35 | 36 | let button = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: Screen.Width, height: FontFamilyHeaderView.HeightWithData())) 37 | button.addTarget(self, action: #selector(FontFamilyHeaderView.buttonEvent), for: .touchUpInside) 38 | self.addSubview(button) 39 | 40 | let redView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: 2, height: 17)) 41 | redView.backgroundColor = UIColor.red 42 | redView.centerY = FontFamilyHeaderView.HeightWithData() / 2 43 | self.addSubview(redView) 44 | } 45 | 46 | override func loadContent() { 47 | 48 | let model = data as! FontFamilyModel 49 | 50 | label.text = model.familyName 51 | label.font = UIFont.init(name: model.familyName!, size: 16) 52 | label.sizeToFit() 53 | 54 | label.x = 15 55 | label.centerY = FontFamilyHeaderView.HeightWithData() / 2 56 | } 57 | 58 | override class func HeightWithData(_ data : AnyObject? = nil) -> CGFloat { 59 | 60 | return 50 61 | } 62 | 63 | @objc private func buttonEvent() { 64 | 65 | delegate?.customHeaderFooterView(self, event: data) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Swift-Animations/FontFamilyModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FontFamilyModel.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/15. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FontFamilyModel: NSObject { 12 | 13 | var familyName : String! 14 | var fonts : [FontModel] 15 | 16 | private override init() { 17 | 18 | self.fonts = [] 19 | super.init() 20 | } 21 | 22 | convenience init(familyName : String) { 23 | 24 | self.init() 25 | self.familyName = familyName 26 | } 27 | } 28 | 29 | class FontModel: NSObject { 30 | 31 | var fontName : String? 32 | 33 | private override init() { 34 | 35 | super.init() 36 | } 37 | 38 | convenience init(fontName : String) { 39 | 40 | self.init() 41 | self.fontName = fontName 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Swift-Animations/FullTitleVisualEffectViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FullTitleVisualEffectViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/18. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FullTitleVisualEffectViewController: BaseCustomViewController { 12 | 13 | fileprivate var effectView : UIVisualEffectView! 14 | fileprivate var vibrancyEffectView : UIVisualEffectView! 15 | 16 | override func setupSubViews() { 17 | 18 | effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) 19 | effectView.isUserInteractionEnabled = true 20 | effectView.frame = (titleView?.bounds)! 21 | titleView?.addSubview(effectView) 22 | 23 | vibrancyEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: effectView.effect as! UIBlurEffect)) 24 | vibrancyEffectView.frame = effectView.bounds 25 | effectView.contentView.addSubview(vibrancyEffectView) 26 | 27 | let headlineLabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: Screen.Width, height: 64)) 28 | headlineLabel.font = UIFont.HeitiSC(20) 29 | headlineLabel.textAlignment = .center 30 | headlineLabel.textColor = UIColor(red: 0.329, green: 0.329, blue: 0.329, alpha: 1) 31 | headlineLabel.text = title 32 | headlineLabel.bottom = effectView.height 33 | 34 | let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 64)) 35 | backButton.center = CGPoint(x: 20, y: headlineLabel.centerY) 36 | backButton.setImage(UIImage(named: "backIconTypeTwo"), for: .normal) 37 | backButton.setImage(UIImage(named: "backIconTypeTwo_pre"), for: .highlighted) 38 | backButton.addTarget(self, action: #selector(FullTitleVisualEffectViewController.popSelf), for: .touchUpInside) 39 | 40 | vibrancyEffectView.contentView.addSubview(backButton) 41 | vibrancyEffectView.contentView.addSubview(headlineLabel) 42 | } 43 | 44 | override func makeViewsConfig(viewsConfig: [String : ControllerBaseViewConfig]) { 45 | 46 | let contentViewConfig = viewsConfig[contentViewId]; 47 | contentViewConfig?.frame = CGRect(x: 0, y: 0, width: Screen.Width, height: Screen.Height); 48 | 49 | /// iPhoneX 50 | if Screen.CurrentScreen == Screen._375x812 { 51 | 52 | let titleViewConfig = viewsConfig[titleViewId] 53 | titleViewConfig?.frame = CGRect.init(x: 0, y: 0, width: Screen.Width, height: 64 + additionaliPhoneXTopSafeHeight) 54 | } 55 | } 56 | 57 | @objc func popSelf() { 58 | 59 | self.popViewControllerAnimated(true) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Swift-Animations/GCDGroup.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDGroup.swift 3 | // Swift-GCD 4 | // 5 | // Created by YouXianMing on 2017/9/19. 6 | // Copyright © 2017年 TechCode. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDGroup { 12 | 13 | public let dispatchGroup : DispatchGroup 14 | 15 | init() { 16 | 17 | self.dispatchGroup = DispatchGroup() 18 | } 19 | 20 | /// 在指定的queue里面获取消息 21 | /// 22 | /// - Parameters: 23 | /// - queue: 指定的queue 24 | /// - execute: 执行的block 25 | func notifyIn(_ queue : GCDQueue, execute: @escaping () -> Void) { 26 | 27 | self.dispatchGroup.notify(queue: queue.dispatchQueue, execute: execute) 28 | } 29 | 30 | /// 进入group 31 | func enter() { 32 | 33 | self.dispatchGroup.enter() 34 | } 35 | 36 | /// 从group出来 37 | func leave() { 38 | 39 | self.dispatchGroup.leave() 40 | } 41 | 42 | /// [阻塞操作] 无限等待 43 | func wait() { 44 | 45 | self.dispatchGroup.wait() 46 | } 47 | 48 | /// [阻塞操作] 等待指定的时间 49 | /// 50 | /// - Parameter seconds: 等待的时间,最多精确到1ms 51 | /// - Returns: DispatchTimeoutResult对象 52 | func waitForSeconds(seconds : Float) -> DispatchTimeoutResult { 53 | 54 | return self.dispatchGroup.wait(timeout: .now() + .milliseconds(Int(seconds * 1000))) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Swift-Animations/GCDQueue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDQueue.swift 3 | // Swift-GCD 4 | // 5 | // Created by YouXianMing on 2017/9/19. 6 | // Copyright © 2017年 TechCode. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDQueue { 12 | 13 | public let dispatchQueue : DispatchQueue 14 | 15 | init(dispatchQueue : DispatchQueue) { 16 | 17 | self.dispatchQueue = dispatchQueue 18 | } 19 | 20 | // MARK: globalQueue & mainQueue 21 | 22 | /// 获取主线程 23 | public class var Main : GCDQueue { 24 | 25 | return GCDQueue.init(dispatchQueue: DispatchQueue.main) 26 | } 27 | 28 | /// 获取子线程 29 | /// 30 | /// - Parameter priority: 优先级 31 | /// - Returns: 子线程 32 | public class func Global(_ priority : GCDQueuePriority = .DefaultPriority) -> GCDQueue { 33 | 34 | return GCDQueue.init(dispatchQueue: DispatchQueue.global(qos: priority.getDispatchQoSClass())) 35 | } 36 | 37 | // MARK: concurrentQueue & serialQueue 38 | 39 | /// 获取并发线程 40 | /// 41 | /// - Parameters: 42 | /// - label: 线程标签 43 | /// - priority: 优先级 44 | /// - Returns: 并发线程 45 | public class func Concurrent(_ label : String = "", _ priority : GCDQueuePriority = .DefaultPriority) -> GCDQueue { 46 | 47 | return GCDQueue.init(dispatchQueue: DispatchQueue(label: label, qos: priority.getDispatchQoS(), attributes: .concurrent)) 48 | } 49 | 50 | /// 获取串行线程 51 | /// 52 | /// - Parameters: 53 | /// - label: 线程标签 54 | /// - priority: 优先级 55 | /// - Returns: 串行线程 56 | public class func Serial(_ label : String = "", _ priority : GCDQueuePriority = .DefaultPriority) -> GCDQueue { 57 | 58 | return GCDQueue.init(dispatchQueue: DispatchQueue(label: label, qos: priority.getDispatchQoS())) 59 | } 60 | 61 | // MARK: Excute 62 | 63 | /// 异步执行 64 | /// 65 | /// - Parameter excute: 执行的block 66 | public func excute(_ excute : @escaping ()-> Void) { 67 | 68 | dispatchQueue.async(execute: excute) 69 | } 70 | 71 | /// 延时异步执行 72 | /// 73 | /// - Parameters: 74 | /// - seconds: 延时秒数,最多精确到1ms 75 | /// - excute: 执行的block 76 | public func excuteAfterDelay(_ seconds : Float, _ excute : @escaping ()-> Void) { 77 | 78 | dispatchQueue.asyncAfter(deadline: .now() + .milliseconds(Int(seconds * 1000)), execute: excute) 79 | } 80 | 81 | /// 同步执行 82 | /// 83 | /// - Parameter excute: 执行的block 84 | public func excuteAndWaitsUntilTheBlockCompletes(_ excute : @escaping ()-> Void) { 85 | 86 | dispatchQueue.sync(execute: excute) 87 | } 88 | 89 | /// 在group中执行 90 | /// 91 | /// - Parameters: 92 | /// - group: GCDGroup对象 93 | /// - excute: 执行的block 94 | public func excuteInGroup(_ group : GCDGroup, _ excute : @escaping ()-> Void) { 95 | 96 | dispatchQueue.async(group: group.dispatchGroup, execute: excute) 97 | } 98 | 99 | // MARK: Class method for excute 100 | 101 | /// 在主线程执行 102 | /// 103 | /// - Parameter excute: 执行的block 104 | class func ExcuteInMain(_ excute : @escaping ()-> Void) { 105 | 106 | GCDQueue.Main.excute(excute) 107 | } 108 | 109 | /// 在主线程延时执行 110 | /// 111 | /// - Parameters: 112 | /// - seconds: 延时秒数,最多精确到1ms 113 | /// - excute: 执行的block 114 | class func ExcuteInMainAfterDelay(_ seconds : Float, _ excute : @escaping ()-> Void) { 115 | 116 | GCDQueue.Main.excuteAfterDelay(seconds, excute) 117 | } 118 | 119 | /// 在子线程执行 120 | /// 121 | /// - Parameters: 122 | /// - priority: 优先级 123 | /// - excute: 执行的block 124 | class func ExcuteInGlobal(_ priority : GCDQueuePriority = .DefaultPriority, _ excute : @escaping ()-> Void) { 125 | 126 | GCDQueue.Global(priority).excute(excute) 127 | } 128 | 129 | /// 在子线程延时执行 130 | /// 131 | /// - Parameters: 132 | /// - seconds: 延时秒数,最多精确到1ms 133 | /// - excute: 执行的block 134 | class func ExcuteInGlobalAfterDelay(_ seconds : Float, _ excute : @escaping ()-> Void) { 135 | 136 | GCDQueue.Global().excuteAfterDelay(seconds, excute) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Swift-Animations/GCDQueuePriority.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDQueuePriority.swift 3 | // Swift-GCD 4 | // 5 | // Created by YouXianMing on 2017/9/20. 6 | // Copyright © 2017年 TechCode. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum GCDQueuePriority { 12 | 13 | case BackgroundPriority // DISPATCH_QUEUE_PRIORITY_BACKGROUND 14 | case LowPriority // DISPATCH_QUEUE_PRIORITY_LOW 15 | case DefaultPriority // DISPATCH_QUEUE_PRIORITY_DEFAULT 16 | case HighPriority // DISPATCH_QUEUE_PRIORITY_HIGH 17 | 18 | case userInteractive 19 | case unspecified 20 | 21 | func getDispatchQoSClass() -> DispatchQoS.QoSClass { 22 | 23 | var qos: DispatchQoS.QoSClass 24 | 25 | switch self { 26 | 27 | case GCDQueuePriority.BackgroundPriority: 28 | qos = .background 29 | break 30 | 31 | case GCDQueuePriority.LowPriority: 32 | qos = .utility 33 | break 34 | 35 | case GCDQueuePriority.DefaultPriority: 36 | qos = .default 37 | break 38 | 39 | case GCDQueuePriority.HighPriority: 40 | qos = .userInitiated 41 | break 42 | 43 | case GCDQueuePriority.userInteractive: 44 | qos = .userInteractive 45 | break 46 | 47 | case GCDQueuePriority.unspecified: 48 | qos = .unspecified 49 | break 50 | } 51 | 52 | return qos 53 | } 54 | 55 | func getDispatchQoS() -> DispatchQoS { 56 | 57 | var qos: DispatchQoS 58 | 59 | switch self { 60 | 61 | case GCDQueuePriority.BackgroundPriority: 62 | qos = .background 63 | break 64 | 65 | case GCDQueuePriority.LowPriority: 66 | qos = .utility 67 | break 68 | 69 | case GCDQueuePriority.DefaultPriority: 70 | qos = .default 71 | break 72 | 73 | case GCDQueuePriority.HighPriority: 74 | qos = .userInitiated 75 | break 76 | 77 | case GCDQueuePriority.userInteractive: 78 | qos = .userInteractive 79 | break 80 | 81 | case GCDQueuePriority.unspecified: 82 | qos = .unspecified 83 | break 84 | } 85 | 86 | return qos 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Swift-Animations/GCDSemaphore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDSemaphore.swift 3 | // Swift-GCD 4 | // 5 | // Created by YouXianMing on 2017/9/19. 6 | // Copyright © 2017年 TechCode. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDSemaphore { 12 | 13 | public let dispatchSemaphore : DispatchSemaphore 14 | 15 | init(initialSignal : Int = 0) { 16 | 17 | self.dispatchSemaphore = DispatchSemaphore(value: initialSignal) 18 | } 19 | 20 | // MARK: Singal 21 | 22 | /// 发信号 23 | func signal() { 24 | 25 | self.dispatchSemaphore.signal() 26 | } 27 | 28 | // MARK: Wait 29 | 30 | /// [阻塞操作] 无限等待 31 | func wait() { 32 | 33 | self.dispatchSemaphore.wait() 34 | } 35 | 36 | /// [阻塞操作] 等待指定的时间 37 | /// 38 | /// - Parameter seconds: 等待的时间,最多精确到1ms 39 | /// - Returns: DispatchTimeoutResult对象 40 | func waitForSeconds(_ seconds : Float) -> DispatchTimeoutResult { 41 | 42 | return self.dispatchSemaphore.wait(timeout: DispatchTime.now() + .milliseconds(Int(seconds * 1000))) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Swift-Animations/GCDTimer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GCDTimer.swift 3 | // Swift-GCD 4 | // 5 | // Created by YouXianMing on 2017/9/20. 6 | // Copyright © 2017年 TechCode. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GCDTimer { 12 | 13 | public let dispatchSourceTimer : DispatchSourceTimer 14 | 15 | init(in : GCDQueue, delay : Float = 0, interval : Float) { 16 | 17 | dispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue: `in`.dispatchQueue) 18 | dispatchSourceTimer.schedule(deadline: .now() + .milliseconds(Int(delay * 1000)), repeating: .milliseconds(Int(interval * 1000))) 19 | } 20 | 21 | /// 设定定时器任务的回调函数 22 | /// 23 | /// - Parameter eventHandler: 回调函数 24 | func setTimerEventHandler(eventHandler: @escaping (GCDTimer)-> Void) { 25 | 26 | dispatchSourceTimer.setEventHandler { 27 | 28 | eventHandler(self) 29 | } 30 | } 31 | 32 | /// 设定定时器销毁时候的回调函数 33 | /// 34 | /// - Parameter eventHandler: 回调函数 35 | func setDestroyEventHandler(eventHandler: @escaping ()-> Void) { 36 | 37 | dispatchSourceTimer.setCancelHandler { 38 | 39 | eventHandler() 40 | } 41 | } 42 | 43 | /// 挂起 44 | func suspend() { 45 | 46 | dispatchSourceTimer.suspend() 47 | } 48 | 49 | /// 开始定时 50 | func start() { 51 | 52 | dispatchSourceTimer.resume() 53 | } 54 | 55 | /// 定时器销毁(执行了此方法后,start就会变得无效) 56 | func destroy() { 57 | 58 | dispatchSourceTimer.cancel() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Swift-Animations/HeaderViewTapAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeaderViewTapAnimationController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/9. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HeaderViewTapAnimationController: NormalTitleViewController, UITableViewDelegate, UITableViewDataSource { 12 | 13 | fileprivate var classes : [ClassModel] = [ClassModel]() 14 | fileprivate var sectionFirstLoad : Bool = false 15 | 16 | fileprivate var tableView : UITableView! 17 | fileprivate weak var tmpHeadView : ClassHeaderView? 18 | 19 | override func viewDidLoad() { 20 | 21 | super.viewDidLoad() 22 | 23 | // TableView. 24 | tableView = UITableView(frame: (contentView?.bounds)!) 25 | tableView.dataSource = self 26 | tableView.delegate = self 27 | tableView.rowHeight = 60 28 | tableView.sectionHeaderHeight = 30 29 | tableView.separatorStyle = .none 30 | contentView?.addSubview(tableView!) 31 | 32 | if #available(iOS 11.0, *) { 33 | 34 | tableView.estimatedRowHeight = 0 35 | tableView.estimatedSectionHeaderHeight = 0 36 | tableView.estimatedSectionFooterHeight = 0 37 | } 38 | 39 | // Register. 40 | ClassHeaderView.RegisterTo(tableView) 41 | StudentInfoCell.RegisterTo(tableView) 42 | 43 | // Data source. 44 | let Aitna = ClassModel(className: "Aitna") 45 | Aitna.expend = false 46 | Aitna.students.append(StudentModel(name: "Y.X.M.", age: 27)) 47 | Aitna.students.append(StudentModel(name: "Leif", age: 12)) 48 | Aitna.students.append(StudentModel(name: "Lennon", age: 23)) 49 | Aitna.students.append(StudentModel(name: "Jerome", age: 19)) 50 | Aitna.students.append(StudentModel(name: "Isidore", age: 15)) 51 | 52 | let Melete = ClassModel(className: "Melete") 53 | Melete.expend = false 54 | Melete.students.append(StudentModel(name: "Merle", age: 17)) 55 | Melete.students.append(StudentModel(name: "Paddy", age: 31)) 56 | Melete.students.append(StudentModel(name: "Perry", age: 59)) 57 | Melete.students.append(StudentModel(name: "Philip", age: 23)) 58 | 59 | let Aoede = ClassModel(className: "Aoede") 60 | Aoede.expend = false 61 | Aoede.students.append(StudentModel(name: "Verne", age: 12)) 62 | Aoede.students.append(StudentModel(name: "Vincent", age: 89)) 63 | Aoede.students.append(StudentModel(name: "Walter", age: 43)) 64 | Aoede.students.append(StudentModel(name: "Zachary", age: 21)) 65 | 66 | let Dione = ClassModel(className: "Dione") 67 | Dione.expend = false 68 | Dione.students.append(StudentModel(name: "Timothy", age: 72)) 69 | Dione.students.append(StudentModel(name: "Roderick", age: 34)) 70 | Dione.students.append(StudentModel(name: "Quentin", age: 12)) 71 | Dione.students.append(StudentModel(name: "Paddy", age: 75)) 72 | 73 | let Adanos = ClassModel(className: "Adanos") 74 | Adanos.expend = false 75 | Adanos.students.append(StudentModel(name: "Mortimer", age: 43)) 76 | Adanos.students.append(StudentModel(name: "Michael", age: 64)) 77 | Adanos.students.append(StudentModel(name: "Kevin", age: 23)) 78 | Adanos.students.append(StudentModel(name: "Jeremy", age: 21)) 79 | 80 | classes.append(Aitna) 81 | classes.append(Melete) 82 | classes.append(Aoede) 83 | classes.append(Dione) 84 | classes.append(Adanos) 85 | 86 | // GCDQueue delay. 87 | GCDQueue.Main.excuteAfterDelay(0.3) { 88 | 89 | self.sectionFirstLoad = true 90 | self.tableView.insertSections(IndexSet(integersIn: Range.init(NSMakeRange(0, self.classes.count))!), with: .fade) 91 | 92 | GCDQueue.Main.excuteAfterDelay(0.4, { 93 | 94 | if let headView = self.tmpHeadView { 95 | 96 | headView.buttonEvent() 97 | } 98 | }) 99 | } 100 | } 101 | 102 | // MARK: UITableView's delegate & dataSource. 103 | 104 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 105 | 106 | let classModel = classes[section] 107 | if classModel.expend == true { 108 | 109 | return classModel.students.count 110 | 111 | } else { 112 | 113 | return 0 114 | } 115 | } 116 | 117 | func numberOfSections(in tableView: UITableView) -> Int { 118 | 119 | if sectionFirstLoad == false { 120 | 121 | return 0 122 | 123 | } else { 124 | 125 | return classes.count 126 | } 127 | } 128 | 129 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 130 | 131 | let classModel = classes[(indexPath as NSIndexPath).section] 132 | let customCell = tableView.dequeueReusableCell(withIdentifier: "StudentInfoCell") as! CustomCell 133 | customCell.data = classModel.students[(indexPath as NSIndexPath).row] 134 | customCell.indexPath = indexPath 135 | customCell.loadContent() 136 | 137 | return customCell 138 | } 139 | 140 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 141 | 142 | tableView.selectedEventWithIndexPath(indexPath) 143 | } 144 | 145 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 146 | 147 | let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "ClassHeaderView") as! ClassHeaderView 148 | headerView.section = section 149 | headerView.data = classes[section] 150 | headerView.tableView = tableView 151 | headerView.loadContent() 152 | 153 | if tmpHeadView == nil && section == 0 { 154 | 155 | tmpHeadView = headerView 156 | } 157 | 158 | return headerView 159 | } 160 | } 161 | 162 | -------------------------------------------------------------------------------- /Swift-Animations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Animations 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UIStatusBarHidden 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Swift-Animations/ListItemCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListItemCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/6. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ListItemCell: CustomCell { 12 | 13 | // MARK: Private var. 14 | 15 | fileprivate var titlelabel : UILabel! 16 | fileprivate var subTitleLabel : UILabel! 17 | 18 | // MARK: Override CustomCell func. 19 | 20 | override func setupCell() { 21 | 22 | super.setupCell() 23 | self.accessoryType = .disclosureIndicator 24 | } 25 | 26 | override func buildSubview() { 27 | 28 | titlelabel = UILabel(frame: CGRect(x: 10, y: 8, width: 290, height: 25)) 29 | titlelabel.font = UIFont.HeitiSC(16) 30 | self.addSubview(titlelabel) 31 | 32 | subTitleLabel = UILabel(frame: CGRect(x: 10, y: 35, width: 290, height: 10)) 33 | subTitleLabel.font = UIFont.AvenirLight(8) 34 | subTitleLabel.textColor = UIColor.gray 35 | self.addSubview(subTitleLabel) 36 | } 37 | 38 | override func loadContent() { 39 | 40 | let item = data as! ControllerItem 41 | titlelabel.text = item.name 42 | subTitleLabel.text = NSStringFromClass(item.controllerClass!).components(separatedBy: ".").last 43 | } 44 | 45 | override func selectedEvent() { 46 | 47 | delegate?.customCell(self, event: data) 48 | } 49 | 50 | override func setHighlighted(_ highlighted: Bool, animated: Bool) { 51 | 52 | UIView.animate(withDuration: 0.35, delay: 0, options: .beginFromCurrentState, animations: { 53 | 54 | self.titlelabel.alpha = (highlighted == true ? 0.5 : 1.0) 55 | self.subTitleLabel.x = (highlighted == true ? 10 + 4 : 10) 56 | 57 | }, completion: nil) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Swift-Animations/LiveImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LiveImageView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/17. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: Public class : LiveImageView 12 | 13 | class LiveImageView: UIImageView { 14 | 15 | // MARK: Properties. 16 | 17 | /// Animation's duration. 18 | var duration : CFTimeInterval = 0.3 19 | 20 | // MARK: Methods. 21 | 22 | /** 23 | Set image with animation or not. 24 | 25 | - parameter newVal: The new image. 26 | - parameter animated: Animated or not. 27 | */ 28 | func setImage(_ newVal : UIImage, animated : Bool) { 29 | 30 | if animated == true { 31 | 32 | let animation = CABasicAnimation(keyPath: "contents") 33 | animation.fromValue = image?.cgImage 34 | animation.toValue = newVal.cgImage 35 | animation.duration = duration 36 | 37 | pLayer.contents = image?.cgImage 38 | pLayer.add(animation, forKey: nil) 39 | 40 | image = newVal 41 | 42 | } else { 43 | 44 | image = newVal 45 | } 46 | } 47 | 48 | // MARK: Private value & func. 49 | 50 | fileprivate var pLayer : CALayer! 51 | 52 | override init(frame: CGRect) { 53 | 54 | super.init(frame: frame) 55 | pLayer = layer 56 | } 57 | 58 | required init?(coder aDecoder: NSCoder) { 59 | 60 | fatalError("init(coder:) has not been implemented") 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Swift-Animations/LiveImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LiveImageViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/17. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LiveImageViewController: NormalTitleViewController { 12 | 13 | fileprivate var timer : Timer! 14 | fileprivate var count : NSInteger = 0 15 | fileprivate var images : [UIImage] = [UIImage]() 16 | fileprivate var liveImageView : LiveImageView! 17 | 18 | override func viewDidLoad() { 19 | 20 | super.viewDidLoad() 21 | 22 | // Init images. 23 | images = [UIImage]() 24 | images.append(UIImage(named: "pic_1")!) 25 | images.append(UIImage(named: "pic_2")!) 26 | images.append(UIImage(named: "pic_3")!) 27 | images.append(UIImage(named: "pic_4")!) 28 | 29 | // Init LiveImageView. 30 | let image = images[0] 31 | liveImageView = LiveImageView(frame: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) 32 | liveImageView.center = (contentView?.middlePoint)! 33 | liveImageView.layer.borderWidth = 3 34 | liveImageView.layer.borderColor = UIColor.black.cgColor 35 | liveImageView.duration = 0.5 36 | contentView?.addSubview(liveImageView) 37 | 38 | let currentIndex = count % images.count 39 | count = count + 1 40 | liveImageView.setImage(images[currentIndex], animated: true) 41 | 42 | // Init timer. 43 | timer = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(LiveImageViewController.timerEvent), userInfo: nil, repeats: true) 44 | } 45 | 46 | @objc func timerEvent() { 47 | 48 | let currentIndex = count % images.count 49 | count = count + 1 50 | liveImageView.setImage(images[currentIndex], animated: true) 51 | 52 | UIView.animate(withDuration: 0.5, animations: { 53 | 54 | var tmpRect = self.liveImageView.bounds 55 | tmpRect.size = (self.liveImageView.image?.size)! 56 | self.liveImageView.bounds = tmpRect 57 | self.liveImageView.center = (self.contentView?.middlePoint)! 58 | }) 59 | } 60 | 61 | override func viewDidDisappear(_ animated: Bool) { 62 | 63 | super.viewDidDisappear(animated) 64 | timer.invalidate() 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Swift-Animations/Math.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Math.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/18. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Math: NSObject { 12 | 13 | // MARK: Radian & degree. 14 | 15 | /** 16 | Convert radian to degree. 17 | 18 | - parameter radian: Radian. 19 | 20 | - returns: Degree. 21 | */ 22 | class func DegreeFromRadian(_ radian : CGFloat) -> CGFloat { 23 | 24 | return ((radian) * (180.0 / CGFloat(Double.pi))); 25 | } 26 | 27 | /** 28 | Convert degree to radian. 29 | 30 | - parameter degree: Degree. 31 | 32 | - returns: Radian. 33 | */ 34 | class func RadianFromDegree(_ degree : CGFloat) -> CGFloat { 35 | 36 | return ((degree) * CGFloat(Double.pi) / 180.0); 37 | } 38 | 39 | // MARK: Calculate radian. 40 | 41 | /** 42 | Radian value from math 'tan' function. 43 | 44 | - parameter sideA: Side A 45 | - parameter sideB: Side B 46 | 47 | - returns: Radian value. 48 | */ 49 | class func RadianValueFromTanSideA(sideA : CGFloat, sideB : CGFloat) -> CGFloat { 50 | 51 | return atan2(sideA, sideB) 52 | } 53 | 54 | // MARK: Reset size. 55 | 56 | /** 57 | Get the new size with the fixed width. 58 | 59 | - parameter size: Old size. 60 | - parameter withFixedWidth: The fixed width. 61 | 62 | - returns: New size. 63 | */ 64 | class func ResetFromSize(_ size : CGSize, withFixedWidth : CGFloat) -> CGSize { 65 | 66 | let newHeight = size.height * (withFixedWidth / size.width) 67 | return CGSize(width: withFixedWidth, height: newHeight) 68 | } 69 | 70 | /** 71 | Get the new size with the fixed height. 72 | 73 | - parameter size: Old size. 74 | - parameter withFixedHeight: The fixed width. 75 | 76 | - returns: New size. 77 | */ 78 | class func ResetFromSize(_ size : CGSize, withFixedHeight : CGFloat) -> CGSize { 79 | 80 | let newWidth = size.width * (withFixedHeight / size.height) 81 | return CGSize(width: newWidth, height: withFixedHeight) 82 | } 83 | 84 | // MARK: Calculate once linear equation (Y = kX + b). 85 | 86 | var k : CGFloat! 87 | var b : CGFloat! 88 | 89 | convenience init(_ pointA : (CGFloat, CGFloat), _ pointB : (CGFloat, CGFloat)) { 90 | 91 | self.init() 92 | k = calculateSlope(x1: pointA.0, y1: pointA.1, x2: pointB.0, y2: pointB.1) 93 | b = calculateConstant(x1: pointA.0, y1: pointA.1, x2: pointB.0, y2: pointB.1) 94 | } 95 | 96 | /** 97 | Get X value when Y equal some number. 98 | 99 | - parameter yValue: Some number. 100 | 101 | - returns: X number. 102 | */ 103 | func xValueWhenYEqual(_ yValue : CGFloat) -> CGFloat { 104 | 105 | if k == 0 { 106 | 107 | return 0 108 | } 109 | 110 | return (yValue - b) / k 111 | } 112 | 113 | /** 114 | Get the point value when Y equal some number. 115 | 116 | - parameter yValue: Some number. 117 | 118 | - returns: The point value. 119 | */ 120 | func whenYEqual(_ yValue : CGFloat) -> (x : CGFloat, y : CGFloat) { 121 | 122 | if k == 0 { 123 | 124 | return (0, yValue) 125 | } 126 | 127 | return ((yValue - b) / k, yValue) 128 | } 129 | 130 | /** 131 | Get Y value when X equal some number. 132 | 133 | - parameter xValue: Some number. 134 | 135 | - returns: Y number. 136 | */ 137 | func yValueWhenXEqual(_ xValue : CGFloat) -> CGFloat { 138 | 139 | return k * xValue + b 140 | } 141 | 142 | /** 143 | Get the point value when X equal some number. 144 | 145 | - parameter xValue: Some number. 146 | 147 | - returns: The point value. 148 | */ 149 | func whenXEqual(_ xValue : CGFloat) -> (x : CGFloat, y : CGFloat) { 150 | 151 | return (xValue, k * xValue + b) 152 | } 153 | 154 | // MARK: Private func. 155 | 156 | fileprivate func calculateSlope(x1 : CGFloat, y1 : CGFloat, x2 : CGFloat, y2 : CGFloat) -> CGFloat { 157 | 158 | if x1 == x2 { 159 | 160 | return 0 161 | 162 | } else { 163 | 164 | return (y2 - y1) / (x2 - x1) 165 | } 166 | } 167 | 168 | fileprivate func calculateConstant(x1 : CGFloat, y1 : CGFloat, x2 : CGFloat, y2 : CGFloat) -> CGFloat { 169 | 170 | if x1 == x2 { 171 | 172 | return 0 173 | 174 | } else { 175 | 176 | return (y1*(x2 - x1) - x1*(y2 - y1)) / (x2 - x1) 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Swift-Animations/MessageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/13. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MessageView: BaseMessageView { 12 | 13 | fileprivate var blackBackgroundView : UIView! 14 | fileprivate var blackView : UIView! 15 | fileprivate var label : UILabel! 16 | 17 | required init(frame : CGRect) { 18 | 19 | super.init(frame: CGRect.zero) 20 | } 21 | 22 | required convenience init() { 23 | 24 | self.init(frame: CGRect.zero) 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | 29 | fatalError("init(coder:) has not been implemented") 30 | } 31 | 32 | override func setupSubViews() { 33 | 34 | blackBackgroundView = UIView.init(frame: (contentView?.bounds)!) 35 | blackBackgroundView.backgroundColor = UIColor.black 36 | blackBackgroundView.alpha = 0 37 | self.addSubview(blackBackgroundView) 38 | 39 | blackView = UIView.init() 40 | blackView.backgroundColor = UIColor.black.alpha(0.65) 41 | self.addSubview(blackView) 42 | 43 | label = UILabel.init() 44 | label.numberOfLines = 0 45 | label.font = UIFont.HeitiSC(15) 46 | label.textColor = UIColor.white 47 | label.text = self.messageObject as? String 48 | label.width = Screen.Width / 4 * 3 49 | label.sizeToFit() 50 | blackView.addSubview(label) 51 | 52 | blackView.bounds = CGRect.init(origin: CGPoint.zero, size: CGSize.init(width: label.width + 15, height: label.height + 15)) 53 | label.center = blackView.middlePoint 54 | blackView.center = self.middlePoint 55 | blackView.alpha = 0 56 | blackView.scale = 1.5 57 | } 58 | 59 | override func beginShowAnimation() { 60 | 61 | beforeStartShowValueConfig() 62 | delegate?.baseMessageViewWillAppear(self) 63 | UIView.animate(withDuration: 0.6, delay: 0, usingSpringWithDamping: 0.35, initialSpringVelocity: 0.9, options: .beginFromCurrentState, animations: { 64 | 65 | self.blackView.scale = 1 66 | 67 | }) { (success) in 68 | 69 | self.delegate?.baseMessageViewDidAppear(self) 70 | } 71 | 72 | UIView.animate(withDuration: 0.3) { 73 | 74 | self.blackBackgroundView.alpha = 0.1 75 | self.blackView.alpha = 1 76 | } 77 | } 78 | 79 | override func startHideAnimated() { 80 | 81 | self.blackBackgroundView.alpha = 0 82 | blackView.alpha = 0 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Swift-Animations/MixedColorProgressViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MixedColorProgressViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/21. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MixedColorProgressViewController: NormalTitleViewController { 12 | 13 | fileprivate var upView : UIView! 14 | fileprivate var upLabel : UILabel! 15 | fileprivate var downView : UIView! 16 | fileprivate var downLabel : UILabel! 17 | fileprivate var timer : Timer! 18 | 19 | override func viewDidLoad() { 20 | 21 | super.viewDidLoad() 22 | 23 | downView = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 17)) 24 | downView.center = (contentView?.middlePoint)! 25 | downView.layer.cornerRadius = 2 26 | downView.backgroundColor = UIColor.white 27 | downView.layer.masksToBounds = true 28 | contentView?.addSubview(downView) 29 | 30 | downLabel = UILabel(frame: downView.bounds) 31 | downLabel.font = UIFont.HelveticaNeueThin(12.0) 32 | downLabel.text = "YouXianMing - iOS Programmer" 33 | downLabel.textColor = UIColor.red 34 | downLabel.textAlignment = .center 35 | downView.layer.borderWidth = 0.5 36 | downView.layer.borderColor = UIColor.red.cgColor 37 | downView.addSubview(downLabel) 38 | 39 | upView = UIView(frame: CGRect(x: 0, y: 0, width: 220, height: 17)) 40 | upView.center = (contentView?.middlePoint)! 41 | upView.layer.cornerRadius = 2 42 | upView.backgroundColor = UIColor.red 43 | upView.layer.masksToBounds = true 44 | contentView?.addSubview(upView) 45 | 46 | upLabel = UILabel(frame: upView.bounds) 47 | upLabel.font = UIFont.HelveticaNeueThin(12.0) 48 | upLabel.text = "YouXianMing - iOS Programmer" 49 | upLabel.textColor = UIColor.white 50 | upLabel.textAlignment = .center 51 | upView.addSubview(upLabel) 52 | 53 | // Init timer. 54 | timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(MixedColorProgressViewController.timerEvent), userInfo: nil, repeats: true) 55 | } 56 | 57 | @objc func timerEvent() { 58 | 59 | UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 3, initialSpringVelocity: 0, options: UIView.AnimationOptions(), animations: { 60 | 61 | self.upView.width = CGFloat(arc4random() % 220) 62 | 63 | }, completion: nil) 64 | } 65 | 66 | override func viewDidDisappear(_ animated: Bool) { 67 | 68 | super.viewDidDisappear(animated) 69 | timer.invalidate() 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Swift-Animations/MoreInfoView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreInfoView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/18. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MoreInfoView: UIView { 12 | 13 | var imageView : UIImageView! 14 | 15 | override init(frame: CGRect) { 16 | 17 | super.init(frame : frame) 18 | 19 | layer.borderWidth = 0.5 20 | layer.borderColor = UIColor.black.cgColor 21 | layer.masksToBounds = true 22 | 23 | /* 24 | * -------------- * 25 | *-50->|-view-width-|<-50-* 26 | * -------------- * 27 | */ 28 | let rect = frame 29 | imageView = UIImageView(frame: CGRect(x: -50, y: 0, width: rect.size.width + 50 * 2, height: rect.size.height)) 30 | imageView.contentMode = .scaleAspectFill 31 | self.addSubview(imageView) 32 | } 33 | 34 | required init?(coder aDecoder: NSCoder) { 35 | 36 | fatalError("init(coder:) has not been implemented") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Swift-Animations/NormalTitleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NormalTitleViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class NormalTitleViewController: BaseCustomViewController { 12 | 13 | override func makeViewsConfig(viewsConfig: [String : ControllerBaseViewConfig]) { 14 | 15 | /// iPhoneX 16 | if Screen.CurrentScreen == Screen._375x812 { 17 | 18 | let titleViewConfig = viewsConfig[titleViewId] 19 | titleViewConfig?.frame = CGRect.init(x: 0, y: 0, width: Screen.Width, height: 64 + additionaliPhoneXTopSafeHeight) 20 | 21 | let contentViewConfig = viewsConfig[contentViewId] 22 | contentViewConfig?.frame = CGRect.init(x: 0, y: 64 + additionaliPhoneXTopSafeHeight, width: Screen.Width, height: Screen.Height - (64 + additionaliPhoneXTopSafeHeight)) 23 | } 24 | } 25 | 26 | override func setupSubViews() { 27 | 28 | // Title label. 29 | let headlinelabel = UILabel.init(frame: CGRect.init(x: 0, y: 0, width: Screen.Width, height: 64)) 30 | headlinelabel.font = UIFont.HeitiSC(20) 31 | headlinelabel.textAlignment = .center 32 | headlinelabel.textColor = UIColor.gray 33 | headlinelabel.text = self.title 34 | headlinelabel.bottom = (self.titleView?.height)! 35 | self.titleView?.addSubview(headlinelabel) 36 | 37 | // Back button. 38 | let button = UIButton(frame : CGRect(x: 0, y: 0, width: 100, height: 64)) 39 | button.center = CGPoint(x: 20, y: headlinelabel.centerY) 40 | button.imageView?.contentMode = .center 41 | button.setImage(UIImage(named: "backIcon"), for: UIControl.State()) 42 | button.setImage(UIImage(named: "backIcon_pre"), for: .highlighted) 43 | self.titleView?.addSubview(button) 44 | button.addTarget(self, action: #selector(NormalTitleViewController.popSelf), for: .touchUpInside) 45 | 46 | // Line view. 47 | titleView?.addSubview(UIView.CreateLine(CGRect(x: 0, y: titleView!.height - 0.5, width: Screen.Width, height: 0.5), lineColor: UIColor.gray.alpha(0.2))) 48 | } 49 | 50 | @objc func popSelf() { 51 | 52 | self.popViewControllerAnimated(true) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Swift-Animations/NotificationEvent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationEvent.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/19. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum NotificationEvent : String { 12 | 13 | case animationsListViewControllerFirstTimeLoadData = "animationsListViewControllerFirstTimeLoadData" 14 | case countDownTimeCellCountDown = "countDownTimeCellCountDown" 15 | 16 | var notificationName : String { 17 | 18 | get { return self.rawValue} 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Swift-Animations/PageFlipEffectController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PageFlipEffectController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/22. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PageFlipEffectController: NormalTitleViewController { 12 | 13 | fileprivate var math : Math = Math((x : 0, degree : 0), 14 | (x : Screen.Width, degree : 180)) 15 | fileprivate var layer : CALayer! 16 | 17 | override func viewDidLoad() { 18 | 19 | super.viewDidLoad() 20 | 21 | let image = UIImage(named: "pic_1") 22 | let size = Math.ResetFromSize((image?.size)!, withFixedWidth: Screen.Width / 2.0) 23 | 24 | layer = CALayer() 25 | layer.anchorPoint = CGPoint(x: 1.0, y: 0.5) 26 | layer.frame = CGRect(x: 0, y: 0, width: Screen.Width / 2, height: size.height) 27 | layer.allowsEdgeAntialiasing = true 28 | layer.position = CGPoint(x: Screen.Width / 2, y: contentView!.middleY) 29 | layer.contents = image?.cgImage 30 | layer.borderColor = UIColor.black.cgColor 31 | layer.borderWidth = 3.0 32 | layer.masksToBounds = true 33 | layer.transform = CATransform3DMakeRotation(Math.RadianFromDegree(0), 0, 1, 1) 34 | contentView?.layer.addSublayer(layer) 35 | 36 | let panGesture = UIPanGestureRecognizer(target: self, action: #selector(PageFlipEffectController.handlePan)) 37 | view.addGestureRecognizer(panGesture) 38 | } 39 | 40 | @objc fileprivate func handlePan(_ sender : UIPanGestureRecognizer) { 41 | 42 | let curPoint = sender.location(in: view) 43 | let x = curPoint.x 44 | 45 | // 初始化3D变换,获取默认值 46 | var perspectiveTransform = CATransform3DIdentity 47 | 48 | // 透视 49 | perspectiveTransform.m34 = -1.0 / 2000.0 50 | 51 | // 空间旋转 52 | perspectiveTransform = CATransform3DRotate(perspectiveTransform, Math.RadianFromDegree(x * math.k), 0, 1, 0) 53 | CATransaction.setDisableActions(true) 54 | layer.transform = perspectiveTransform 55 | 56 | layer.contents = UIImage(named: x >= Screen.Width / 2.0 ? "pic_2" : "pic_1")?.cgImage 57 | 58 | if sender.state == .ended { 59 | 60 | // 初始化3D变换,获取默认值 61 | var perspectiveTransform = CATransform3DIdentity 62 | 63 | // 透视 64 | perspectiveTransform.m34 = -1.0 / 2000.0 65 | 66 | // 空间旋转 67 | perspectiveTransform = CATransform3DRotate(perspectiveTransform, Math.RadianFromDegree(x >= Screen.Width / 2.0 ? 180 : 0), 0, 1, 0) 68 | 69 | CATransaction.setDisableActions(false) 70 | layer.transform = perspectiveTransform 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Swift-Animations/RootNavigationViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RootNavigationViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/11. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class RootNavigationViewController: BaseCustomNavigationController { 12 | 13 | override func viewDidLoad() { 14 | 15 | super.viewDidLoad() 16 | 17 | let lauchImageView = UIImageView(frame: self.view.bounds) 18 | lauchImageView.image = AppleSystemService.LaunchImage 19 | view.addSubview(lauchImageView) 20 | 21 | UIView.animate(withDuration: 1, delay: 1, options: UIView.AnimationOptions(), animations: { 22 | 23 | lauchImageView.scale = 1.3 24 | lauchImageView.alpha = 0 25 | 26 | }) { _ in 27 | 28 | lauchImageView.removeFromSuperview() 29 | DefaultNotificationCenter.PostMessageTo(NotificationEvent.animationsListViewControllerFirstTimeLoadData.notificationName) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Swift-Animations/RotateView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RotateView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/14. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // MARK: Public class : RotateView 12 | 13 | class RotateView: UIView { 14 | 15 | // MARK: Properties. 16 | 17 | var rotateDuration : TimeInterval = 0.25 18 | 19 | // MARK: Animation method. 20 | 21 | func changeToUpAnimated(_ animated : Bool) { 22 | 23 | UIView.animate(withDuration: (animated == true ? self.rotateDuration : 0.0), animations: { 24 | 25 | self.transform = self.defaultTransform 26 | }) 27 | } 28 | 29 | func changeToLeftAnimated(_ animated : Bool) { 30 | 31 | UIView.animate(withDuration: (animated == true ? self.rotateDuration : 0.0), animations: { 32 | 33 | self.transform = self.defaultTransform.rotated(by: CGFloat(-Double.pi / 2)) 34 | }) 35 | } 36 | 37 | func changeToRightAnimated(_ animated : Bool) { 38 | 39 | UIView.animate(withDuration: (animated == true ? self.rotateDuration : 0.0), animations: { 40 | 41 | self.transform = self.defaultTransform.rotated(by: CGFloat(Double.pi / 2)) 42 | }) 43 | } 44 | 45 | func changeToDownAnimated(_ animated : Bool) { 46 | 47 | UIView.animate(withDuration: (animated == true ? self.rotateDuration : 0.0), animations: { 48 | 49 | self.transform = self.defaultTransform.rotated(by: CGFloat(Double.pi)) 50 | }) 51 | } 52 | 53 | // MARK: Private value & func & system method. 54 | 55 | fileprivate var defaultTransform : CGAffineTransform! 56 | 57 | override init(frame: CGRect) { 58 | 59 | super.init(frame : frame) 60 | defaultTransform = self.transform 61 | } 62 | 63 | required init?(coder aDecoder: NSCoder) { 64 | 65 | fatalError("init(coder:) has not been implemented") 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Swift-Animations/ScrollImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollImageViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/18. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ScrollImageViewController: FullTitleVisualEffectViewController, UIScrollViewDelegate { 12 | 13 | fileprivate let viewTag : Int = 1000 14 | fileprivate var pictures : [UIImage] = [UIImage]() 15 | fileprivate var scrollView : UIScrollView! 16 | fileprivate var onceLinearEquation : Math! 17 | 18 | override func viewDidLoad() { 19 | 20 | super.viewDidLoad() 21 | 22 | onceLinearEquation = Math((x : 0, imageViewX : -50), 23 | (x : contentView!.width, imageViewX : 270 - 80)) 24 | pictures.append(UIImage(named: "1")!) 25 | pictures.append(UIImage(named: "2")!) 26 | pictures.append(UIImage(named: "3")!) 27 | pictures.append(UIImage(named: "4")!) 28 | pictures.append(UIImage(named: "5")!) 29 | 30 | scrollView = UIScrollView(frame: (contentView?.bounds)!) 31 | scrollView.delegate = self 32 | scrollView.isPagingEnabled = true 33 | scrollView.backgroundColor = UIColor.black 34 | scrollView.showsHorizontalScrollIndicator = false 35 | scrollView.bounces = false 36 | scrollView.contentSize = CGSize(width: CGFloat(pictures.count) * Screen.Width, height: Screen.Height) 37 | contentView?.addSubview(scrollView) 38 | 39 | for (i, image) in pictures.enumerated() { 40 | 41 | let showView = MoreInfoView(frame: CGRect(x: CGFloat(i) * Screen.Width, y: 0, width: Screen.Width, height: Screen.Height)) 42 | showView.imageView.image = image 43 | showView.tag = viewTag + i 44 | scrollView.addSubview(showView) 45 | } 46 | } 47 | 48 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 49 | 50 | let X = scrollView.contentOffset.x 51 | 52 | for i in 0 ..< pictures.count { 53 | 54 | let showView = scrollView.viewWithTag(viewTag + i) as! MoreInfoView 55 | showView.imageView.x = onceLinearEquation.k * (X - CGFloat(i) * Screen.Width) + onceLinearEquation.b 56 | } 57 | } 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /Swift-Animations/ShowLoadingView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShowLoadingView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/6/29. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ShowLoadingView: UIView { 12 | 13 | public private(set) var count: Int = 0 { 14 | 15 | didSet { 16 | 17 | if count >= 1 { 18 | 19 | isUserInteractionEnabled = true 20 | 21 | } else { 22 | 23 | isUserInteractionEnabled = false 24 | } 25 | } 26 | } 27 | 28 | override init(frame: CGRect) { 29 | 30 | super.init(frame: frame) 31 | self.isUserInteractionEnabled = false 32 | } 33 | 34 | required init?(coder aDecoder: NSCoder) { 35 | 36 | fatalError("init(coder:) has not been implemented") 37 | } 38 | 39 | /// push 一次导致 count + 1 40 | public func push() { 41 | 42 | count += 1 43 | } 44 | 45 | /// pop 一次导致 count - 1 46 | public func pop() { 47 | 48 | count -= 1 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Swift-Animations/ShowTextCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShowTextCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/30. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum EShowTextCellType : Int { 12 | 13 | case normalType, expendType 14 | } 15 | 16 | private let heitiSC : UIFont = UIFont.HeitiSC(16) 17 | private let numberOfLines : Int = 4 18 | 19 | class ShowTextCell: CustomCell { 20 | 21 | fileprivate var expendLabel : UILabel! 22 | fileprivate var normalLabel : UILabel! 23 | fileprivate var lineView : UIView! 24 | fileprivate var redView : UIView! 25 | 26 | override func buildSubview() { 27 | 28 | normalLabel = UILabel(frame: CGRect.zero) 29 | normalLabel.font = heitiSC 30 | addSubview(normalLabel) 31 | 32 | expendLabel = UILabel(frame: CGRect.zero) 33 | expendLabel.font = heitiSC 34 | expendLabel.textColor = UIColor.gray.alpha(0.5) 35 | addSubview(expendLabel) 36 | 37 | redView = UIView(frame: CGRect(x: 0, y: 20, width: 2, height: 14)) 38 | redView.backgroundColor = UIColor.red 39 | addSubview(redView) 40 | 41 | lineView = UIView.CreateLine(CGRect(x: 0, y: 0, width: Screen.Width, height: 0.5), lineColor: UIColor.black.alpha(0.1)) 42 | addSubview(lineView) 43 | } 44 | 45 | override func loadContent() { 46 | 47 | (indexPath as NSIndexPath?)?.row == 0 ? (lineView.isHidden = true) : (lineView.isHidden = false) 48 | changeStateWithCellType((dataAdapter?.cellType!)!) 49 | } 50 | 51 | fileprivate func changeStateWithCellType(_ type : Int) { 52 | 53 | let model = data as! ShowTextModel 54 | 55 | normalLabel.sizeToFitWithString(model.inputString!, width: Screen.Width - 30, numberOfLines: numberOfLines) 56 | normalLabel.left = 15 57 | normalLabel.top = 15 58 | 59 | expendLabel.sizeToFitWithString(model.inputString!, width: Screen.Width - 30, numberOfLines: 0) 60 | expendLabel.left = 15 61 | expendLabel.top = 15 62 | 63 | if type == EShowTextCellType.normalType.rawValue { 64 | 65 | expendLabel.alpha = 0 66 | normalLabel.alpha = 1 67 | redView.backgroundColor = UIColor.gray 68 | 69 | } else if type == EShowTextCellType.expendType.rawValue { 70 | 71 | expendLabel.alpha = 1 72 | normalLabel.alpha = 0 73 | redView.backgroundColor = UIColor.red 74 | } 75 | } 76 | 77 | override func selectedEvent() { 78 | 79 | let model = data as! ShowTextModel 80 | 81 | if dataAdapter?.cellType == EShowTextCellType.normalType.rawValue { 82 | 83 | self.dataAdapter?.cellType = EShowTextCellType.expendType.rawValue 84 | self.updateWithNewCellHeight(model.expendStringHeight!) 85 | 86 | UIView.animate(withDuration: 0.25, animations: { 87 | 88 | self.normalLabel.alpha = 0 89 | self.expendLabel.alpha = 1 90 | self.redView.backgroundColor = UIColor.red 91 | }) 92 | 93 | } else if dataAdapter?.cellType == EShowTextCellType.expendType.rawValue { 94 | 95 | self.dataAdapter?.cellType = EShowTextCellType.normalType.rawValue 96 | self.updateWithNewCellHeight(model.normalStringHeight!) 97 | 98 | UIView.animate(withDuration: 0.25, animations: { 99 | 100 | self.normalLabel.alpha = 1 101 | self.expendLabel.alpha = 0 102 | self.redView.backgroundColor = UIColor.gray.alpha(0.5) 103 | }) 104 | } 105 | } 106 | 107 | override class func HeightWithData(_ data : AnyObject?) -> CGFloat { 108 | 109 | let model = data as! ShowTextModel 110 | model.expendStringHeight = 15 + (model.inputString?.heightWithFont(heitiSC, fixedWidth: Screen.Width - 30))! + 15 111 | model.normalStringHeight = 15 + String.HeightWithFont(heitiSC) * CGFloat(numberOfLines) + 15 112 | return model.normalStringHeight! 113 | } 114 | } 115 | 116 | -------------------------------------------------------------------------------- /Swift-Animations/ShowTextModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShowTextModel.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/30. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ShowTextModel: NSObject { 12 | 13 | var inputString : String? 14 | var expendStringHeight : CGFloat? 15 | var normalStringHeight : CGFloat? 16 | 17 | convenience init(_ inputString : String) { 18 | 19 | self.init() 20 | self.inputString = inputString 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Swift-Animations/StoredValueTypeIs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StoredValueType.swift 3 | // SwiftDemo 4 | // 5 | // Created by YouXianMing on 2017/10/9. 6 | // Copyright © 2017年 TechCode. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class StoredValueTypeIs { 12 | 13 | private init() {} 14 | 15 | class var value : StoredValueTypeIs { 16 | 17 | get { 18 | 19 | return self.init() 20 | } 21 | } 22 | 23 | subscript(name : String) -> T? { 24 | 25 | get { 26 | 27 | return UserDefaults.standard.value(forKey: name) as? T 28 | } 29 | 30 | set (newValue) { 31 | 32 | UserDefaults.standard.set(newValue, forKey: name) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Swift-Animations/String+StringHeight.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+StringHeight.swift 3 | // StringHeight 4 | // 5 | // Created by YouXianMing on 16/8/30. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension String { 12 | 13 | /** 14 | Get the height with the string. 15 | 16 | - parameter attributes: The string attributes. 17 | - parameter fixedWidth: The fixed width. 18 | 19 | - returns: The height. 20 | */ 21 | func heightWithStringAttributes(_ attributes : [NSAttributedString.Key : Any], fixedWidth : CGFloat) -> CGFloat { 22 | 23 | guard self.count > 0 && fixedWidth > 0 else { 24 | 25 | return 0 26 | } 27 | 28 | let size = CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude) 29 | let text = self as NSString 30 | let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: attributes, context:nil) 31 | 32 | return rect.size.height 33 | } 34 | 35 | /** 36 | Get the height with font. 37 | 38 | - parameter font: The font. 39 | - parameter fixedWidth: The fixed width. 40 | 41 | - returns: The height. 42 | */ 43 | func heightWithFont(_ font : UIFont = UIFont.systemFont(ofSize: 18), fixedWidth : CGFloat) -> CGFloat { 44 | 45 | guard self.count > 0 && fixedWidth > 0 else { 46 | 47 | return 0 48 | } 49 | 50 | let size = CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude) 51 | let text = self as NSString 52 | let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font], context:nil) 53 | 54 | return rect.size.height 55 | } 56 | 57 | /** 58 | Get the height with font. 59 | 60 | - parameter font: The font. 61 | - parameter fixedWidth: The fixed width. 62 | 63 | - returns: The height. 64 | */ 65 | static func HeightWithFont(_ font : UIFont = UIFont.systemFont(ofSize: 18)) -> CGFloat { 66 | 67 | let string = "One" 68 | let size = CGSize(width: 200, height: CGFloat.greatestFiniteMagnitude) 69 | let text = string as NSString 70 | let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font], context:nil) 71 | 72 | return rect.size.height 73 | } 74 | 75 | /** 76 | Get the width with the string. 77 | 78 | - parameter attributes: The string attributes. 79 | 80 | - returns: The width. 81 | */ 82 | func widthWithStringAttributes(_ attributes : [NSAttributedString.Key : Any]) -> CGFloat { 83 | 84 | guard self.count > 0 else { 85 | 86 | return 0 87 | } 88 | 89 | let size = CGSize(width: CGFloat.greatestFiniteMagnitude, height: 0) 90 | let text = self as NSString 91 | let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: attributes, context:nil) 92 | 93 | return rect.size.width 94 | } 95 | 96 | /** 97 | Get the width with the string. 98 | 99 | - parameter font: The font. 100 | 101 | - returns: The string's width. 102 | */ 103 | func widthWithFont(_ font : UIFont = UIFont.systemFont(ofSize: 18)) -> CGFloat { 104 | 105 | guard self.count > 0 else { 106 | 107 | return 0 108 | } 109 | 110 | let size = CGSize(width: CGFloat.greatestFiniteMagnitude, height: 0) 111 | let text = self as NSString 112 | let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font], context:nil) 113 | 114 | return rect.size.width 115 | } 116 | } 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /Swift-Animations/StudentInfoCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentInfoCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/9. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class StudentInfoCell: CustomCell { 12 | 13 | fileprivate var nameLabel : UILabel! 14 | fileprivate var ageLabel : UILabel! 15 | 16 | override func setupCell() { 17 | 18 | self.selectionStyle = .none 19 | } 20 | 21 | override func buildSubview() { 22 | 23 | nameLabel = UILabel(frame: CGRect(x: 20, y: 0, width: 200, height: 60)) 24 | nameLabel.font = UIFont.AppleSDGothicNeoThin(20) 25 | self.addSubview(nameLabel) 26 | 27 | ageLabel = UILabel(frame: CGRect(x: Screen.Width - 220, y: 0, width: 200, height: 60)) 28 | ageLabel.textAlignment = .right 29 | ageLabel.font = UIFont.AppleSDGothicNeoThin(20) 30 | self.addSubview(ageLabel) 31 | 32 | self.addSubview(UIView.CreateLine(CGRect(x: 0, y: 59.5, width: Screen.Width, height: 0.5), lineColor: UIColor.gray.alpha(0.1))) 33 | } 34 | 35 | override func loadContent() { 36 | 37 | let model = data as! StudentModel 38 | 39 | nameLabel.text = model.name 40 | ageLabel.text = model.age.stringValue 41 | } 42 | 43 | override func selectedEvent() { 44 | 45 | showSelectedAnimation() 46 | } 47 | 48 | fileprivate func showSelectedAnimation() { 49 | 50 | let tempView = UIView(frame: CGRect(x: 0, y: 0, width: Screen.Width, height: 60)) 51 | tempView.backgroundColor = UIColor.cyan.alpha(0.2) 52 | tempView.alpha = 0 53 | self.addSubview(tempView) 54 | 55 | UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn, animations: { 56 | 57 | tempView.alpha = 0.8 58 | 59 | }) { (finished) in 60 | 61 | UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { 62 | 63 | tempView.alpha = 0 64 | 65 | }, completion: { (finished) in 66 | 67 | tempView.removeFromSuperview() 68 | }) 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Swift-Animations/StudentModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentModel.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/9. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class StudentModel: NSObject { 12 | 13 | var name : String = "" 14 | var age : NSNumber = 0 15 | 16 | convenience init(name : String, age : NSNumber) { 17 | 18 | self.init() 19 | self.name = name 20 | self.age = age 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Swift-Animations/SystemFontInfoController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SystemFontInfoController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/15. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SystemFontInfoController: NormalTitleViewController, UITableViewDelegate, UITableViewDataSource, CustomCellDelegate, CustomHeaderFooterViewDelegate { 12 | 13 | fileprivate var fontFamilyArray : [FontFamilyModel] = [] 14 | fileprivate var tableView : UITableView! 15 | 16 | override func viewDidLoad() { 17 | 18 | super.viewDidLoad() 19 | 20 | getFonts() 21 | 22 | tableView = UITableView.init(frame: (contentView?.bounds)!, style: .plain) 23 | tableView.delegate = self 24 | tableView.dataSource = self 25 | tableView.separatorStyle = .none 26 | tableView.rowHeight = FontCell.HeightWithData() 27 | tableView.sectionHeaderHeight = FontFamilyHeaderView.HeightWithData() 28 | contentView!.addSubview(tableView) 29 | 30 | // if #available(iOS 11.0, *) { 31 | // 32 | // tableView.contentInsetAdjustmentBehavior = .never 33 | // } 34 | 35 | FontCell.RegisterTo(tableView) 36 | FontFamilyHeaderView.RegisterTo(tableView) 37 | } 38 | 39 | // MARK: private 40 | 41 | private func getFonts() { 42 | 43 | for (familyName , fontNames) in FontInfomation.Shared.fontsDictionary() { 44 | 45 | let fontFamilyModel = FontFamilyModel.init(familyName: familyName) 46 | 47 | for fontName in fontNames { 48 | 49 | fontFamilyModel.fonts.append(FontModel.init(fontName: fontName)) 50 | } 51 | 52 | fontFamilyArray.append(fontFamilyModel) 53 | } 54 | } 55 | 56 | // MARK: UITableViewDelegate, UITableViewDataSource 57 | 58 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 59 | 60 | let cell = tableView.dequeueReusableCell(withIdentifier: "FontCell") as! CustomCell 61 | cell.data = fontFamilyArray[indexPath.section].fonts[indexPath.row] 62 | cell.delegate = self 63 | cell.loadContent() 64 | 65 | return cell 66 | } 67 | 68 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 69 | 70 | return fontFamilyArray[section].fonts.count 71 | } 72 | 73 | func numberOfSections(in tableView: UITableView) -> Int { 74 | 75 | return fontFamilyArray.count 76 | } 77 | 78 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 79 | 80 | let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "FontFamilyHeaderView") as! CustomHeaderFooterView 81 | headerView.data = fontFamilyArray[section] 82 | headerView.delegate = self 83 | headerView.loadContent() 84 | 85 | return headerView 86 | } 87 | 88 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 89 | 90 | tableView.selectedEventWithIndexPath(indexPath) 91 | } 92 | 93 | // MARK: CustomCellDelegate 94 | 95 | func customCell(_ cell: CustomCell?, event: Any?) { 96 | 97 | if event is FontModel { 98 | 99 | print((event as! FontModel).fontName!) 100 | } 101 | } 102 | 103 | // MARK: CustomHeaderFooterViewDelegate 104 | 105 | func customHeaderFooterView(_ headerFooterView: CustomHeaderFooterView?, event: AnyObject?) { 106 | 107 | if event is FontFamilyModel { 108 | 109 | print((event as! FontFamilyModel).familyName!) 110 | } 111 | } 112 | } 113 | 114 | class FontInfomation : NSObject { 115 | 116 | // MARK: private 117 | 118 | private var infos : [String : Array] 119 | 120 | private override init() { 121 | 122 | infos = [String : Array]() 123 | for familyName in UIFont.familyNames { 124 | 125 | infos[familyName] = UIFont.fontNames(forFamilyName: familyName) 126 | } 127 | } 128 | 129 | // MARK: public 130 | 131 | static let Shared = FontInfomation() 132 | 133 | func fontsDictionary() -> [String : Array] { 134 | 135 | return FontInfomation.Shared.infos 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Swift-Animations/TableViewTapAnimationCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewTapAnimationCell.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum TableViewTapAnimationCellState : Int { 12 | 13 | case kNormalState, kSelectedState 14 | } 15 | 16 | class TableViewTapAnimationCell: CustomCell { 17 | 18 | // MARK: Private var. 19 | 20 | fileprivate var titleLabel : UILabel! 21 | fileprivate var iconView : UIImageView! 22 | fileprivate var lineView : UIView! 23 | fileprivate var rectView : UIView! 24 | 25 | // MARK: Override CustomCell func. 26 | 27 | override func buildSubview() { 28 | 29 | rectView = UIView(frame: CGRect(x: Screen.Width - 60, y: 23, width: 35, height: 35)) 30 | rectView.layer.borderWidth = 1 31 | rectView.layer.borderColor = UIColor.gray.cgColor 32 | self.addSubview(rectView) 33 | 34 | iconView = UIImageView(frame: CGRect(x: Screen.Width - 62, y: 20, width: 40, height: 40)) 35 | iconView.image = UIImage(named: "plane") 36 | iconView.alpha = 0 37 | self.addSubview(iconView) 38 | 39 | titleLabel = UILabel(frame: CGRect(x: 30, y: 10, width: 300, height: 60)) 40 | titleLabel.font = UIFont.Avenir(20) 41 | titleLabel.textColor = UIColor.gray 42 | self.addSubview(titleLabel) 43 | 44 | lineView = UIView(frame: CGRect(x: 30, y: 70, width: 0, height: 2)) 45 | lineView.alpha = 0 46 | lineView.backgroundColor = UIColor.red 47 | self.addSubview(lineView) 48 | } 49 | 50 | override func loadContent() { 51 | 52 | let model = self.data as! TapAnimationModel 53 | titleLabel.text = model.name 54 | 55 | if model.selected == true { 56 | 57 | changeToState(.kSelectedState, animated: false) 58 | 59 | } else { 60 | 61 | changeToState(.kNormalState, animated: false) 62 | } 63 | } 64 | 65 | override func selectedEvent() { 66 | 67 | showSelectedAnimation() 68 | 69 | let model = self.data as! TapAnimationModel 70 | 71 | if model.selected == true { 72 | 73 | model.selected = false 74 | changeToState(.kNormalState, animated: true) 75 | 76 | } else { 77 | 78 | model.selected = true 79 | changeToState(.kSelectedState, animated: true) 80 | } 81 | 82 | if let delegate = delegate { 83 | 84 | delegate.customCell(self, event: model.name as AnyObject?) 85 | } 86 | } 87 | 88 | // MARK: Private func. 89 | 90 | fileprivate func changeToState(_ state : TableViewTapAnimationCellState, animated : Bool) { 91 | 92 | switch state { 93 | 94 | case .kNormalState: 95 | 96 | UIView.animate(withDuration: animated == false ? 0 : 0.5, delay: 0, usingSpringWithDamping: 7, initialSpringVelocity: 4, options: UIView.AnimationOptions(), animations: { 97 | 98 | if animated == true { 99 | 100 | self.iconView.transform = CGAffineTransform(a: 0.5, b: 0, c: 0, d: 0.5, tx: 0, ty: 0) 101 | } 102 | 103 | self.iconView.alpha = 0 104 | self.lineView.alpha = 0 105 | self.lineView.frame = CGRect(x: 30, y: 70, width: 0, height: 2) 106 | self.titleLabel.frame = CGRect(x: 30, y: 10, width: 300, height: 60) 107 | 108 | self.rectView.layer.borderColor = UIColor.gray.cgColor 109 | self.rectView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0) 110 | self.rectView.layer.cornerRadius = 0 111 | 112 | }, completion: nil) 113 | 114 | case .kSelectedState: 115 | 116 | if animated == true { 117 | 118 | self.iconView.transform = CGAffineTransform(a: 2, b: 0, c: 0, d: 2, tx: 0, ty: 0) 119 | } 120 | 121 | UIView.animate(withDuration: animated == false ? 0 : 0.5, delay: 0, usingSpringWithDamping: 7, initialSpringVelocity: 4, options: UIView.AnimationOptions(), animations: { 122 | 123 | self.iconView.transform = CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0) 124 | self.iconView.alpha = 1 125 | self.lineView.alpha = 1 126 | self.lineView.frame = CGRect(x: 30, y: 70, width: 200, height: 2) 127 | self.titleLabel.frame = CGRect(x: 30 + 50, y: 10, width: 300, height: 60) 128 | 129 | self.rectView.layer.borderColor = UIColor.red.cgColor 130 | self.rectView.transform = CGAffineTransform(a: 0.8, b: 0, c: 0, d: 0.8, tx: 0, ty: 0) 131 | self.rectView.layer.cornerRadius = 4 132 | 133 | }, completion: nil) 134 | } 135 | } 136 | 137 | fileprivate func showSelectedAnimation() { 138 | 139 | let tempView = UIView(frame: CGRect(x: 0, y: 0, width: Screen.Width, height: 80)) 140 | tempView.backgroundColor = UIColor.cyan.alpha(0.2) 141 | tempView.alpha = 0 142 | self.addSubview(tempView) 143 | 144 | UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseIn, animations: { 145 | 146 | tempView.alpha = 0.8 147 | 148 | }) { (finished) in 149 | 150 | UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: { 151 | 152 | tempView.alpha = 0 153 | 154 | }, completion: { (finished) in 155 | 156 | tempView.removeFromSuperview() 157 | }) 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Swift-Animations/TableViewTapAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewTapAnimationController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TableViewTapAnimationController: NormalTitleViewController, UITableViewDelegate, UITableViewDataSource, CustomCellDelegate { 12 | 13 | fileprivate var adapters : [CellDataAdapter] = [CellDataAdapter]() 14 | fileprivate var tableView : UITableView! 15 | 16 | override func viewDidLoad() { 17 | 18 | super.viewDidLoad() 19 | 20 | func appendModel(_ model : TapAnimationModel, cellHeight : CGFloat = 80) { 21 | 22 | adapters.append(TableViewTapAnimationCell.Adapter(data: model, cellHeight: cellHeight)) 23 | } 24 | 25 | // TableView. 26 | tableView = UITableView(frame: (contentView?.bounds)!) 27 | tableView.dataSource = self 28 | tableView.delegate = self 29 | tableView.separatorStyle = .none 30 | contentView?.addSubview(tableView!) 31 | 32 | // Register cell. 33 | TableViewTapAnimationCell.RegisterTo(tableView) 34 | 35 | // Data source. 36 | appendModel(TapAnimationModel(name: "YouXianMing", selected: false)) 37 | appendModel(TapAnimationModel(name: "Animations", selected: false)) 38 | appendModel(TapAnimationModel(name: "YoCelsius", selected: false)) 39 | appendModel(TapAnimationModel(name: "iOS-Progrommer", selected: false)) 40 | appendModel(TapAnimationModel(name: "Design-Patterns", selected: false)) 41 | appendModel(TapAnimationModel(name: "Arabia-Terra", selected: false)) 42 | appendModel(TapAnimationModel(name: "Swift", selected: false)) 43 | } 44 | 45 | // MARK: UITableView's delegate & dataSource. 46 | 47 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 48 | 49 | return adapters.count 50 | } 51 | 52 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 53 | 54 | let cell = tableView.dequeueCellAndLoadContentFromAdapter(adapters[(indexPath as NSIndexPath).row], indexPath: indexPath) 55 | cell.delegate = self 56 | 57 | return cell 58 | } 59 | 60 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 61 | 62 | tableView.selectedEventWithIndexPath(indexPath) 63 | } 64 | 65 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 66 | 67 | return adapters[(indexPath as NSIndexPath).row].cellHeight! 68 | } 69 | 70 | // MARK: CustomCellDelegate. 71 | 72 | func customCell(_ cell: CustomCell?, event: Any?) { 73 | 74 | print("\(String(describing: cell)) + \(String(describing: event))") 75 | } 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /Swift-Animations/TapAnimationModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TapAnimationModel.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TapAnimationModel: NSObject { 12 | 13 | var name : String = "" 14 | var selected : Bool = false 15 | 16 | convenience init(name : String, selected : Bool) { 17 | 18 | self.init() 19 | self.name = name 20 | self.selected = selected 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Swift-Animations/TapCellAnimationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TapCellAnimationController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/30. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TapCellAnimationController: NormalTitleViewController, UITableViewDelegate, UITableViewDataSource { 12 | 13 | fileprivate var tableView : UITableView! 14 | fileprivate var datas : [CellDataAdapter]! 15 | 16 | override func viewDidLoad() { 17 | 18 | super.viewDidLoad() 19 | 20 | datas = [CellDataAdapter]() 21 | 22 | tableView = UITableView(frame: (contentView?.bounds)!) 23 | tableView.delegate = self 24 | tableView.dataSource = self 25 | tableView.separatorStyle = .none 26 | ShowTextCell.RegisterTo(tableView) 27 | contentView?.addSubview(tableView) 28 | 29 | func addText(_ string : String) { 30 | 31 | let model = ShowTextModel(string) 32 | 33 | datas.append(ShowTextCell.Adapter( 34 | data : model, 35 | cellHeight : ShowTextCell.HeightWithData(model), 36 | type : EShowTextCellType.normalType.rawValue)) 37 | } 38 | 39 | GCDQueue.Main.excuteAfterDelay(0.5) { 40 | 41 | addText("AFNetworking is a delightful networking library for iOS and Mac OS X. It's built on top of the Foundation URL Loading System, extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed, feature-rich APIs that are a joy to use. Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac. Choose AFNetworking for your next project, or migrate over your existing projects—you'll be happy you did!") 42 | 43 | addText("黄色的树林里分出两条路,可惜我不能同时去涉足,我在那路口久久伫立,我向着一条路极目望去,直到它消失在丛林深处。但我却选了另外一条路,它荒草萋萋,十分幽寂,显得更诱人、更美丽,虽然在这两条小路上,都很少留下旅人的足迹,虽然那天清晨落叶满地,两条路都未经脚印污染。呵,留下一条路等改日再见!但我知道路径延绵无尽头,恐怕我难以再回返。也许多少年后在某个地方,我将轻声叹息把往事回顾,一片树林里分出两条路,而我选了人迹更少的一条,从此决定了我一生的道路。") 44 | 45 | addText("★タクシー代がなかったので、家まで歩いて帰った。★もし事故が発生した场所、このレバーを引いて列车を止めてください。(丁)为了清楚地表示出一个短语或句节,其后须标逗号。如:★この薬を、夜寝る前に一度、朝起きてからもう一度、饮んでください。★私は、空を飞ぶ鸟のように、自由に生きて行きたいと思った。*****为了清楚地表示词语与词语间的关系,须标逗号。标注位置不同,有时会使句子的意思发生变化。如:★その人は大きな音にびっくりして、横から飞び出した子供にぶつかった。★その人は、大きな音にびっくりして横から飞び出した子供に、ぶつかった。") 46 | 47 | addText("Two roads diverged in a yellow wood, And sorry I could not travel both And be one traveler, long I stood And looked down one as far as I could To where it bent in the undergrowth; Then took the other, as just as fair, And having perhaps the better claim, Because it was grassy and wanted wear; Though as for that the passing there Had worn them really about the same, And both that morning equally lay In leaves no step had trodden black. Oh, I kept the first for another day! Yet knowing how way leads on to way, I doubted if I should ever come back. I shall be telling this with a sigh Somewhere ages and ages hence: Two roads diverged in a wood, and I- I took the one less traveled by, And that has made all the difference.") 48 | 49 | var indexPaths = [IndexPath]() 50 | for i in 0 ..< self.datas.count { 51 | 52 | indexPaths.append(IndexPath(item: i, section: 0)) 53 | } 54 | self.tableView.insertRows(at: indexPaths, with: .fade) 55 | 56 | GCDQueue.Main.excuteAfterDelay(0.5, { 57 | 58 | let cell = self.tableView.cellForRow(at: IndexPath(item: 0, section: 0)) as! CustomCell 59 | cell.selectedEvent() 60 | }) 61 | } 62 | } 63 | 64 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 65 | 66 | return tableView.dequeueCellAndLoadContentFromAdapter(datas[(indexPath as NSIndexPath).row], indexPath: indexPath, tableView: tableView) 67 | } 68 | 69 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 70 | 71 | return datas.count 72 | } 73 | 74 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 75 | 76 | return datas[(indexPath as NSIndexPath).row].cellHeight! 77 | } 78 | 79 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 80 | 81 | tableView.selectedEventWithIndexPath(indexPath) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Swift-Animations/TimeModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeModel.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/9/4. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TimeModel: NSObject { 12 | 13 | var title : String? = "" 14 | var countdownTime : Int? = 0 15 | 16 | var currentTimeString : String? { 17 | 18 | get { 19 | 20 | if let val = countdownTime { 21 | 22 | if val <= 0 { 23 | 24 | return "00:00:00" 25 | 26 | } else { 27 | 28 | return String(format:"%02.f:%02.f:%02.f", 29 | CGFloat(val) / 3600, 30 | CGFloat(val).truncatingRemainder(dividingBy: 3600) / 60, 31 | CGFloat(val).truncatingRemainder(dividingBy: 60)) 32 | } 33 | 34 | } else { 35 | 36 | return Optional.none 37 | } 38 | } 39 | } 40 | 41 | convenience init(title : String, countdownTime : Int) { 42 | 43 | self.init() 44 | self.title = title 45 | self.countdownTime = countdownTime 46 | } 47 | 48 | func countDown() { 49 | 50 | countdownTime = countdownTime! - 1 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Swift-Animations/TranformFadeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TranformFadeView.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/20. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum TranformFadeViewAnimatedType : Int { 12 | 13 | case fade, show 14 | } 15 | 16 | // MARK: TranformFadeView 17 | 18 | class TranformFadeView: UIView { 19 | 20 | // MARK: Convenience init. 21 | 22 | convenience init(frame: CGRect, verticalCount : Int, horizontalCount : Int, fadeDuradtion : TimeInterval, animationGapDuration : TimeInterval) { 23 | 24 | self.init(frame: frame) 25 | self.verticalCount = verticalCount 26 | self.horizontalCount = horizontalCount 27 | self.fadeDuradtion = fadeDuradtion 28 | self.animationGapDuration = animationGapDuration 29 | self.makeConfigEffective() 30 | } 31 | 32 | // MARK: Properies & funcs. 33 | 34 | /// The content imageView's image. 35 | var image : UIImage? { 36 | 37 | get { return imageView.image} 38 | set(newVal) { imageView.image = newVal} 39 | } 40 | 41 | /// The content imageView's contentMode. 42 | var imageContentMode: UIView.ContentMode { 43 | 44 | get { return imageView.contentMode} 45 | set(newVal) { imageView.contentMode = newVal} 46 | } 47 | 48 | /// Vertical direction view's count, default is 3. 49 | var verticalCount : Int = 3 50 | 51 | /// Horizontal direction view's count, default is 4. 52 | var horizontalCount : Int = 4 53 | 54 | /// One of the maskView's animation duration, default is 1.0 55 | var fadeDuradtion : TimeInterval = 1 56 | 57 | /// The animation duration two subViews from allMaskView, default is 0.2 58 | var animationGapDuration : TimeInterval = 0.2 59 | 60 | /** 61 | Make the config effective. 62 | */ 63 | func makeConfigEffective() { 64 | 65 | guard verticalCount >= 1 && horizontalCount >= 1 else { 66 | 67 | return 68 | } 69 | 70 | if allMaskView != nil { 71 | 72 | allMaskView.removeFromSuperview() 73 | } 74 | 75 | countNumArray.removeAll() 76 | 77 | allMaskView = UIView(frame: bounds) 78 | mask = allMaskView 79 | 80 | let height = bounds.size.height 81 | let width = bounds.size.width 82 | let maskViewHeight = height / CGFloat(verticalCount) 83 | let maskViewWidth = width / CGFloat(horizontalCount) 84 | 85 | var count : Int = 0 86 | for horizontal in 0 ..< horizontalCount { 87 | 88 | for vertical in 0 ..< verticalCount { 89 | 90 | let frame = CGRect(x: maskViewWidth * CGFloat(horizontal), y: maskViewHeight * CGFloat(vertical), width: maskViewWidth, height: maskViewHeight) 91 | let maskView = UIView(frame: frame) 92 | maskView.tag = maskViewTag + count 93 | maskView.backgroundColor = UIColor.black 94 | allMaskView.addSubview(maskView) 95 | 96 | count = count + 1; 97 | } 98 | } 99 | 100 | maskViewCount = count 101 | 102 | for i in 0 ..< maskViewCount { 103 | 104 | countNumArray.append(i) 105 | } 106 | } 107 | 108 | /** 109 | Start transform to fade or show state. 110 | 111 | - parameter animated: Animated or not. 112 | - parameter transformTo: Show or fade. 113 | */ 114 | func start(animated : Bool, transformTo : TranformFadeViewAnimatedType) { 115 | 116 | if animated == true { 117 | 118 | let tmpFadeDuradtion = fadeDuradtion < 0 ? 1.0 : fadeDuradtion 119 | let tmpGapDuration = animationGapDuration < 0 ? 0.2 : animationGapDuration 120 | 121 | for i in 0 ..< maskViewCount { 122 | 123 | let tmpView = allMaskView.viewWithTag(maskViewTag + i) 124 | 125 | UIView.animate(withDuration: tmpFadeDuradtion, delay: TimeInterval(i) * tmpGapDuration, options: .curveLinear, animations: { 126 | 127 | switch transformTo { 128 | 129 | case .fade : 130 | tmpView?.alpha = 0.0 131 | 132 | case .show : 133 | tmpView?.alpha = 1.0 134 | } 135 | 136 | }, completion: nil) 137 | } 138 | 139 | } else { 140 | 141 | for i in 0 ..< maskViewCount { 142 | 143 | let tmpView = allMaskView.viewWithTag(maskViewTag + i) 144 | 145 | switch transformTo { 146 | 147 | case .fade : 148 | tmpView?.alpha = 0.0 149 | 150 | case .show : 151 | tmpView?.alpha = 1.0 152 | } 153 | } 154 | } 155 | } 156 | 157 | // MARK: System methods & Private properties 158 | 159 | fileprivate var imageView : UIImageView! 160 | fileprivate var allMaskView : UIView! 161 | fileprivate var maskViewCount : Int! 162 | fileprivate var countNumArray : [Int]! 163 | fileprivate var maskViewTag : Int = 1000 164 | 165 | override init(frame: CGRect) { 166 | 167 | super.init(frame: frame) 168 | 169 | imageView = UIImageView(frame: bounds) 170 | imageView.layer.masksToBounds = true 171 | countNumArray = [Int]() 172 | self.addSubview(imageView) 173 | } 174 | 175 | required init?(coder aDecoder: NSCoder) { 176 | 177 | fatalError("init(coder:) has not been implemented") 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Swift-Animations/TransformFadeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TransformFadeViewController.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/20. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private enum EType : Int { 12 | 13 | case typeOne, typeTwo 14 | } 15 | 16 | class TransformFadeViewController: FullTitleVisualEffectViewController { 17 | 18 | fileprivate var images : [UIImage]! 19 | fileprivate var tranformFadeViewOne : TranformFadeView! 20 | fileprivate var tranformFadeViewTwo : TranformFadeView! 21 | fileprivate var type : EType = .typeOne 22 | fileprivate var count : Int = 0 23 | fileprivate var gcdTimer : GCDTimer! 24 | 25 | override func viewDidLoad() { 26 | 27 | super.viewDidLoad() 28 | 29 | images = [UIImage]() 30 | images.append(UIImage(named: "5")!) 31 | images.append(UIImage(named: "1")!) 32 | images.append(UIImage(named: "2")!) 33 | images.append(UIImage(named: "3")!) 34 | images.append(UIImage(named: "4")!) 35 | 36 | tranformFadeViewOne = TranformFadeView(frame: contentView!.bounds, verticalCount: 3, horizontalCount: 12, 37 | fadeDuradtion: 1, animationGapDuration: 0.075) 38 | tranformFadeViewOne.imageContentMode = .scaleAspectFill 39 | tranformFadeViewOne.image = currentImage() 40 | tranformFadeViewOne.start(animated: false, transformTo: .show) 41 | contentView!.addSubview(tranformFadeViewOne) 42 | 43 | tranformFadeViewTwo = TranformFadeView(frame: contentView!.bounds, verticalCount: 3, horizontalCount: 12, 44 | fadeDuradtion: 1, animationGapDuration: 0.075) 45 | tranformFadeViewTwo.imageContentMode = .scaleAspectFill 46 | tranformFadeViewTwo.image = currentImage() 47 | tranformFadeViewTwo.start(animated: false, transformTo: .fade) 48 | contentView!.addSubview(tranformFadeViewTwo) 49 | 50 | gcdTimer = GCDTimer(in: GCDQueue.Main, delay: 1.0, interval: 8.0) 51 | weak var weakSelf = self 52 | gcdTimer.setTimerEventHandler { _ in 53 | 54 | if weakSelf?.type == .typeOne { 55 | 56 | weakSelf?.type = .typeTwo 57 | weakSelf?.contentView?.sendSubviewToBack((weakSelf?.tranformFadeViewTwo)!) 58 | weakSelf?.tranformFadeViewTwo.image = weakSelf?.currentImage() 59 | weakSelf?.tranformFadeViewTwo.start(animated: false, transformTo: .show) 60 | weakSelf?.tranformFadeViewOne.start(animated: true, transformTo: .fade) 61 | 62 | } else { 63 | 64 | weakSelf?.type = .typeOne 65 | weakSelf?.contentView?.sendSubviewToBack((weakSelf?.tranformFadeViewOne)!) 66 | weakSelf?.tranformFadeViewOne.image = weakSelf?.currentImage() 67 | weakSelf?.tranformFadeViewOne.start(animated: false, transformTo: .show) 68 | weakSelf?.tranformFadeViewTwo.start(animated: true, transformTo: .fade) 69 | } 70 | } 71 | 72 | gcdTimer.start() 73 | } 74 | 75 | fileprivate func currentImage() -> UIImage { 76 | 77 | count = (count + 1) % images.count 78 | return images[count] 79 | } 80 | 81 | override func viewDidDisappear(_ animated: Bool) { 82 | 83 | super.viewDidDisappear(animated) 84 | gcdTimer.destroy() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Swift-Animations/UIColor+Convenience.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Convenience.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/20. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIColor { 12 | 13 | /** 14 | Creates and returns a color object that has the same color space and component values as the receiver, but has the specified alpha component. 15 | 16 | - parameter alpha: The opacity value of the new UIColor object. 17 | 18 | - returns: The new UIColor object. 19 | */ 20 | func alpha(_ alpha : CGFloat) -> UIColor { 21 | 22 | return self.withAlphaComponent(alpha) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Swift-Animations/UIColor+HexColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+HexColor.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/14. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | #if os(iOS) || os(tvOS) 10 | 11 | import UIKit 12 | typealias HexColor = UIColor 13 | 14 | #else 15 | 16 | import Cocoa 17 | typealias HexColor = NSColor 18 | 19 | #endif 20 | 21 | private extension Int { 22 | 23 | func duplicate4bits() -> Int { 24 | 25 | return (self << 4) + self 26 | } 27 | } 28 | 29 | extension HexColor { 30 | 31 | // MARK: class func. 32 | 33 | class func Hex(_ hex6 : Int) -> HexColor { 34 | 35 | if (0x000000 ... 0xFFFFFF) ~= hex6 { 36 | 37 | return HexColor(hex6: hex6, alpha: 1)! 38 | 39 | } else { 40 | 41 | return HexColor.white 42 | } 43 | } 44 | 45 | class func Hex6(_ hex6 : Int, alpha : Float) -> HexColor { 46 | 47 | if (0x000000 ... 0xFFFFFF) ~= hex6 { 48 | 49 | return HexColor(hex6: hex6, alpha: alpha)! 50 | 51 | } else { 52 | 53 | return HexColor.white 54 | } 55 | } 56 | 57 | class func Hex6(_ hex6 : Int) -> HexColor { 58 | 59 | if (0x000000 ... 0xFFFFFF) ~= hex6 { 60 | 61 | return HexColor(hex6: hex6, alpha: 1)! 62 | 63 | } else { 64 | 65 | return HexColor.white 66 | } 67 | } 68 | 69 | class func Hex3(_ hex3 : Int, alpha : Float) -> HexColor { 70 | 71 | if (0x000 ... 0xFFF) ~= hex3 { 72 | 73 | return HexColor(hex3: hex3, alpha: alpha)! 74 | 75 | } else { 76 | 77 | return HexColor.white 78 | } 79 | } 80 | 81 | class func Hex3(_ hex3 : Int) -> HexColor { 82 | 83 | if (0x000 ... 0xFFF) ~= hex3 { 84 | 85 | return HexColor(hex3: hex3, alpha: 1)! 86 | 87 | } else { 88 | 89 | return HexColor.white 90 | } 91 | } 92 | 93 | // MARK: Private func. 94 | 95 | fileprivate convenience init?(hex3: Int, alpha: Float) { 96 | 97 | self.init(red : CGFloat(((hex3 & 0xF00) >> 8).duplicate4bits()) / 255.0, 98 | green : CGFloat(((hex3 & 0x0F0) >> 4).duplicate4bits()) / 255.0, 99 | blue : CGFloat(((hex3 & 0x00F) >> 0).duplicate4bits()) / 255.0, 100 | alpha : CGFloat(alpha)) 101 | } 102 | 103 | fileprivate convenience init?(hex6: Int, alpha: Float) { 104 | 105 | self.init(red : CGFloat((hex6 & 0xFF0000) >> 16) / 255.0, 106 | green : CGFloat((hex6 & 0x00FF00) >> 8) / 255.0, 107 | blue : CGFloat((hex6 & 0x0000FF) >> 0) / 255.0, 108 | alpha : CGFloat(alpha)) 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /Swift-Animations/UIFont+extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIFont+extension.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIFont { 12 | 13 | class func AppleSDGothicNeoThin(_ value : CGFloat) -> UIFont! { 14 | 15 | return self.init(name : "AppleSDGothicNeo-Thin", size: value) 16 | } 17 | 18 | class func Avenir(_ value : CGFloat) -> UIFont! { 19 | 20 | return self.init(name : "Avenir", size: value) 21 | } 22 | 23 | class func AvenirLight(_ value : CGFloat) -> UIFont! { 24 | 25 | return self.init(name : "Avenir-Light", size: value) 26 | } 27 | 28 | class func HeitiSC(_ value : CGFloat) -> UIFont! { 29 | 30 | return self.init(name : "Heiti SC", size: value) 31 | } 32 | 33 | class func HelveticaNeueThin(_ value : CGFloat) -> UIFont! { 34 | 35 | return self.init(name : "HelveticaNeue-Thin", size: value) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Swift-Animations/UILabel+SizeToFit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel+SizeToFit.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/30. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UILabel { 12 | 13 | public func sizeToFitWithWidth(_ width : CGFloat, numberOfLines : Int = 0) { 14 | 15 | var frame = self.frame 16 | frame.size.width = width 17 | self.frame = frame 18 | self.numberOfLines = numberOfLines 19 | sizeToFit() 20 | } 21 | 22 | public func sizeToFitWithString(_ string : String, width : CGFloat, numberOfLines : Int = 0) { 23 | 24 | text = string 25 | var newFrame = self.frame 26 | newFrame.size.width = width 27 | frame = newFrame 28 | self.numberOfLines = numberOfLines 29 | sizeToFit() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Swift-Animations/UIView+AnimationProperty.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+AnimationProperty.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/4. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private var scaleKey: UInt8 = 0 12 | private var angleKey: UInt8 = 0 13 | 14 | extension UIView { 15 | 16 | /// CGAffineTransformMakeScale 17 | var scale : CGFloat? { 18 | 19 | get { 20 | 21 | if let tmpValue = objc_getAssociatedObject(self, &scaleKey) as? CGFloat { 22 | 23 | return tmpValue 24 | 25 | } else { 26 | 27 | return 0 28 | } 29 | } 30 | 31 | set(newVal) { 32 | 33 | objc_setAssociatedObject(self, &scaleKey, newVal, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) 34 | transform = CGAffineTransform(scaleX: newVal!, y: newVal!) 35 | } 36 | } 37 | 38 | /// CGAffineTransformMakeRotation 39 | var angle : CGFloat? { 40 | 41 | get { 42 | 43 | if let tmpValue = objc_getAssociatedObject(self, &angleKey) as? CGFloat { 44 | 45 | return tmpValue 46 | 47 | } else { 48 | 49 | return 0 50 | } 51 | } 52 | 53 | set(newVal) { 54 | 55 | objc_setAssociatedObject(self, &angleKey, newVal, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) 56 | transform = CGAffineTransform(rotationAngle: newVal!) 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /Swift-Animations/UIView+CreateFrame.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+CreateFrame.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/8/7. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | /** 14 | Create Line view. 15 | 16 | - parameter frame: The frame you give. 17 | - parameter lineColor: The line color. 18 | 19 | - returns: Line view. 20 | */ 21 | class func CreateLine(_ frame : CGRect, lineColor : UIColor) -> UIView { 22 | 23 | let view = UIView(frame: frame) 24 | view.backgroundColor = lineColor 25 | view.isUserInteractionEnabled = false 26 | 27 | return view 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Swift-Animations/UIView+ScreensShot.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ScreensShot.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 16/9/5. 6 | // Copyright © 2016年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | /** 14 | Get the view's screen shot, this function may be called from any thread of your app. 15 | 16 | - returns: The screen shot's image. 17 | */ 18 | func screenShot() -> UIImage? { 19 | 20 | guard frame.size.height > 0 && frame.size.width > 0 else { 21 | 22 | return nil 23 | } 24 | 25 | UIGraphicsBeginImageContextWithOptions(frame.size, false, 0) 26 | layer.render(in: UIGraphicsGetCurrentContext()!) 27 | let image = UIGraphicsGetImageFromCurrentImageContext() 28 | UIGraphicsEndImageContext() 29 | 30 | return image 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Swift-Animations/UIWindow+keyWindow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIWindow+keyWindow.swift 3 | // Swift-Animations 4 | // 5 | // Created by YouXianMing on 2017/9/13. 6 | // Copyright © 2017年 YouXianMing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIWindow { 12 | 13 | class func getKeyWindow() -> UIWindow { 14 | 15 | return UIApplication.shared.keyWindow! 16 | } 17 | } 18 | --------------------------------------------------------------------------------