From 834c60da4592dbbe3db0b76b85a38058869a5864 Mon Sep 17 00:00:00 2001 From: JasonChengzi <3923240@qq.com> Date: Fri, 15 Jul 2016 17:07:03 +0800 Subject: [PATCH] Swift version --- MJAlertView-Swift/CGFloatExtension.swift | 41 +++ MJAlertView-Swift/NumberExtension.swift | 125 +++++++ MJAlertView-Swift/StringExtension.swift | 145 ++++++++ .../UIColorExtension-Instance.swift | 135 +++++++ .../UIViewExtension-MJAlertView.swift | 337 +++++++++++++++++ .../MJAlertView-Swift/CGFloatExtension.swift | 41 +++ .../MJAlertView-Swift/NumberExtension.swift | 125 +++++++ .../MJAlertView-Swift/StringExtension.swift | 145 ++++++++ .../UIColorExtension-Instance.swift | 135 +++++++ .../UIViewExtension-MJAlertView.swift | 337 +++++++++++++++++ .../project.pbxproj | 321 +++++++++++++++++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 17330 bytes .../xcschemes/MJAlertViewDemo-Swift.xcscheme | 91 +++++ .../xcschemes/xcschememanagement.plist | 22 ++ .../MJAlertViewDemo-Swift/AppDelegate.swift | 46 +++ .../AppIcon.appiconset/Contents.json | 38 ++ .../Base.lproj/LaunchScreen.storyboard | 27 ++ .../Base.lproj/Main.storyboard | 66 ++++ .../MJAlertViewDemo-Swift/Info.plist | 40 +++ .../MJAlertView-Swift/CGFloatExtension.swift | 43 +++ .../MJAlertView-Swift/NumberExtension.swift | 125 +++++++ .../MJAlertView-Swift/StringExtension.swift | 131 +++++++ .../UIColorExtension-Instance.swift | 135 +++++++ .../UIViewExtension-MJAlertView.swift | 339 ++++++++++++++++++ .../ViewController.swift | 40 +++ .../UserInterfaceState.xcuserstate | Bin 0 -> 9273 bytes .../xcschemes/MJAlertViewDemo.xcscheme | 101 ++++++ .../xcschemes/xcschememanagement.plist | 27 ++ .../Base.lproj/Main.storyboard | 5 +- 30 files changed, 3168 insertions(+), 2 deletions(-) create mode 100644 MJAlertView-Swift/CGFloatExtension.swift create mode 100644 MJAlertView-Swift/NumberExtension.swift create mode 100644 MJAlertView-Swift/StringExtension.swift create mode 100644 MJAlertView-Swift/UIColorExtension-Instance.swift create mode 100644 MJAlertView-Swift/UIViewExtension-MJAlertView.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertView-Swift/UIColorExtension-Instance.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.pbxproj create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/xcuserdata/JasonLee.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo-Swift.xcscheme create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/AppDelegate.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/LaunchScreen.storyboard create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/Main.storyboard create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Info.plist create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIColorExtension-Instance.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift create mode 100644 MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/ViewController.swift create mode 100644 MJAlertViewDemo/MJAlertViewDemo.xcodeproj/project.xcworkspace/xcuserdata/JasonLee.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo.xcscheme create mode 100644 MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/MJAlertView-Swift/CGFloatExtension.swift b/MJAlertView-Swift/CGFloatExtension.swift new file mode 100644 index 0000000..d89a4ed --- /dev/null +++ b/MJAlertView-Swift/CGFloatExtension.swift @@ -0,0 +1,41 @@ +// +// CGFloatExtension.swift +// ChildrenGuardian +// +// Created by Jason.Chengzi on 16/06/17. +// Copyright © 2016年 Hvit. All rights reserved. +// + +extension CGFloat { + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Int + var toInt : Int { return Int(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : CGFloat { return self / 2 } + ///相反数值 + var opposite : CGFloat { return -self } + ///绝对值 + var absolute : CGFloat { return abs(self) } + ///两倍数值 + var double : CGFloat { return self * 2 } + ///三倍数值 + var triple : CGFloat { return self * 3 } + ///平方数 + var square : CGFloat { return (self * self) } + ///立方数 + var cube : CGFloat { return (self * self * self) } + + static func MIN(lbs lbs : CGFloat, rbs : CGFloat) -> CGFloat { + if lbs > rbs { + return rbs + } else if lbs < rbs { + return lbs + } else { + return lbs + } + } +} \ No newline at end of file diff --git a/MJAlertView-Swift/NumberExtension.swift b/MJAlertView-Swift/NumberExtension.swift new file mode 100644 index 0000000..9a8078b --- /dev/null +++ b/MJAlertView-Swift/NumberExtension.swift @@ -0,0 +1,125 @@ +// +// NumberExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/20. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +extension Int { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : Int { return self / 2 } + ///相反数值 + var opposite : Int { return -self } + ///绝对值 + var absolute : Int { return abs(self) } + ///两倍数值 + var double : Int { return self * 2 } + ///三倍数值 + var triple : Int { return self * 3 } + ///平方数 + var square : Int { return (self * self) } + ///立方数 + var cube : Int { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Int, lessThan max : Int) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Int, equalAndLessThan max : Int) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} + +extension Float { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Int + var toInt : Int { return Int(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : Float { return self / 2 } + ///相反数值 + var opposite : Float { return -self } + ///绝对值 + var absolute : Float { return abs(self) } + ///两倍数值 + var double : Float { return self * 2 } + ///三倍数值 + var triple : Float { return self * 3 } + ///平方数 + var square : Float { return (self * self) } + ///立方数 + var cube : Float { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Float, lessThan max : Float) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Float, equalAndLessThan max : Float) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} + +extension Double { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Int + var toInt : Int { return Int(self) } + + ///一半数值 + var half : Double { return self / 2 } + ///相反数值 + var opposite : Double { return -self } + ///绝对值 + var absolute : Double { return abs(self) } + ///两倍数值 + var double : Double { return self * 2 } + ///三倍数值 + var triple : Double { return self * 3 } + ///平方数 + var square : Double { return (self * self) } + ///立方数 + var cube : Double { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Double, lessThan max : Double) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Double, equalAndLessThan max : Double) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} \ No newline at end of file diff --git a/MJAlertView-Swift/StringExtension.swift b/MJAlertView-Swift/StringExtension.swift new file mode 100644 index 0000000..6870118 --- /dev/null +++ b/MJAlertView-Swift/StringExtension.swift @@ -0,0 +1,145 @@ +// +// StringExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/17. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +extension String { + ///获取NSString对象 + var toNSString : NSString { + return NSString(string: self) + } + ///获取字符串长度 + var length : Int { + return self.characters.count + } + + ///判断是否为整数 + var isInt : Bool { + if Int(self) != nil { + return true + } else { + return false + } + } + ///判断是否为浮点数 + var isFloat : Bool { + if Float(self) != nil { + return true + } else { + return false + } + } + ///判断是否为长浮点数 + var isDouble : Bool { + if Double(self) != nil { + return true + } else { + return false + } + } + + ///尝试转换为整型 + var nullableInt : Int? { + return Int(self) + } + ///尝试转换为浮点数 + var nullableFloat : Float? { + return Float(self) + } + ///尝试转换为长浮点数 + var nullableDouble : Double? { + return Double(self) + } + + ///强制转换为整型,失败返回0 + var toInt : Int { + return Int(self) ?? 0 + } + ///强制转换为浮点数,失败返回0 + var toFloat : Float { + return Float(self) ?? Float(0) + } + ///强制转换为长浮点数,失败返回0 + var toDouble : Double { + return Double(self) ?? Double(0) + } + + ///获取第一个字母 + var firstLetter : String { + var ret = "" + if !self.canBeConvertedToEncoding(NSASCIIStringEncoding) { + ret = self.letters.firstLetter + } else { + ret = "\("\(self.characters.first)" ?? "")" + } + return ret + } + + var letters : String { + let str = NSMutableString(string: self) + if CFStringTransform(str, nil, kCFStringTransformMandarinLatin, false) { + if CFStringTransform(str, nil, kCFStringTransformStripDiacritics, false) { + return str as String + } + } + return self + } + + func getFirstLetter() -> String { + return self.firstLetter + } + + ///通过字体获取字符串的尺寸 + func sizeWithFont(font : UIFont) -> CGSize { + //如果没有内容 + guard self.isEmpty == false else { + return CGSizeZero + } + return self.toNSString.sizeWithAttributes([NSFontAttributeName : font]) + } + ///通过字体和固定宽度计算字符串的高度 + func heightWithWidth(width : CGFloat, font : UIFont) -> CGFloat { + //如果没有内容 + guard self.isEmpty == false else { + return CGFloat(0) + } + return self.sizeWithFont(font).width / width + } + ///截取指定长度的字符串 + func substringWithStartPosition(start : Int, andEndPosition end : Int) -> String { + return self.substringWithRange(self.startIndex.advancedBy(start).. Bool { + let regex : NSRegularExpression? = try? NSRegularExpression(pattern: pattern.pattern, options: NSRegularExpressionOptions.CaseInsensitive) + if let matches = regex?.matchesInString(self, options: [], range: NSMakeRange(0, self.toNSString.length)) { + return matches.count > 0 + } else { + return false + } + } + + //MD5加密字符串 + func md5() -> String { + let str = self.cStringUsingEncoding(NSUTF8StringEncoding) + let strLen = CUnsignedInt(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) + let digestLen = Int(CC_MD5_DIGEST_LENGTH) + let result = UnsafeMutablePointer.alloc(digestLen) + CC_MD5(str!, strLen, result) + let hash = NSMutableString() + for i in 0..= 0.5 { + return true + } else { + return false + } + } + + ///便捷颜色。色相、饱和度、亮度、通透度 + class func colorWithHue(hue : CGFloat, saturation : CGFloat, brightness : CGFloat, andAlpha alpha : CGFloat) -> UIColor { + return UIColor( + hue: hue / 256, + saturation: saturation / 256, + brightness: brightness / 256, + alpha: alpha + ) + } + class func colorWithHue(hue : CGFloat, saturation : CGFloat, brightness : CGFloat) -> UIColor { + return colorWithHue(hue, saturation: saturation, brightness: brightness, andAlpha: 1) + } + ///便捷颜色初始化 + class func colorWithRed(red: CGFloat, green: CGFloat, blue: CGFloat, andAlpha alpha: CGFloat) -> UIColor { + return UIColor( + red: (red / 255.0), + green: (green / 255.0), + blue: (blue / 255.0), + alpha: alpha + ) + } + class func colorWithRed(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor { + return UIColor.colorWithRed( + red, + green: green, + blue: blue, + andAlpha: 1 + ) + } + ///16进制初始化颜色 + class func colorWithHex(hex h: Int, andAlpha alpha: CGFloat) -> UIColor { + let red = CGFloat(((h & 0xFF0000) >> 16)) + let green = CGFloat(((h & 0xFF00) >> 8)) + let blue = CGFloat((h & 0xFF)) + + return UIColor.colorWithRed( + red, green: + green, + blue: blue, + andAlpha: alpha + ) + } + class func colorWithHex(hex h: Int) -> UIColor { + return UIColor.colorWithHex(hex: h, andAlpha: 1) + } + class func colorWithHex(hex : String, andAlpha alpha : CGFloat) -> UIColor { + var cString : String = hex.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).uppercaseString + + if cString.hasPrefix("#") { + cString = cString.substringFromIndex(cString.startIndex.advancedBy(1)) + } + + if cString.characters.count != 6 { + return UIColor.grayColor() + } + + var rgbValue : UInt32 = 0 + NSScanner(string: cString).scanHexInt(&rgbValue) + + return UIColor( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: alpha + ) + } + class func colorWithHex(hex : String) -> UIColor { + return UIColor.colorWithHex(hex, andAlpha: 1) + } + class func randomColor() -> UIColor { + return UIColor( + hue: (CGFloat(arc4random()) % 256 / 256.0), + saturation: (CGFloat(arc4random()) % 128 / 256.0) + 0.5, + brightness: (CGFloat(arc4random()) % 128 / 256.0) + 0.5, + alpha: 1 + ) + } +} diff --git a/MJAlertView-Swift/UIViewExtension-MJAlertView.swift b/MJAlertView-Swift/UIViewExtension-MJAlertView.swift new file mode 100644 index 0000000..a11026b --- /dev/null +++ b/MJAlertView-Swift/UIViewExtension-MJAlertView.swift @@ -0,0 +1,337 @@ +// +// UIViewExtension-MJAlertView.swift +// ChildrenGuardian +// +// Created by Jason.Chengzi on 7/13/16. +// Copyright © 2016 Hvit. All rights reserved. +// + +import UIKit +import QuartzCore + +private let MJAV_APPDELEGATE = UIApplication.sharedApplication().delegate + +private let MJAV_FONT_SIZE_LABEL = 18.toCGFloat +private let MJAV_FONT_SIZE_CANCEL = 13.toCGFloat + +private let MJAV_NOTIFIER_LABEL_FONT = UIFont(name: "HelveticaNeue-Light", size: MJAV_FONT_SIZE_LABEL) +private let MJAV_NOTIFIER_CANCEL_FONT = UIFont(name: "HelveticaNeue", size: MJAV_FONT_SIZE_CANCEL) + +private let MJAV_Tag = 181200 +private let MJAV_xPadding = 18.0.toCGFloat +private let MJAV_Height_Label = 45.0.toCGFloat +private let MJAV_Height_Cancel_Button = 30.0.toCGFloat +private let MJAV_Height_Separator = 1.0.toCGFloat +private let MJAV_Height_FromBottom = 70.0.toCGFloat +private let MJAV_Width_Max = 290.0.toCGFloat + +enum MJAlertViewStyle { + case Success + case Error + case Warn + case Info + case SubjectTheme + case Default + + var backgroundColor : UIColor { + switch self { + case .Success: + return UIColor.colorWithHex(hex: 0x2ecc71) + case .Error: + return UIColor.colorWithHex(hex: 0xc0392b) + case .Warn: + return UIColor.colorWithHex(hex: 0xe67e22) + case .Info: + return UIColor.colorWithHex(hex: 0x2980b9) + case .SubjectTheme: + return AppearenceDefaults.COLOR_THEME + case .Default: + return UIColor.blackColor().colorWithAlphaComponent(0.8) + } + } + + var textColor : UIColor { + switch self { + case .Success: + return UIColor.whiteColor() + case .Error: + return UIColor.whiteColor() + case .Warn: + return UIColor.whiteColor() + case .Info: + return UIColor.whiteColor() + case .SubjectTheme: +// return UIColor.whiteColor() + if self.backgroundColor.isLight { + return UIColor.blackColor() + } else { + return UIColor.whiteColor() + } + case .Default: + return UIColor.whiteColor() + } + } +} + +extension UIView { + class func makeSuccessNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Success) + } + class func makeWarnNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Warn) + } + class func makeErrorNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Error) + } + class func makeInfoNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Info) + } + class func makeAlertViewWithText(text : String, type : MJAlertViewStyle = .Default) { + + let shouldDismiss = true + + if let screenBounds = MJAV_APPDELEGATE?.window!!.bounds { + let attributes : [String : AnyObject] = [NSFontAttributeName : MJAV_NOTIFIER_LABEL_FONT ?? UIFont.systemFontOfSize(MJAV_FONT_SIZE_LABEL)] + + let height = MJAV_Height_Label + let width = CGFloat.max + let notifierRect = text.toNSString.boundingRectWithSize( + CGSize( + width: width, + height: height + ), + options: NSStringDrawingOptions.UsesLineFragmentOrigin, + attributes: attributes, + context: nil + ) + let notifierWidth = CGFloat.MIN(lbs: CGRectGetWidth(notifierRect) + MJAV_xPadding.double, rbs: MJAV_Width_Max) + let xOffset = (CGRectGetWidth(screenBounds) - notifierWidth).half + + let notifierHeight = MJAV_Height_Label + +// if !shouldDismiss { +// notifierHeight += (MJAV_Height_Cancel_Button + MJAV_Height_Separator) +// } + + let yOffset = CGRectGetHeight(screenBounds) - notifierHeight - MJAV_Height_FromBottom + + let finalFrame = CGRect(x: xOffset, y: yOffset, width: notifierWidth, height: notifierHeight) + + let notifierView = isNotifierExistedAlready() + + if let view = notifierView { + updateNotifierWithAnimation(notifierView, andText: text, andCompletion: { (finished) in + var atLastFrame = finalFrame + atLastFrame.origin.y = finalFrame.origin.y + 8 + view.frame = atLastFrame + + var textLabel : UILabel? + for subview in view.subviews { + if subview is UILabel { + textLabel = subview as? UILabel + } + + if subview is UIImageView || subview is UIButton { + subview.removeFromSuperview() + } + } + + textLabel?.text = text + textLabel?.frame = CGRect(x: MJAV_xPadding, y: 0, width: notifierWidth - MJAV_xPadding.double, height: MJAV_Height_Label) + + if !shouldDismiss { + let separatorImageView = UIImageView(frame: CGRect(x: 0, y: CGRectGetHeight(textLabel!.frame), width: CGRectGetWidth(view.frame), height: MJAV_Height_Separator)) + separatorImageView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) + view.addSubview(separatorImageView) + + let cancelButton = UIButton(type: UIButtonType.Custom) + cancelButton.frame = CGRect(x: 0, y: CGRectGetMaxY(separatorImageView.frame), width: CGRectGetWidth(view.frame), height: MJAV_Height_Cancel_Button) +// cancelButton.setNormalTitleColor(UIColor.whiteColor()) + cancelButton.backgroundColor = UIColor.colorWithHex(hex: 0x000000) + cancelButton.addTarget(self, action: #selector(UIView.buttonCancelClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside) + cancelButton.titleLabel?.font = MJAV_NOTIFIER_CANCEL_FONT + view.addSubview(cancelButton) + } + + UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + view.alpha = 1 + view.frame = finalFrame + }, completion: nil) + }) + + if shouldDismiss { + performSelector(#selector(UIView.dismissMJNotifier), withObject: nil, afterDelay: 2.0) + } + } else { + let notifierView = UIView(frame: CGRect(x: xOffset, y: CGRectGetHeight(screenBounds), width: notifierWidth, height: notifierHeight)) +// notifierView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) + notifierView.backgroundColor = type.backgroundColor + notifierView.tag = MJAV_Tag + notifierView.clipsToBounds = true + notifierView.layer.cornerRadius = 5 + + MJAV_APPDELEGATE?.window??.addSubview(notifierView) + MJAV_APPDELEGATE?.window??.bringSubviewToFront(notifierView) + + let textLabel = UILabel(frame: CGRect(x: MJAV_xPadding, y: 0, width: notifierWidth - MJAV_xPadding.double, height: MJAV_Height_Label)) + textLabel.adjustsFontSizeToFitWidth = true + textLabel.backgroundColor = UIColor.clearColor() + textLabel.textAlignment = .Center +// textLabel.textColor = UIColor.colorWithHex(hex: 0xFFFFFF) + textLabel.textColor = type.textColor + textLabel.font = MJAV_NOTIFIER_LABEL_FONT + textLabel.minimumScaleFactor = 0.7 + textLabel.text = text + notifierView.addSubview(textLabel) + + if shouldDismiss { + self.performSelector(#selector(UIView.dismissMJNotifier), withObject: nil, afterDelay: 2) +// } else { +// let separatorImageView = UIImageView(frame: CGRect(x: 0, y: CGRectGetHeight(textLabel.frame), width: CGRectGetWidth(notifierView.frame), height: MJAV_Height_Separator)) +// separatorImageView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) +// notifierView.addSubview(separatorImageView) +// +// let cancelButton = UIButton(type: UIButtonType.Custom) +// cancelButton.frame = CGRect(x: 0, y: CGRectGetMaxY(separatorImageView.frame), width: CGRectGetWidth(notifierView.frame), height: MJAV_Height_Cancel_Button) +// cancelButton.backgroundColor = UIColor.colorWithHex(hex: 0x000000) +// cancelButton.addTarget(self, action: #selector(UIView.buttonCancelClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside) +// cancelButton.titleLabel?.font = MJAV_NOTIFIER_CANCEL_FONT +// notifierView.addSubview(cancelButton) + } + + self.startEntryAnimation(notifierView, withFinalFrame: finalFrame) + } + } + } + class func dismissMJNotifier() { + NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: #selector(UIView.dismissMJNotifier), object: nil) + + var notifier : UIView? + + for subview in MJAV_APPDELEGATE!.window!!.subviews { + if subview.tag == MJAV_Tag && subview.isKindOfClass(UIView.self) { + notifier = subview + } + } + + startExitAnimation(notifier) + } +} + +private extension UIView { + class func isNotifierExistedAlready() -> UIView? { + NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: #selector(UIView.dismissMJNotifier), object: nil) + + var notifier : UIView? + + for subview in MJAV_APPDELEGATE!.window!!.subviews { + if subview.tag == MJAV_Tag && subview.isKindOfClass(UIView.self) { + notifier = subview + } + } + + return notifier + } + + @objc class func buttonCancelClicked(sender : UIButton) { + dismissMJNotifier() + } + + class func updateNotifierWithAnimation(notifierView : UIView?, andText text : String, andCompletion completion : ((finished : Bool) -> Void)?) { + if let view = notifierView { + var finalFrame = view.frame + finalFrame.origin.y = finalFrame.origin.y + 8 + + UIView.animateWithDuration( 0.2, + delay: 0, + options: UIViewAnimationOptions.CurveEaseOut, + animations: { + view.alpha = 0 + view.frame = finalFrame + }, + completion: { (finished : Bool) in + completion?(finished: finished) + } + ) + } + } + + class func startEntryAnimation(notifierView : UIView?, withFinalFrame finalFrame : CGRect) { + + if let view = notifierView { + + var mutableFinalFrame = finalFrame + + let finalYOffset = mutableFinalFrame.origin.y + mutableFinalFrame.origin.y = finalFrame.origin.y - 15 + + let transform = transformWithXAxisValue(-0.1, andAngle: 45) + view.layer.zPosition = 400 + view.layer.transform = transform + + UIView.animateWithDuration(0.2, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + + view.frame = mutableFinalFrame + + let anotherTransform = transformWithXAxisValue(0.1, andAngle: 15) + view.layer.zPosition = 400 + view.layer.transform = anotherTransform + + }, completion: { (finished : Bool) in + UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { + + var atLastFrame = mutableFinalFrame + atLastFrame.origin.y = finalYOffset + view.frame = atLastFrame + + let transform = self.transformWithXAxisValue(0.0, andAngle: 90) + view.layer.zPosition = 400 + view.layer.transform = transform + + }, completion: nil) + }) + } + + } + + class func startExitAnimation(notifierView : UIView?) { + + if let view = notifierView { + + let screenBounds = MJAV_APPDELEGATE!.window!!.bounds + + var notifierFrame = view.frame + let finalYOffset = notifierFrame.origin.y - 12 + notifierFrame.origin.y = finalYOffset + + UIView.animateWithDuration(0.3, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + view.frame = notifierFrame + let transform = transformWithXAxisValue(0.1, andAngle: 30) + view.layer.zPosition = 400 + view.layer.transform = transform + }, completion: { (finished : Bool) in + UIView.animateWithDuration(0.15, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { + var atLastFrame = view.frame + atLastFrame.origin.y = CGRectGetHeight(screenBounds) + view.frame = atLastFrame + + let transform = transformWithXAxisValue(-1, andAngle: 90) + view.layer.zPosition = 400 + view.layer.transform = transform + }, completion: { (finished : Bool) in + view.removeFromSuperview() + }) + }) + } + } + + class func transformWithXAxisValue(xValue : CGFloat, andAngle angle : CGFloat) -> CATransform3D { + var transform = CATransform3DIdentity + + transform.m34 = 1.0 / -1000 + + transform = CATransform3DRotate(transform, angle * M_PI.toCGFloat / 180, xValue, 0, 0) + + return transform + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift b/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift new file mode 100644 index 0000000..d89a4ed --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift @@ -0,0 +1,41 @@ +// +// CGFloatExtension.swift +// ChildrenGuardian +// +// Created by Jason.Chengzi on 16/06/17. +// Copyright © 2016年 Hvit. All rights reserved. +// + +extension CGFloat { + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Int + var toInt : Int { return Int(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : CGFloat { return self / 2 } + ///相反数值 + var opposite : CGFloat { return -self } + ///绝对值 + var absolute : CGFloat { return abs(self) } + ///两倍数值 + var double : CGFloat { return self * 2 } + ///三倍数值 + var triple : CGFloat { return self * 3 } + ///平方数 + var square : CGFloat { return (self * self) } + ///立方数 + var cube : CGFloat { return (self * self * self) } + + static func MIN(lbs lbs : CGFloat, rbs : CGFloat) -> CGFloat { + if lbs > rbs { + return rbs + } else if lbs < rbs { + return lbs + } else { + return lbs + } + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift b/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift new file mode 100644 index 0000000..9a8078b --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift @@ -0,0 +1,125 @@ +// +// NumberExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/20. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +extension Int { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : Int { return self / 2 } + ///相反数值 + var opposite : Int { return -self } + ///绝对值 + var absolute : Int { return abs(self) } + ///两倍数值 + var double : Int { return self * 2 } + ///三倍数值 + var triple : Int { return self * 3 } + ///平方数 + var square : Int { return (self * self) } + ///立方数 + var cube : Int { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Int, lessThan max : Int) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Int, equalAndLessThan max : Int) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} + +extension Float { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Int + var toInt : Int { return Int(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : Float { return self / 2 } + ///相反数值 + var opposite : Float { return -self } + ///绝对值 + var absolute : Float { return abs(self) } + ///两倍数值 + var double : Float { return self * 2 } + ///三倍数值 + var triple : Float { return self * 3 } + ///平方数 + var square : Float { return (self * self) } + ///立方数 + var cube : Float { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Float, lessThan max : Float) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Float, equalAndLessThan max : Float) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} + +extension Double { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Int + var toInt : Int { return Int(self) } + + ///一半数值 + var half : Double { return self / 2 } + ///相反数值 + var opposite : Double { return -self } + ///绝对值 + var absolute : Double { return abs(self) } + ///两倍数值 + var double : Double { return self * 2 } + ///三倍数值 + var triple : Double { return self * 3 } + ///平方数 + var square : Double { return (self * self) } + ///立方数 + var cube : Double { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Double, lessThan max : Double) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Double, equalAndLessThan max : Double) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift b/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift new file mode 100644 index 0000000..6870118 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift @@ -0,0 +1,145 @@ +// +// StringExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/17. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +extension String { + ///获取NSString对象 + var toNSString : NSString { + return NSString(string: self) + } + ///获取字符串长度 + var length : Int { + return self.characters.count + } + + ///判断是否为整数 + var isInt : Bool { + if Int(self) != nil { + return true + } else { + return false + } + } + ///判断是否为浮点数 + var isFloat : Bool { + if Float(self) != nil { + return true + } else { + return false + } + } + ///判断是否为长浮点数 + var isDouble : Bool { + if Double(self) != nil { + return true + } else { + return false + } + } + + ///尝试转换为整型 + var nullableInt : Int? { + return Int(self) + } + ///尝试转换为浮点数 + var nullableFloat : Float? { + return Float(self) + } + ///尝试转换为长浮点数 + var nullableDouble : Double? { + return Double(self) + } + + ///强制转换为整型,失败返回0 + var toInt : Int { + return Int(self) ?? 0 + } + ///强制转换为浮点数,失败返回0 + var toFloat : Float { + return Float(self) ?? Float(0) + } + ///强制转换为长浮点数,失败返回0 + var toDouble : Double { + return Double(self) ?? Double(0) + } + + ///获取第一个字母 + var firstLetter : String { + var ret = "" + if !self.canBeConvertedToEncoding(NSASCIIStringEncoding) { + ret = self.letters.firstLetter + } else { + ret = "\("\(self.characters.first)" ?? "")" + } + return ret + } + + var letters : String { + let str = NSMutableString(string: self) + if CFStringTransform(str, nil, kCFStringTransformMandarinLatin, false) { + if CFStringTransform(str, nil, kCFStringTransformStripDiacritics, false) { + return str as String + } + } + return self + } + + func getFirstLetter() -> String { + return self.firstLetter + } + + ///通过字体获取字符串的尺寸 + func sizeWithFont(font : UIFont) -> CGSize { + //如果没有内容 + guard self.isEmpty == false else { + return CGSizeZero + } + return self.toNSString.sizeWithAttributes([NSFontAttributeName : font]) + } + ///通过字体和固定宽度计算字符串的高度 + func heightWithWidth(width : CGFloat, font : UIFont) -> CGFloat { + //如果没有内容 + guard self.isEmpty == false else { + return CGFloat(0) + } + return self.sizeWithFont(font).width / width + } + ///截取指定长度的字符串 + func substringWithStartPosition(start : Int, andEndPosition end : Int) -> String { + return self.substringWithRange(self.startIndex.advancedBy(start).. Bool { + let regex : NSRegularExpression? = try? NSRegularExpression(pattern: pattern.pattern, options: NSRegularExpressionOptions.CaseInsensitive) + if let matches = regex?.matchesInString(self, options: [], range: NSMakeRange(0, self.toNSString.length)) { + return matches.count > 0 + } else { + return false + } + } + + //MD5加密字符串 + func md5() -> String { + let str = self.cStringUsingEncoding(NSUTF8StringEncoding) + let strLen = CUnsignedInt(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) + let digestLen = Int(CC_MD5_DIGEST_LENGTH) + let result = UnsafeMutablePointer.alloc(digestLen) + CC_MD5(str!, strLen, result) + let hash = NSMutableString() + for i in 0..= 0.5 { + return true + } else { + return false + } + } + + ///便捷颜色。色相、饱和度、亮度、通透度 + class func colorWithHue(hue : CGFloat, saturation : CGFloat, brightness : CGFloat, andAlpha alpha : CGFloat) -> UIColor { + return UIColor( + hue: hue / 256, + saturation: saturation / 256, + brightness: brightness / 256, + alpha: alpha + ) + } + class func colorWithHue(hue : CGFloat, saturation : CGFloat, brightness : CGFloat) -> UIColor { + return colorWithHue(hue, saturation: saturation, brightness: brightness, andAlpha: 1) + } + ///便捷颜色初始化 + class func colorWithRed(red: CGFloat, green: CGFloat, blue: CGFloat, andAlpha alpha: CGFloat) -> UIColor { + return UIColor( + red: (red / 255.0), + green: (green / 255.0), + blue: (blue / 255.0), + alpha: alpha + ) + } + class func colorWithRed(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor { + return UIColor.colorWithRed( + red, + green: green, + blue: blue, + andAlpha: 1 + ) + } + ///16进制初始化颜色 + class func colorWithHex(hex h: Int, andAlpha alpha: CGFloat) -> UIColor { + let red = CGFloat(((h & 0xFF0000) >> 16)) + let green = CGFloat(((h & 0xFF00) >> 8)) + let blue = CGFloat((h & 0xFF)) + + return UIColor.colorWithRed( + red, green: + green, + blue: blue, + andAlpha: alpha + ) + } + class func colorWithHex(hex h: Int) -> UIColor { + return UIColor.colorWithHex(hex: h, andAlpha: 1) + } + class func colorWithHex(hex : String, andAlpha alpha : CGFloat) -> UIColor { + var cString : String = hex.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).uppercaseString + + if cString.hasPrefix("#") { + cString = cString.substringFromIndex(cString.startIndex.advancedBy(1)) + } + + if cString.characters.count != 6 { + return UIColor.grayColor() + } + + var rgbValue : UInt32 = 0 + NSScanner(string: cString).scanHexInt(&rgbValue) + + return UIColor( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: alpha + ) + } + class func colorWithHex(hex : String) -> UIColor { + return UIColor.colorWithHex(hex, andAlpha: 1) + } + class func randomColor() -> UIColor { + return UIColor( + hue: (CGFloat(arc4random()) % 256 / 256.0), + saturation: (CGFloat(arc4random()) % 128 / 256.0) + 0.5, + brightness: (CGFloat(arc4random()) % 128 / 256.0) + 0.5, + alpha: 1 + ) + } +} diff --git a/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift b/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift new file mode 100644 index 0000000..a11026b --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift @@ -0,0 +1,337 @@ +// +// UIViewExtension-MJAlertView.swift +// ChildrenGuardian +// +// Created by Jason.Chengzi on 7/13/16. +// Copyright © 2016 Hvit. All rights reserved. +// + +import UIKit +import QuartzCore + +private let MJAV_APPDELEGATE = UIApplication.sharedApplication().delegate + +private let MJAV_FONT_SIZE_LABEL = 18.toCGFloat +private let MJAV_FONT_SIZE_CANCEL = 13.toCGFloat + +private let MJAV_NOTIFIER_LABEL_FONT = UIFont(name: "HelveticaNeue-Light", size: MJAV_FONT_SIZE_LABEL) +private let MJAV_NOTIFIER_CANCEL_FONT = UIFont(name: "HelveticaNeue", size: MJAV_FONT_SIZE_CANCEL) + +private let MJAV_Tag = 181200 +private let MJAV_xPadding = 18.0.toCGFloat +private let MJAV_Height_Label = 45.0.toCGFloat +private let MJAV_Height_Cancel_Button = 30.0.toCGFloat +private let MJAV_Height_Separator = 1.0.toCGFloat +private let MJAV_Height_FromBottom = 70.0.toCGFloat +private let MJAV_Width_Max = 290.0.toCGFloat + +enum MJAlertViewStyle { + case Success + case Error + case Warn + case Info + case SubjectTheme + case Default + + var backgroundColor : UIColor { + switch self { + case .Success: + return UIColor.colorWithHex(hex: 0x2ecc71) + case .Error: + return UIColor.colorWithHex(hex: 0xc0392b) + case .Warn: + return UIColor.colorWithHex(hex: 0xe67e22) + case .Info: + return UIColor.colorWithHex(hex: 0x2980b9) + case .SubjectTheme: + return AppearenceDefaults.COLOR_THEME + case .Default: + return UIColor.blackColor().colorWithAlphaComponent(0.8) + } + } + + var textColor : UIColor { + switch self { + case .Success: + return UIColor.whiteColor() + case .Error: + return UIColor.whiteColor() + case .Warn: + return UIColor.whiteColor() + case .Info: + return UIColor.whiteColor() + case .SubjectTheme: +// return UIColor.whiteColor() + if self.backgroundColor.isLight { + return UIColor.blackColor() + } else { + return UIColor.whiteColor() + } + case .Default: + return UIColor.whiteColor() + } + } +} + +extension UIView { + class func makeSuccessNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Success) + } + class func makeWarnNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Warn) + } + class func makeErrorNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Error) + } + class func makeInfoNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Info) + } + class func makeAlertViewWithText(text : String, type : MJAlertViewStyle = .Default) { + + let shouldDismiss = true + + if let screenBounds = MJAV_APPDELEGATE?.window!!.bounds { + let attributes : [String : AnyObject] = [NSFontAttributeName : MJAV_NOTIFIER_LABEL_FONT ?? UIFont.systemFontOfSize(MJAV_FONT_SIZE_LABEL)] + + let height = MJAV_Height_Label + let width = CGFloat.max + let notifierRect = text.toNSString.boundingRectWithSize( + CGSize( + width: width, + height: height + ), + options: NSStringDrawingOptions.UsesLineFragmentOrigin, + attributes: attributes, + context: nil + ) + let notifierWidth = CGFloat.MIN(lbs: CGRectGetWidth(notifierRect) + MJAV_xPadding.double, rbs: MJAV_Width_Max) + let xOffset = (CGRectGetWidth(screenBounds) - notifierWidth).half + + let notifierHeight = MJAV_Height_Label + +// if !shouldDismiss { +// notifierHeight += (MJAV_Height_Cancel_Button + MJAV_Height_Separator) +// } + + let yOffset = CGRectGetHeight(screenBounds) - notifierHeight - MJAV_Height_FromBottom + + let finalFrame = CGRect(x: xOffset, y: yOffset, width: notifierWidth, height: notifierHeight) + + let notifierView = isNotifierExistedAlready() + + if let view = notifierView { + updateNotifierWithAnimation(notifierView, andText: text, andCompletion: { (finished) in + var atLastFrame = finalFrame + atLastFrame.origin.y = finalFrame.origin.y + 8 + view.frame = atLastFrame + + var textLabel : UILabel? + for subview in view.subviews { + if subview is UILabel { + textLabel = subview as? UILabel + } + + if subview is UIImageView || subview is UIButton { + subview.removeFromSuperview() + } + } + + textLabel?.text = text + textLabel?.frame = CGRect(x: MJAV_xPadding, y: 0, width: notifierWidth - MJAV_xPadding.double, height: MJAV_Height_Label) + + if !shouldDismiss { + let separatorImageView = UIImageView(frame: CGRect(x: 0, y: CGRectGetHeight(textLabel!.frame), width: CGRectGetWidth(view.frame), height: MJAV_Height_Separator)) + separatorImageView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) + view.addSubview(separatorImageView) + + let cancelButton = UIButton(type: UIButtonType.Custom) + cancelButton.frame = CGRect(x: 0, y: CGRectGetMaxY(separatorImageView.frame), width: CGRectGetWidth(view.frame), height: MJAV_Height_Cancel_Button) +// cancelButton.setNormalTitleColor(UIColor.whiteColor()) + cancelButton.backgroundColor = UIColor.colorWithHex(hex: 0x000000) + cancelButton.addTarget(self, action: #selector(UIView.buttonCancelClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside) + cancelButton.titleLabel?.font = MJAV_NOTIFIER_CANCEL_FONT + view.addSubview(cancelButton) + } + + UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + view.alpha = 1 + view.frame = finalFrame + }, completion: nil) + }) + + if shouldDismiss { + performSelector(#selector(UIView.dismissMJNotifier), withObject: nil, afterDelay: 2.0) + } + } else { + let notifierView = UIView(frame: CGRect(x: xOffset, y: CGRectGetHeight(screenBounds), width: notifierWidth, height: notifierHeight)) +// notifierView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) + notifierView.backgroundColor = type.backgroundColor + notifierView.tag = MJAV_Tag + notifierView.clipsToBounds = true + notifierView.layer.cornerRadius = 5 + + MJAV_APPDELEGATE?.window??.addSubview(notifierView) + MJAV_APPDELEGATE?.window??.bringSubviewToFront(notifierView) + + let textLabel = UILabel(frame: CGRect(x: MJAV_xPadding, y: 0, width: notifierWidth - MJAV_xPadding.double, height: MJAV_Height_Label)) + textLabel.adjustsFontSizeToFitWidth = true + textLabel.backgroundColor = UIColor.clearColor() + textLabel.textAlignment = .Center +// textLabel.textColor = UIColor.colorWithHex(hex: 0xFFFFFF) + textLabel.textColor = type.textColor + textLabel.font = MJAV_NOTIFIER_LABEL_FONT + textLabel.minimumScaleFactor = 0.7 + textLabel.text = text + notifierView.addSubview(textLabel) + + if shouldDismiss { + self.performSelector(#selector(UIView.dismissMJNotifier), withObject: nil, afterDelay: 2) +// } else { +// let separatorImageView = UIImageView(frame: CGRect(x: 0, y: CGRectGetHeight(textLabel.frame), width: CGRectGetWidth(notifierView.frame), height: MJAV_Height_Separator)) +// separatorImageView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) +// notifierView.addSubview(separatorImageView) +// +// let cancelButton = UIButton(type: UIButtonType.Custom) +// cancelButton.frame = CGRect(x: 0, y: CGRectGetMaxY(separatorImageView.frame), width: CGRectGetWidth(notifierView.frame), height: MJAV_Height_Cancel_Button) +// cancelButton.backgroundColor = UIColor.colorWithHex(hex: 0x000000) +// cancelButton.addTarget(self, action: #selector(UIView.buttonCancelClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside) +// cancelButton.titleLabel?.font = MJAV_NOTIFIER_CANCEL_FONT +// notifierView.addSubview(cancelButton) + } + + self.startEntryAnimation(notifierView, withFinalFrame: finalFrame) + } + } + } + class func dismissMJNotifier() { + NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: #selector(UIView.dismissMJNotifier), object: nil) + + var notifier : UIView? + + for subview in MJAV_APPDELEGATE!.window!!.subviews { + if subview.tag == MJAV_Tag && subview.isKindOfClass(UIView.self) { + notifier = subview + } + } + + startExitAnimation(notifier) + } +} + +private extension UIView { + class func isNotifierExistedAlready() -> UIView? { + NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: #selector(UIView.dismissMJNotifier), object: nil) + + var notifier : UIView? + + for subview in MJAV_APPDELEGATE!.window!!.subviews { + if subview.tag == MJAV_Tag && subview.isKindOfClass(UIView.self) { + notifier = subview + } + } + + return notifier + } + + @objc class func buttonCancelClicked(sender : UIButton) { + dismissMJNotifier() + } + + class func updateNotifierWithAnimation(notifierView : UIView?, andText text : String, andCompletion completion : ((finished : Bool) -> Void)?) { + if let view = notifierView { + var finalFrame = view.frame + finalFrame.origin.y = finalFrame.origin.y + 8 + + UIView.animateWithDuration( 0.2, + delay: 0, + options: UIViewAnimationOptions.CurveEaseOut, + animations: { + view.alpha = 0 + view.frame = finalFrame + }, + completion: { (finished : Bool) in + completion?(finished: finished) + } + ) + } + } + + class func startEntryAnimation(notifierView : UIView?, withFinalFrame finalFrame : CGRect) { + + if let view = notifierView { + + var mutableFinalFrame = finalFrame + + let finalYOffset = mutableFinalFrame.origin.y + mutableFinalFrame.origin.y = finalFrame.origin.y - 15 + + let transform = transformWithXAxisValue(-0.1, andAngle: 45) + view.layer.zPosition = 400 + view.layer.transform = transform + + UIView.animateWithDuration(0.2, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + + view.frame = mutableFinalFrame + + let anotherTransform = transformWithXAxisValue(0.1, andAngle: 15) + view.layer.zPosition = 400 + view.layer.transform = anotherTransform + + }, completion: { (finished : Bool) in + UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { + + var atLastFrame = mutableFinalFrame + atLastFrame.origin.y = finalYOffset + view.frame = atLastFrame + + let transform = self.transformWithXAxisValue(0.0, andAngle: 90) + view.layer.zPosition = 400 + view.layer.transform = transform + + }, completion: nil) + }) + } + + } + + class func startExitAnimation(notifierView : UIView?) { + + if let view = notifierView { + + let screenBounds = MJAV_APPDELEGATE!.window!!.bounds + + var notifierFrame = view.frame + let finalYOffset = notifierFrame.origin.y - 12 + notifierFrame.origin.y = finalYOffset + + UIView.animateWithDuration(0.3, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + view.frame = notifierFrame + let transform = transformWithXAxisValue(0.1, andAngle: 30) + view.layer.zPosition = 400 + view.layer.transform = transform + }, completion: { (finished : Bool) in + UIView.animateWithDuration(0.15, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { + var atLastFrame = view.frame + atLastFrame.origin.y = CGRectGetHeight(screenBounds) + view.frame = atLastFrame + + let transform = transformWithXAxisValue(-1, andAngle: 90) + view.layer.zPosition = 400 + view.layer.transform = transform + }, completion: { (finished : Bool) in + view.removeFromSuperview() + }) + }) + } + } + + class func transformWithXAxisValue(xValue : CGFloat, andAngle angle : CGFloat) -> CATransform3D { + var transform = CATransform3DIdentity + + transform.m34 = 1.0 / -1000 + + transform = CATransform3DRotate(transform, angle * M_PI.toCGFloat / 180, xValue, 0, 0) + + return transform + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.pbxproj b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c3ce169 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.pbxproj @@ -0,0 +1,321 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A169EFB81D38DBC600431D02 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFB71D38DBC600431D02 /* AppDelegate.swift */; }; + A169EFBA1D38DBC600431D02 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFB91D38DBC600431D02 /* ViewController.swift */; }; + A169EFBD1D38DBC600431D02 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A169EFBB1D38DBC600431D02 /* Main.storyboard */; }; + A169EFBF1D38DBC600431D02 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A169EFBE1D38DBC600431D02 /* Assets.xcassets */; }; + A169EFC21D38DBC600431D02 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A169EFC01D38DBC600431D02 /* LaunchScreen.storyboard */; }; + A169EFCB1D38DBF300431D02 /* UIViewExtension-MJAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFCA1D38DBF300431D02 /* UIViewExtension-MJAlertView.swift */; }; + A169EFCD1D38DC2100431D02 /* UIColorExtension-Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFCC1D38DC2100431D02 /* UIColorExtension-Instance.swift */; }; + A169EFCF1D38DC3400431D02 /* NumberExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFCE1D38DC3400431D02 /* NumberExtension.swift */; }; + A169EFD11D38DC5300431D02 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFD01D38DC5300431D02 /* StringExtension.swift */; }; + A169EFD31D38DC6500431D02 /* CGFloatExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A169EFD21D38DC6500431D02 /* CGFloatExtension.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + A169EFB41D38DBC600431D02 /* MJAlertViewDemo-Swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MJAlertViewDemo-Swift.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A169EFB71D38DBC600431D02 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A169EFB91D38DBC600431D02 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + A169EFBC1D38DBC600431D02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + A169EFBE1D38DBC600431D02 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A169EFC11D38DBC600431D02 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + A169EFC31D38DBC600431D02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A169EFCA1D38DBF300431D02 /* UIViewExtension-MJAlertView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewExtension-MJAlertView.swift"; sourceTree = ""; }; + A169EFCC1D38DC2100431D02 /* UIColorExtension-Instance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColorExtension-Instance.swift"; sourceTree = ""; }; + A169EFCE1D38DC3400431D02 /* NumberExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberExtension.swift; sourceTree = ""; }; + A169EFD01D38DC5300431D02 /* StringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; + A169EFD21D38DC6500431D02 /* CGFloatExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGFloatExtension.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A169EFB11D38DBC600431D02 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A169EFAB1D38DBC600431D02 = { + isa = PBXGroup; + children = ( + A169EFB61D38DBC600431D02 /* MJAlertViewDemo-Swift */, + A169EFB51D38DBC600431D02 /* Products */, + ); + sourceTree = ""; + }; + A169EFB51D38DBC600431D02 /* Products */ = { + isa = PBXGroup; + children = ( + A169EFB41D38DBC600431D02 /* MJAlertViewDemo-Swift.app */, + ); + name = Products; + sourceTree = ""; + }; + A169EFB61D38DBC600431D02 /* MJAlertViewDemo-Swift */ = { + isa = PBXGroup; + children = ( + A169EFC91D38DBF300431D02 /* MJAlertView-Swift */, + A169EFB71D38DBC600431D02 /* AppDelegate.swift */, + A169EFB91D38DBC600431D02 /* ViewController.swift */, + A169EFBB1D38DBC600431D02 /* Main.storyboard */, + A169EFBE1D38DBC600431D02 /* Assets.xcassets */, + A169EFC01D38DBC600431D02 /* LaunchScreen.storyboard */, + A169EFC31D38DBC600431D02 /* Info.plist */, + ); + path = "MJAlertViewDemo-Swift"; + sourceTree = ""; + }; + A169EFC91D38DBF300431D02 /* MJAlertView-Swift */ = { + isa = PBXGroup; + children = ( + A169EFD21D38DC6500431D02 /* CGFloatExtension.swift */, + A169EFD01D38DC5300431D02 /* StringExtension.swift */, + A169EFCE1D38DC3400431D02 /* NumberExtension.swift */, + A169EFCC1D38DC2100431D02 /* UIColorExtension-Instance.swift */, + A169EFCA1D38DBF300431D02 /* UIViewExtension-MJAlertView.swift */, + ); + path = "MJAlertView-Swift"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A169EFB31D38DBC600431D02 /* MJAlertViewDemo-Swift */ = { + isa = PBXNativeTarget; + buildConfigurationList = A169EFC61D38DBC600431D02 /* Build configuration list for PBXNativeTarget "MJAlertViewDemo-Swift" */; + buildPhases = ( + A169EFB01D38DBC600431D02 /* Sources */, + A169EFB11D38DBC600431D02 /* Frameworks */, + A169EFB21D38DBC600431D02 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "MJAlertViewDemo-Swift"; + productName = "MJAlertViewDemo-Swift"; + productReference = A169EFB41D38DBC600431D02 /* MJAlertViewDemo-Swift.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A169EFAC1D38DBC600431D02 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0730; + ORGANIZATIONNAME = Jason; + TargetAttributes = { + A169EFB31D38DBC600431D02 = { + CreatedOnToolsVersion = 7.3.1; + }; + }; + }; + buildConfigurationList = A169EFAF1D38DBC600431D02 /* Build configuration list for PBXProject "MJAlertViewDemo-Swift" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A169EFAB1D38DBC600431D02; + productRefGroup = A169EFB51D38DBC600431D02 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A169EFB31D38DBC600431D02 /* MJAlertViewDemo-Swift */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A169EFB21D38DBC600431D02 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A169EFC21D38DBC600431D02 /* LaunchScreen.storyboard in Resources */, + A169EFBF1D38DBC600431D02 /* Assets.xcassets in Resources */, + A169EFBD1D38DBC600431D02 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A169EFB01D38DBC600431D02 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A169EFBA1D38DBC600431D02 /* ViewController.swift in Sources */, + A169EFB81D38DBC600431D02 /* AppDelegate.swift in Sources */, + A169EFD11D38DC5300431D02 /* StringExtension.swift in Sources */, + A169EFD31D38DC6500431D02 /* CGFloatExtension.swift in Sources */, + A169EFCD1D38DC2100431D02 /* UIColorExtension-Instance.swift in Sources */, + A169EFCB1D38DBF300431D02 /* UIViewExtension-MJAlertView.swift in Sources */, + A169EFCF1D38DC3400431D02 /* NumberExtension.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + A169EFBB1D38DBC600431D02 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A169EFBC1D38DBC600431D02 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + A169EFC01D38DBC600431D02 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A169EFC11D38DBC600431D02 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A169EFC41D38DBC600431D02 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + A169EFC51D38DBC600431D02 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + A169EFC71D38DBC600431D02 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "MJAlertViewDemo-Swift/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.WeSwift.MJAlertViewDemo-Swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + A169EFC81D38DBC600431D02 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "MJAlertViewDemo-Swift/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.WeSwift.MJAlertViewDemo-Swift"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A169EFAF1D38DBC600431D02 /* Build configuration list for PBXProject "MJAlertViewDemo-Swift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A169EFC41D38DBC600431D02 /* Debug */, + A169EFC51D38DBC600431D02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A169EFC61D38DBC600431D02 /* Build configuration list for PBXNativeTarget "MJAlertViewDemo-Swift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A169EFC71D38DBC600431D02 /* Debug */, + A169EFC81D38DBC600431D02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = A169EFAC1D38DBC600431D02 /* Project object */; +} diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..6d830fb --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/xcuserdata/JasonLee.xcuserdatad/UserInterfaceState.xcuserstate b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/project.xcworkspace/xcuserdata/JasonLee.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..7bfc0f18999a244a2f0983b63ab0029a2ef84cbb GIT binary patch literal 17330 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 literal 0 HcmV?d00001 diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo-Swift.xcscheme b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo-Swift.xcscheme new file mode 100644 index 0000000..46cb875 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo-Swift.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..031e5bc --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + MJAlertViewDemo-Swift.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + A169EFB31D38DBC600431D02 + + primary + + + + + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/AppDelegate.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/AppDelegate.swift new file mode 100644 index 0000000..efc3c0e --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// MJAlertViewDemo-Swift +// +// Created by Jason.Chengzi on 7/15/16. +// Copyright © 2016 Jason. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Assets.xcassets/AppIcon.appiconset/Contents.json b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..118c98f --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/LaunchScreen.storyboard b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..2e721e1 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/Main.storyboard b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/Main.storyboard new file mode 100644 index 0000000..5362dd6 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Base.lproj/Main.storyboard @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Info.plist b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Info.plist new file mode 100644 index 0000000..6905cc6 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift new file mode 100644 index 0000000..1e11718 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/CGFloatExtension.swift @@ -0,0 +1,43 @@ +// +// CGFloatExtension.swift +// ChildrenGuardian +// +// Created by Jason.Chengzi on 16/06/17. +// Copyright © 2016年 Hvit. All rights reserved. +// + +import UIKit + +extension CGFloat { + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Int + var toInt : Int { return Int(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : CGFloat { return self / 2 } + ///相反数值 + var opposite : CGFloat { return -self } + ///绝对值 + var absolute : CGFloat { return abs(self) } + ///两倍数值 + var double : CGFloat { return self * 2 } + ///三倍数值 + var triple : CGFloat { return self * 3 } + ///平方数 + var square : CGFloat { return (self * self) } + ///立方数 + var cube : CGFloat { return (self * self * self) } + + static func MIN(lbs lbs : CGFloat, rbs : CGFloat) -> CGFloat { + if lbs > rbs { + return rbs + } else if lbs < rbs { + return lbs + } else { + return lbs + } + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift new file mode 100644 index 0000000..9a8078b --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/NumberExtension.swift @@ -0,0 +1,125 @@ +// +// NumberExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/20. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +extension Int { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : Int { return self / 2 } + ///相反数值 + var opposite : Int { return -self } + ///绝对值 + var absolute : Int { return abs(self) } + ///两倍数值 + var double : Int { return self * 2 } + ///三倍数值 + var triple : Int { return self * 3 } + ///平方数 + var square : Int { return (self * self) } + ///立方数 + var cube : Int { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Int, lessThan max : Int) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Int, equalAndLessThan max : Int) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} + +extension Float { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Int + var toInt : Int { return Int(self) } + ///转换为Double + var toDouble : Double { return Double(self) } + + ///一半数值 + var half : Float { return self / 2 } + ///相反数值 + var opposite : Float { return -self } + ///绝对值 + var absolute : Float { return abs(self) } + ///两倍数值 + var double : Float { return self * 2 } + ///三倍数值 + var triple : Float { return self * 3 } + ///平方数 + var square : Float { return (self * self) } + ///立方数 + var cube : Float { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Float, lessThan max : Float) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Float, equalAndLessThan max : Float) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} + +extension Double { + ///转换为CGFloat + var toCGFloat : CGFloat { return CGFloat(self) } + ///转换为Float + var toFloat : Float { return Float(self) } + ///转换为Int + var toInt : Int { return Int(self) } + + ///一半数值 + var half : Double { return self / 2 } + ///相反数值 + var opposite : Double { return -self } + ///绝对值 + var absolute : Double { return abs(self) } + ///两倍数值 + var double : Double { return self * 2 } + ///三倍数值 + var triple : Double { return self * 3 } + ///平方数 + var square : Double { return (self * self) } + ///立方数 + var cube : Double { return (self * self * self) } + + ///是否在开区间内 + func isGreaterThan(min : Double, lessThan max : Double) -> Bool { + if self > min && self < max { + return true + } + return false + } + ///是否在闭区间内 + func isEqualAndGreaterThan(min : Double, equalAndLessThan max : Double) -> Bool { + if self >= min && self <= max { + return true + } + return false + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift new file mode 100644 index 0000000..96d3159 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/StringExtension.swift @@ -0,0 +1,131 @@ +// +// StringExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/17. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +extension String { + ///获取NSString对象 + var toNSString : NSString { + return NSString(string: self) + } + ///获取字符串长度 + var length : Int { + return self.characters.count + } + + ///判断是否为整数 + var isInt : Bool { + if Int(self) != nil { + return true + } else { + return false + } + } + ///判断是否为浮点数 + var isFloat : Bool { + if Float(self) != nil { + return true + } else { + return false + } + } + ///判断是否为长浮点数 + var isDouble : Bool { + if Double(self) != nil { + return true + } else { + return false + } + } + + ///尝试转换为整型 + var nullableInt : Int? { + return Int(self) + } + ///尝试转换为浮点数 + var nullableFloat : Float? { + return Float(self) + } + ///尝试转换为长浮点数 + var nullableDouble : Double? { + return Double(self) + } + + ///强制转换为整型,失败返回0 + var toInt : Int { + return Int(self) ?? 0 + } + ///强制转换为浮点数,失败返回0 + var toFloat : Float { + return Float(self) ?? Float(0) + } + ///强制转换为长浮点数,失败返回0 + var toDouble : Double { + return Double(self) ?? Double(0) + } + + ///获取第一个字母 + var firstLetter : String { + var ret = "" + if !self.canBeConvertedToEncoding(NSASCIIStringEncoding) { + ret = self.letters.firstLetter + } else { + ret = "\("\(self.characters.first)" ?? "")" + } + return ret + } + + var letters : String { + let str = NSMutableString(string: self) + if CFStringTransform(str, nil, kCFStringTransformMandarinLatin, false) { + if CFStringTransform(str, nil, kCFStringTransformStripDiacritics, false) { + return str as String + } + } + return self + } + + func getFirstLetter() -> String { + return self.firstLetter + } + + ///通过字体获取字符串的尺寸 + func sizeWithFont(font : UIFont) -> CGSize { + //如果没有内容 + guard self.isEmpty == false else { + return CGSizeZero + } + return self.toNSString.sizeWithAttributes([NSFontAttributeName : font]) + } + ///通过字体和固定宽度计算字符串的高度 + func heightWithWidth(width : CGFloat, font : UIFont) -> CGFloat { + //如果没有内容 + guard self.isEmpty == false else { + return CGFloat(0) + } + return self.sizeWithFont(font).width / width + } + ///截取指定长度的字符串 + func substringWithStartPosition(start : Int, andEndPosition end : Int) -> String { + return self.substringWithRange(self.startIndex.advancedBy(start).. Bool { + let regex : NSRegularExpression? = try? NSRegularExpression(pattern: pattern.pattern, options: NSRegularExpressionOptions.CaseInsensitive) + if let matches = regex?.matchesInString(self, options: [], range: NSMakeRange(0, self.toNSString.length)) { + return matches.count > 0 + } else { + return false + } + } + + +} + +struct MCPattern { + var pattern : String +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIColorExtension-Instance.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIColorExtension-Instance.swift new file mode 100644 index 0000000..dbb028c --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIColorExtension-Instance.swift @@ -0,0 +1,135 @@ +// +// UIColorExtension.swift +// HealthPlus +// +// Created by Jason.Chengzi on 16/05/13. +// Copyright © 2016年 Hvit. All rights reserved. +// +import UIKit + +//MARK: - UIColor +extension UIColor { + + ///CGFloat类型的RGB值 + var components : (red : CGFloat, green : CGFloat, blue : CGFloat, alpha : CGFloat) { + var fRed : CGFloat = 0 + var fGreen : CGFloat = 0 + var fBlue : CGFloat = 0 + var fAlpha : CGFloat = 0 + + self.getRed(&fRed, green: &fGreen, blue: &fBlue, alpha: &fAlpha) + + return (fRed, fGreen, fBlue, fAlpha) + } + ///Int类型的RGB值 + var RGBValues : (red : Int, green : Int, blue : Int, alpha : CGFloat) { + let components = self.components + return ((components.red * 255).toInt, (components.green * 255).toInt, (components.blue * 255).toInt, components.alpha) + } + + var redComponent : CGFloat { + return self.components.red + } + var greenComponent : CGFloat { + return self.components.green + } + var blueComponent : CGFloat { + return self.components.blue + } + var alphaComponent : CGFloat { + return self.components.alpha + } + + var coreImageColor : CoreImage.CIColor? { + return CoreImage.CIColor(color: self) + } + + var isLight : Bool { + var white : CGFloat = 0 + self.getWhite(&white, alpha: nil) + + if white >= 0.5 { + return true + } else { + return false + } + } + + ///便捷颜色。色相、饱和度、亮度、通透度 + class func colorWithHue(hue : CGFloat, saturation : CGFloat, brightness : CGFloat, andAlpha alpha : CGFloat) -> UIColor { + return UIColor( + hue: hue / 256, + saturation: saturation / 256, + brightness: brightness / 256, + alpha: alpha + ) + } + class func colorWithHue(hue : CGFloat, saturation : CGFloat, brightness : CGFloat) -> UIColor { + return colorWithHue(hue, saturation: saturation, brightness: brightness, andAlpha: 1) + } + ///便捷颜色初始化 + class func colorWithRed(red: CGFloat, green: CGFloat, blue: CGFloat, andAlpha alpha: CGFloat) -> UIColor { + return UIColor( + red: (red / 255.0), + green: (green / 255.0), + blue: (blue / 255.0), + alpha: alpha + ) + } + class func colorWithRed(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor { + return UIColor.colorWithRed( + red, + green: green, + blue: blue, + andAlpha: 1 + ) + } + ///16进制初始化颜色 + class func colorWithHex(hex h: Int, andAlpha alpha: CGFloat) -> UIColor { + let red = CGFloat(((h & 0xFF0000) >> 16)) + let green = CGFloat(((h & 0xFF00) >> 8)) + let blue = CGFloat((h & 0xFF)) + + return UIColor.colorWithRed( + red, green: + green, + blue: blue, + andAlpha: alpha + ) + } + class func colorWithHex(hex h: Int) -> UIColor { + return UIColor.colorWithHex(hex: h, andAlpha: 1) + } + class func colorWithHex(hex : String, andAlpha alpha : CGFloat) -> UIColor { + var cString : String = hex.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).uppercaseString + + if cString.hasPrefix("#") { + cString = cString.substringFromIndex(cString.startIndex.advancedBy(1)) + } + + if cString.characters.count != 6 { + return UIColor.grayColor() + } + + var rgbValue : UInt32 = 0 + NSScanner(string: cString).scanHexInt(&rgbValue) + + return UIColor( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: alpha + ) + } + class func colorWithHex(hex : String) -> UIColor { + return UIColor.colorWithHex(hex, andAlpha: 1) + } + class func randomColor() -> UIColor { + return UIColor( + hue: (CGFloat(arc4random()) % 256 / 256.0), + saturation: (CGFloat(arc4random()) % 128 / 256.0) + 0.5, + brightness: (CGFloat(arc4random()) % 128 / 256.0) + 0.5, + alpha: 1 + ) + } +} diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift new file mode 100644 index 0000000..8d3c3b4 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/MJAlertView-Swift/UIViewExtension-MJAlertView.swift @@ -0,0 +1,339 @@ +// +// UIViewExtension-MJAlertView.swift +// ChildrenGuardian +// +// Created by Jason.Chengzi on 7/13/16. +// Copyright © 2016 Hvit. All rights reserved. +// + +import UIKit +import QuartzCore + +private let MJAV_APPDELEGATE = UIApplication.sharedApplication().delegate + +private let MJAV_FONT_SIZE_LABEL = 18.toCGFloat +private let MJAV_FONT_SIZE_CANCEL = 13.toCGFloat + +private let MJAV_NOTIFIER_LABEL_FONT = UIFont(name: "HelveticaNeue-Light", size: MJAV_FONT_SIZE_LABEL) +private let MJAV_NOTIFIER_CANCEL_FONT = UIFont(name: "HelveticaNeue", size: MJAV_FONT_SIZE_CANCEL) + +private let MJAV_Tag = 181200 +private let MJAV_xPadding = 18.0.toCGFloat +private let MJAV_Height_Label = 45.0.toCGFloat +private let MJAV_Height_Cancel_Button = 30.0.toCGFloat +private let MJAV_Height_Separator = 1.0.toCGFloat +private let MJAV_Height_FromBottom = 70.0.toCGFloat +private let MJAV_Width_Max = 290.0.toCGFloat + +enum MJAlertViewStyle { + case Success + case Error + case Warn + case Info + case SubjectTheme + case Default + + var backgroundColor : UIColor { + switch self { + case .Success: + return UIColor.colorWithHex(hex: 0x2ecc71) + case .Error: + return UIColor.colorWithHex(hex: 0xc0392b) + case .Warn: + return UIColor.colorWithHex(hex: 0xe67e22) + case .Info: + return UIColor.colorWithHex(hex: 0x2980b9) + case .SubjectTheme: + return UIColor.blackColor().colorWithAlphaComponent(0.8) + case .Default: + return UIColor.blackColor().colorWithAlphaComponent(0.8) + } + } + + var textColor : UIColor { + switch self { + case .Success: + return UIColor.whiteColor() + case .Error: + return UIColor.whiteColor() + case .Warn: + return UIColor.whiteColor() + case .Info: + return UIColor.whiteColor() + case .SubjectTheme: +// return UIColor.whiteColor() + if self.backgroundColor.isLight { + return UIColor.blackColor() + } else { + return UIColor.whiteColor() + } + case .Default: + return UIColor.whiteColor() + } + } +} + +extension UIView { + class func makeSuccessNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Success) + } + class func makeWarnNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Warn) + } + class func makeErrorNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Error) + } + class func makeInfoNotificationWithText(text : String) { + UIView.makeAlertViewWithText(text, type: .Info) + } + class func makeAlertViewWithText(text : String, type : MJAlertViewStyle = .Default) { + + let shouldDismiss = true + + if let screenBounds = MJAV_APPDELEGATE?.window!!.bounds { + let attributes : [String : AnyObject] = [NSFontAttributeName : MJAV_NOTIFIER_LABEL_FONT ?? UIFont.systemFontOfSize(MJAV_FONT_SIZE_LABEL)] + + let height = MJAV_Height_Label + let width = CGFloat.max + let notifierRect = text.toNSString.boundingRectWithSize( + CGSize( + width: width, + height: height + ), + options: NSStringDrawingOptions.UsesLineFragmentOrigin, + attributes: attributes, + context: nil + ) + let notifierWidth = CGFloat.MIN(lbs: CGRectGetWidth(notifierRect) + MJAV_xPadding.double, rbs: MJAV_Width_Max) + let xOffset = (CGRectGetWidth(screenBounds) - notifierWidth).half + + let notifierHeight = MJAV_Height_Label + +// if !shouldDismiss { +// notifierHeight += (MJAV_Height_Cancel_Button + MJAV_Height_Separator) +// } + + let yOffset = CGRectGetHeight(screenBounds) - notifierHeight - MJAV_Height_FromBottom + + let finalFrame = CGRect(x: xOffset, y: yOffset, width: notifierWidth, height: notifierHeight) + + let notifierView = isNotifierExistedAlready() + + if let view = notifierView { + updateNotifierWithAnimation(notifierView, andText: text, andCompletion: { (finished) in + var atLastFrame = finalFrame + atLastFrame.origin.y = finalFrame.origin.y + 8 + view.frame = atLastFrame + view.backgroundColor = type.backgroundColor + + var textLabel : UILabel? + for subview in view.subviews { + if subview is UILabel { + textLabel = subview as? UILabel + } + + if subview is UIImageView || subview is UIButton { + subview.removeFromSuperview() + } + } + + textLabel?.text = text + textLabel?.frame = CGRect(x: MJAV_xPadding, y: 0, width: notifierWidth - MJAV_xPadding.double, height: MJAV_Height_Label) + textLabel?.textColor = type.textColor + + if !shouldDismiss { + let separatorImageView = UIImageView(frame: CGRect(x: 0, y: CGRectGetHeight(textLabel!.frame), width: CGRectGetWidth(view.frame), height: MJAV_Height_Separator)) + separatorImageView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) + view.addSubview(separatorImageView) + + let cancelButton = UIButton(type: UIButtonType.Custom) + cancelButton.frame = CGRect(x: 0, y: CGRectGetMaxY(separatorImageView.frame), width: CGRectGetWidth(view.frame), height: MJAV_Height_Cancel_Button) +// cancelButton.setNormalTitleColor(UIColor.whiteColor()) + cancelButton.backgroundColor = UIColor.colorWithHex(hex: 0x000000) + cancelButton.addTarget(self, action: #selector(UIView.buttonCancelClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside) + cancelButton.titleLabel?.font = MJAV_NOTIFIER_CANCEL_FONT + view.addSubview(cancelButton) + } + + UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + view.alpha = 1 + view.frame = finalFrame + }, completion: nil) + }) + + if shouldDismiss { + performSelector(#selector(UIView.dismissMJNotifier), withObject: nil, afterDelay: 2.0) + } + } else { + let notifierView = UIView(frame: CGRect(x: xOffset, y: CGRectGetHeight(screenBounds), width: notifierWidth, height: notifierHeight)) +// notifierView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) + notifierView.backgroundColor = type.backgroundColor + notifierView.tag = MJAV_Tag + notifierView.clipsToBounds = true + notifierView.layer.cornerRadius = 5 + + MJAV_APPDELEGATE?.window??.addSubview(notifierView) + MJAV_APPDELEGATE?.window??.bringSubviewToFront(notifierView) + + let textLabel = UILabel(frame: CGRect(x: MJAV_xPadding, y: 0, width: notifierWidth - MJAV_xPadding.double, height: MJAV_Height_Label)) + textLabel.adjustsFontSizeToFitWidth = true + textLabel.backgroundColor = UIColor.clearColor() + textLabel.textAlignment = .Center +// textLabel.textColor = UIColor.colorWithHex(hex: 0xFFFFFF) + textLabel.textColor = type.textColor + textLabel.font = MJAV_NOTIFIER_LABEL_FONT + textLabel.minimumScaleFactor = 0.7 + textLabel.text = text + notifierView.addSubview(textLabel) + + if shouldDismiss { + self.performSelector(#selector(UIView.dismissMJNotifier), withObject: nil, afterDelay: 2) +// } else { +// let separatorImageView = UIImageView(frame: CGRect(x: 0, y: CGRectGetHeight(textLabel.frame), width: CGRectGetWidth(notifierView.frame), height: MJAV_Height_Separator)) +// separatorImageView.backgroundColor = UIColor.colorWithHex(hex: 0xF94137) +// notifierView.addSubview(separatorImageView) +// +// let cancelButton = UIButton(type: UIButtonType.Custom) +// cancelButton.frame = CGRect(x: 0, y: CGRectGetMaxY(separatorImageView.frame), width: CGRectGetWidth(notifierView.frame), height: MJAV_Height_Cancel_Button) +// cancelButton.backgroundColor = UIColor.colorWithHex(hex: 0x000000) +// cancelButton.addTarget(self, action: #selector(UIView.buttonCancelClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside) +// cancelButton.titleLabel?.font = MJAV_NOTIFIER_CANCEL_FONT +// notifierView.addSubview(cancelButton) + } + + self.startEntryAnimation(notifierView, withFinalFrame: finalFrame) + } + } + } + class func dismissMJNotifier() { + NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: #selector(UIView.dismissMJNotifier), object: nil) + + var notifier : UIView? + + for subview in MJAV_APPDELEGATE!.window!!.subviews { + if subview.tag == MJAV_Tag && subview.isKindOfClass(UIView.self) { + notifier = subview + } + } + + startExitAnimation(notifier) + } +} + +private extension UIView { + class func isNotifierExistedAlready() -> UIView? { + NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: #selector(UIView.dismissMJNotifier), object: nil) + + var notifier : UIView? + + for subview in MJAV_APPDELEGATE!.window!!.subviews { + if subview.tag == MJAV_Tag && subview.isKindOfClass(UIView.self) { + notifier = subview + } + } + + return notifier + } + + @objc class func buttonCancelClicked(sender : UIButton) { + dismissMJNotifier() + } + + class func updateNotifierWithAnimation(notifierView : UIView?, andText text : String, andCompletion completion : ((finished : Bool) -> Void)?) { + if let view = notifierView { + var finalFrame = view.frame + finalFrame.origin.y = finalFrame.origin.y + 8 + + UIView.animateWithDuration( 0.2, + delay: 0, + options: UIViewAnimationOptions.CurveEaseOut, + animations: { + view.alpha = 0 + view.frame = finalFrame + }, + completion: { (finished : Bool) in + completion?(finished: finished) + } + ) + } + } + + class func startEntryAnimation(notifierView : UIView?, withFinalFrame finalFrame : CGRect) { + + if let view = notifierView { + + var mutableFinalFrame = finalFrame + + let finalYOffset = mutableFinalFrame.origin.y + mutableFinalFrame.origin.y = finalFrame.origin.y - 15 + + let transform = transformWithXAxisValue(-0.1, andAngle: 45) + view.layer.zPosition = 400 + view.layer.transform = transform + + UIView.animateWithDuration(0.2, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + + view.frame = mutableFinalFrame + + let anotherTransform = transformWithXAxisValue(0.1, andAngle: 15) + view.layer.zPosition = 400 + view.layer.transform = anotherTransform + + }, completion: { (finished : Bool) in + UIView.animateWithDuration(0.4, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { + + var atLastFrame = mutableFinalFrame + atLastFrame.origin.y = finalYOffset + view.frame = atLastFrame + + let transform = self.transformWithXAxisValue(0.0, andAngle: 90) + view.layer.zPosition = 400 + view.layer.transform = transform + + }, completion: nil) + }) + } + + } + + class func startExitAnimation(notifierView : UIView?) { + + if let view = notifierView { + + let screenBounds = MJAV_APPDELEGATE!.window!!.bounds + + var notifierFrame = view.frame + let finalYOffset = notifierFrame.origin.y - 12 + notifierFrame.origin.y = finalYOffset + + UIView.animateWithDuration(0.3, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: { + view.frame = notifierFrame + let transform = transformWithXAxisValue(0.1, andAngle: 30) + view.layer.zPosition = 400 + view.layer.transform = transform + }, completion: { (finished : Bool) in + UIView.animateWithDuration(0.15, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations: { + var atLastFrame = view.frame + atLastFrame.origin.y = CGRectGetHeight(screenBounds) + view.frame = atLastFrame + + let transform = transformWithXAxisValue(-1, andAngle: 90) + view.layer.zPosition = 400 + view.layer.transform = transform + }, completion: { (finished : Bool) in + view.removeFromSuperview() + }) + }) + } + } + + class func transformWithXAxisValue(xValue : CGFloat, andAngle angle : CGFloat) -> CATransform3D { + var transform = CATransform3DIdentity + + transform.m34 = 1.0 / -1000 + + transform = CATransform3DRotate(transform, angle * M_PI.toCGFloat / 180, xValue, 0, 0) + + return transform + } +} \ No newline at end of file diff --git a/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/ViewController.swift b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/ViewController.swift new file mode 100644 index 0000000..65d4516 --- /dev/null +++ b/MJAlertViewDemo-Swift/MJAlertViewDemo-Swift/ViewController.swift @@ -0,0 +1,40 @@ +// +// ViewController.swift +// MJAlertViewDemo-Swift +// +// Created by Jason.Chengzi on 7/15/16. +// Copyright © 2016 Jason. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + @IBAction func showSuccess(sender: AnyObject) { + UIView.makeSuccessNotificationWithText("Success Color") + } + + @IBAction func showError(sender: AnyObject) { + UIView.makeErrorNotificationWithText("Error Color") + } + + @IBAction func showWarn(sender: AnyObject) { + UIView.makeWarnNotificationWithText("Warn Color") + } + + @IBAction func showInfo(sender: AnyObject) { + UIView.makeInfoNotificationWithText("Info Color") + } + +} + diff --git a/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/project.xcworkspace/xcuserdata/JasonLee.xcuserdatad/UserInterfaceState.xcuserstate b/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/project.xcworkspace/xcuserdata/JasonLee.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..4ee4b12c88e2212f7b30394361ee8618cdf5c8c6 GIT binary patch literal 9273 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 literal 0 HcmV?d00001 diff --git a/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo.xcscheme b/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo.xcscheme new file mode 100644 index 0000000..4702ac9 --- /dev/null +++ b/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/MJAlertViewDemo.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist b/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..595bc18 --- /dev/null +++ b/MJAlertViewDemo/MJAlertViewDemo.xcodeproj/xcuserdata/JasonLee.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + MJAlertViewDemo.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 4D50BACA1A9610B100EC9FDC + + primary + + + 4D50BAE31A9610B100EC9FDC + + primary + + + + + diff --git a/MJAlertViewDemo/MJAlertViewDemo/Base.lproj/Main.storyboard b/MJAlertViewDemo/MJAlertViewDemo/Base.lproj/Main.storyboard index e277f1f..4c98c65 100644 --- a/MJAlertViewDemo/MJAlertViewDemo/Base.lproj/Main.storyboard +++ b/MJAlertViewDemo/MJAlertViewDemo/Base.lproj/Main.storyboard @@ -1,7 +1,8 @@ - + - + +