diff --git a/Example/SCLAlertViewExample/ViewController.swift b/Example/SCLAlertViewExample/ViewController.swift index 1883edb..fd27a0d 100644 --- a/Example/SCLAlertViewExample/ViewController.swift +++ b/Example/SCLAlertViewExample/ViewController.swift @@ -70,7 +70,14 @@ class ViewController: UIViewController { @IBAction func showCustomSubview(sender: AnyObject) { - let alert = SCLAlertView() + // Create custom Appearance Configuration + let appearance = SCLAlertView.SCLAppearance( + kTitleFont: UIFont(name: "HelveticaNeue", size: 20)!, + kTextFont: UIFont(name: "HelveticaNeue", size: 14)!, + kButtonFont: UIFont(name: "HelveticaNeue-Bold", size: 14)!) + + // Initialize SCLAlertView using custom Appearance + let alert = SCLAlertView(appearance: appearance) // Creat the subview let subview = UIView(frame: CGRectMake(0,0,216,70)) diff --git a/SCLAlertView/SCLAlertView.swift b/SCLAlertView/SCLAlertView.swift index 313ceaa..a073641 100644 --- a/SCLAlertView/SCLAlertView.swift +++ b/SCLAlertView/SCLAlertView.swift @@ -97,40 +97,87 @@ public typealias DismissBlock = () -> Void // The Main Class public class SCLAlertView: UIViewController { - let kDefaultShadowOpacity: CGFloat = 0.7 - let kCircleTopPosition: CGFloat = -12.0 - let kCircleBackgroundTopPosition: CGFloat = -15.0 - let kCircleHeight: CGFloat = 56.0 - let kCircleIconHeight: CGFloat = 20.0 - let kTitleTop:CGFloat = 30.0 - let kTitleHeight:CGFloat = 25.0 - let kWindowWidth: CGFloat = 240.0 - var kWindowHeight: CGFloat = 178.0 - var kTextHeight: CGFloat = 90.0 - let kTextFieldHeight: CGFloat = 45.0 - let kTextViewdHeight: CGFloat = 80.0 - let kButtonHeight: CGFloat = 45.0 - - // Font - let kDefaultFont = "HelveticaNeue" - let kButtonFont = "HelveticaNeue-Bold" + + public struct SCLAppearance { + let kDefaultShadowOpacity: CGFloat + let kCircleTopPosition: CGFloat + let kCircleBackgroundTopPosition: CGFloat + let kCircleHeight: CGFloat + let kCircleIconHeight: CGFloat + let kTitleTop:CGFloat + let kTitleHeight:CGFloat + let kWindowWidth: CGFloat + var kWindowHeight: CGFloat + var kTextHeight: CGFloat + let kTextFieldHeight: CGFloat + let kTextViewdHeight: CGFloat + let kButtonHeight: CGFloat + + // Fonts + let kTitleFont: UIFont + let kTextFont: UIFont + let kButtonFont: UIFont + + // UI Options + var showCloseButton: Bool + var showCircularIcon: Bool + var shouldAutoDismiss: Bool // Set this false to 'Disable' Auto hideView when SCLButton is tapped + var contentViewCornerRadius : CGFloat + var fieldCornerRadius : CGFloat + var buttonCornerRadius : CGFloat + + // Actions + var hideWhenBackgroundViewIsTapped: Bool + + public init(kDefaultShadowOpacity: CGFloat = 0.7, kCircleTopPosition: CGFloat = -12.0, kCircleBackgroundTopPosition: CGFloat = -15.0, kCircleHeight: CGFloat = 56.0, kCircleIconHeight: CGFloat = 20.0, kTitleTop:CGFloat = 30.0, kTitleHeight:CGFloat = 25.0, kWindowWidth: CGFloat = 240.0, kWindowHeight: CGFloat = 178.0, kTextHeight: CGFloat = 90.0, kTextFieldHeight: CGFloat = 45.0, kTextViewdHeight: CGFloat = 80.0, kButtonHeight: CGFloat = 45.0, kTitleFont: UIFont = UIFont.systemFontOfSize(20), kTextFont: UIFont = UIFont.systemFontOfSize(14), kButtonFont: UIFont = UIFont.boldSystemFontOfSize(14), showCloseButton: Bool = true, showCircularIcon: Bool = true, shouldAutoDismiss: Bool = true, contentViewCornerRadius: CGFloat = 5.0, fieldCornerRadius: CGFloat = 3.0, buttonCornerRadius: CGFloat = 3.0, hideWhenBackgroundViewIsTapped: Bool = false) { + + self.kDefaultShadowOpacity = kDefaultShadowOpacity + self.kCircleTopPosition = kCircleTopPosition + self.kCircleBackgroundTopPosition = kCircleBackgroundTopPosition + self.kCircleHeight = kCircleHeight + self.kCircleIconHeight = kCircleIconHeight + self.kTitleTop = kTitleTop + self.kTitleHeight = kTitleHeight + self.kWindowWidth = kWindowWidth + self.kWindowHeight = kWindowHeight + self.kTextHeight = kTextHeight + self.kTextFieldHeight = kTextFieldHeight + self.kTextViewdHeight = kTextViewdHeight + self.kButtonHeight = kButtonHeight + + self.kTitleFont = kTitleFont + self.kTextFont = kTextFont + self.kButtonFont = kButtonFont + + self.showCloseButton = showCloseButton + self.showCircularIcon = showCircularIcon + self.shouldAutoDismiss = shouldAutoDismiss + self.contentViewCornerRadius = contentViewCornerRadius + self.fieldCornerRadius = fieldCornerRadius + self.buttonCornerRadius = buttonCornerRadius + + self.hideWhenBackgroundViewIsTapped = hideWhenBackgroundViewIsTapped + } + + mutating func setkWindowHeight(kWindowHeight:CGFloat) { + self.kWindowHeight = kWindowHeight + } + + mutating func setkTextHeight(kTextHeight:CGFloat) { + self.kTextHeight = kTextHeight + } + } + + var appearance: SCLAppearance! // UI Colour var viewColor = UIColor() - var pressBrightnessFactor = 0.85 // UI Options - public var showCloseButton = true - public var showCircularIcon = true - public var shouldAutoDismiss = true //Set this false to 'Disable' Auto hideView when SCLButton is tapped - public var contentViewCornerRadius : CGFloat = 5.0 - public var fieldCornerRadius : CGFloat = 3.0 - public var buttonCornerRadius : CGFloat = 3.0 public var iconTintColor: UIColor? public var customSubview : UIView? - // Actions - public var hideWhenBackgroundViewIsTapped = false + // Members declaration var baseView = UIView() @@ -149,23 +196,39 @@ public class SCLAlertView: UIViewController { internal var buttons = [SCLButton]() private var selfReference: SCLAlertView? + public init(appearance: SCLAppearance) { + self.appearance = appearance + super.init(nibName:nil, bundle:nil) + setup() + } + required public init?(coder aDecoder: NSCoder) { fatalError("NSCoding not supported") } required public init() { + appearance = SCLAppearance() super.init(nibName:nil, bundle:nil) + setup() + } + + override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { + appearance = SCLAppearance() + super.init(nibName:nibNameOrNil, bundle:nibBundleOrNil) + } + + private func setup() { // Set up main view view.frame = UIScreen.mainScreen().bounds view.autoresizingMask = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth] - view.backgroundColor = UIColor(red:0, green:0, blue:0, alpha:kDefaultShadowOpacity) + view.backgroundColor = UIColor(red:0, green:0, blue:0, alpha:appearance.kDefaultShadowOpacity) view.addSubview(baseView) // Base View baseView.frame = view.frame baseView.addSubview(contentView) // Content View contentView.backgroundColor = UIColor(white:1, alpha:1) - contentView.layer.cornerRadius = contentViewCornerRadius + contentView.layer.cornerRadius = appearance.contentViewCornerRadius contentView.layer.masksToBounds = true contentView.layer.borderWidth = 0.5 contentView.addSubview(labelTitle) @@ -175,20 +238,20 @@ public class SCLAlertView: UIViewController { circleBG.layer.cornerRadius = circleBG.frame.size.height / 2 baseView.addSubview(circleBG) circleBG.addSubview(circleView) - let x = (kCircleHeightBackground - kCircleHeight) / 2 - circleView.frame = CGRect(x:x, y:x, width:kCircleHeight, height:kCircleHeight) + let x = (kCircleHeightBackground - appearance.kCircleHeight) / 2 + circleView.frame = CGRect(x:x, y:x, width:appearance.kCircleHeight, height:appearance.kCircleHeight) circleView.layer.cornerRadius = circleView.frame.size.height / 2 // Title labelTitle.numberOfLines = 1 labelTitle.textAlignment = .Center - labelTitle.font = UIFont(name: kDefaultFont, size:20) - labelTitle.frame = CGRect(x:12, y:kTitleTop, width: kWindowWidth - 24, height:kTitleHeight) + labelTitle.font = appearance.kTitleFont + labelTitle.frame = CGRect(x:12, y:appearance.kTitleTop, width: appearance.kWindowWidth - 24, height:appearance.kTitleHeight) // View text viewText.editable = false viewText.textAlignment = .Center viewText.textContainerInset = UIEdgeInsetsZero viewText.textContainer.lineFragmentPadding = 0; - viewText.font = UIFont(name: kDefaultFont, size:14) + viewText.font = appearance.kTextFont // Colours contentView.backgroundColor = UIColorFromRGB(0xFFFFFF) labelTitle.textColor = UIColorFromRGB(0x4D4D4D) @@ -200,10 +263,6 @@ public class SCLAlertView: UIViewController { self.view.addGestureRecognizer(tapGesture) } - override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { - super.init(nibName:nibNameOrNil, bundle:nibBundleOrNil) - } - override public func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() let rv = UIApplication.sharedApplication().keyWindow! as UIWindow @@ -215,14 +274,14 @@ public class SCLAlertView: UIViewController { // computing the right size to use for the textView let maxHeight = sz.height - 100 // max overall height var consumedHeight = CGFloat(0) - consumedHeight += kTitleTop + kTitleHeight + consumedHeight += appearance.kTitleTop + appearance.kTitleHeight consumedHeight += 14 - consumedHeight += kButtonHeight * CGFloat(buttons.count) - consumedHeight += kTextFieldHeight * CGFloat(inputs.count) - consumedHeight += kTextViewdHeight * CGFloat(input.count) + consumedHeight += appearance.kButtonHeight * CGFloat(buttons.count) + consumedHeight += appearance.kTextFieldHeight * CGFloat(inputs.count) + consumedHeight += appearance.kTextViewdHeight * CGFloat(input.count) let maxViewTextHeight = maxHeight - consumedHeight - let viewTextWidth = kWindowWidth - 24 - var viewTextHeight = kTextHeight + let viewTextWidth = appearance.kWindowWidth - 24 + var viewTextHeight = appearance.kTextHeight // Check if there is a custom subview and add it over the textview if let customSubview = customSubview { @@ -244,39 +303,39 @@ public class SCLAlertView: UIViewController { let windowHeight = consumedHeight + viewTextHeight // Set frames - var x = (sz.width - kWindowWidth) / 2 - var y = (sz.height - windowHeight - (kCircleHeight / 8)) / 2 - contentView.frame = CGRect(x:x, y:y, width:kWindowWidth, height:windowHeight) - contentView.layer.cornerRadius = contentViewCornerRadius + var x = (sz.width - appearance.kWindowWidth) / 2 + var y = (sz.height - windowHeight - (appearance.kCircleHeight / 8)) / 2 + contentView.frame = CGRect(x:x, y:y, width:appearance.kWindowWidth, height:windowHeight) + contentView.layer.cornerRadius = appearance.contentViewCornerRadius y -= kCircleHeightBackground * 0.6 x = (sz.width - kCircleHeightBackground) / 2 circleBG.frame = CGRect(x:x, y:y+6, width:kCircleHeightBackground, height:kCircleHeightBackground) //adjust Title frame based on circularIcon show/hide flag - let titleOffset : CGFloat = showCircularIcon ? 0.0 : -12.0 + let titleOffset : CGFloat = appearance.showCircularIcon ? 0.0 : -12.0 labelTitle.frame = labelTitle.frame.offsetBy(dx: 0, dy: titleOffset) // Subtitle - y = kTitleTop + kTitleHeight + titleOffset - viewText.frame = CGRect(x:12, y:y, width: kWindowWidth - 24, height:kTextHeight) + y = appearance.kTitleTop + appearance.kTitleHeight + titleOffset + viewText.frame = CGRect(x:12, y:y, width: appearance.kWindowWidth - 24, height:appearance.kTextHeight) viewText.frame = CGRect(x:12, y:y, width: viewTextWidth, height:viewTextHeight) // Text fields y += viewTextHeight + 14.0 for txt in inputs { - txt.frame = CGRect(x:12, y:y, width:kWindowWidth - 24, height:30) - txt.layer.cornerRadius = fieldCornerRadius - y += kTextFieldHeight + txt.frame = CGRect(x:12, y:y, width:appearance.kWindowWidth - 24, height:30) + txt.layer.cornerRadius = appearance.fieldCornerRadius + y += appearance.kTextFieldHeight } for txt in input { - txt.frame = CGRect(x:12, y:y, width:kWindowWidth - 24, height:70) + txt.frame = CGRect(x:12, y:y, width:appearance.kWindowWidth - 24, height:70) //txt.layer.cornerRadius = fieldCornerRadius - y += kTextViewdHeight + y += appearance.kTextViewdHeight } // Buttons for btn in buttons { - btn.frame = CGRect(x:12, y:y, width:kWindowWidth - 24, height:35) - btn.layer.cornerRadius = buttonCornerRadius - y += kButtonHeight + btn.frame = CGRect(x:12, y:y, width:appearance.kWindowWidth - 24, height:35) + btn.layer.cornerRadius = appearance.buttonCornerRadius + y += appearance.kButtonHeight } } @@ -300,11 +359,11 @@ public class SCLAlertView: UIViewController { public func addTextField(title:String?=nil)->UITextField { // Update view height - kWindowHeight += kTextFieldHeight + appearance.setkWindowHeight(appearance.kWindowHeight + appearance.kTextFieldHeight) // Add text field let txt = UITextField() txt.borderStyle = UITextBorderStyle.RoundedRect - txt.font = UIFont(name:kDefaultFont, size: 14) + txt.font = appearance.kTextFont txt.autocapitalizationType = UITextAutocapitalizationType.Words txt.clearButtonMode = UITextFieldViewMode.WhileEditing txt.layer.masksToBounds = true @@ -319,11 +378,11 @@ public class SCLAlertView: UIViewController { public func addTextView()->UITextView { // Update view height - kWindowHeight += kTextViewdHeight + appearance.setkWindowHeight(appearance.kWindowHeight + appearance.kTextViewdHeight) // Add text view let txt = UITextView() // No placeholder with UITextView but you can use KMPlaceholderTextView library - txt.font = UIFont(name:kDefaultFont, size: 14) + txt.font = appearance.kTextFont //txt.autocapitalizationType = UITextAutocapitalizationType.Words //txt.clearButtonMode = UITextFieldViewMode.WhileEditing txt.layer.masksToBounds = true @@ -356,12 +415,12 @@ public class SCLAlertView: UIViewController { private func addButton(title:String, backgroundColor:UIColor? = nil, textColor:UIColor? = nil, showDurationStatus:Bool=false)->SCLButton { // Update view height - kWindowHeight += kButtonHeight + appearance.setkWindowHeight(appearance.kWindowHeight + appearance.kButtonHeight) // Add button let btn = SCLButton() btn.layer.masksToBounds = true btn.setTitle(title, forState: .Normal) - btn.titleLabel?.font = UIFont(name:kButtonFont, size: 14) + btn.titleLabel?.font = appearance.kButtonFont btn.customBackgroundColor = backgroundColor btn.customTextColor = textColor btn.initialTitle = title @@ -381,7 +440,7 @@ public class SCLAlertView: UIViewController { print("Unknow action type for button") } - if(self.view.alpha != 0.0 && shouldAutoDismiss){ hideView() } + if(self.view.alpha != 0.0 && appearance.shouldAutoDismiss){ hideView() } } @@ -435,7 +494,7 @@ public class SCLAlertView: UIViewController { func tapped(gestureRecognizer: UITapGestureRecognizer) { self.view.endEditing(true) - if let tappedView = gestureRecognizer.view where tappedView.hitTest(gestureRecognizer.locationInView(tappedView), withEvent: nil) == baseView && hideWhenBackgroundViewIsTapped { + if let tappedView = gestureRecognizer.view where tappedView.hitTest(gestureRecognizer.locationInView(tappedView), withEvent: nil) == baseView && appearance.hideWhenBackgroundViewIsTapped { hideView() } @@ -535,23 +594,23 @@ public class SCLAlertView: UIViewController { // Adjust text view size, if necessary let str = subTitle as NSString let attr = [NSFontAttributeName:viewText.font ?? UIFont()] - let sz = CGSize(width: kWindowWidth - 24, height:90) + let sz = CGSize(width: appearance.kWindowWidth - 24, height:90) let r = str.boundingRectWithSize(sz, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes:attr, context:nil) let ht = ceil(r.size.height) - if ht < kTextHeight { - kWindowHeight -= (kTextHeight - ht) - kTextHeight = ht + if ht < appearance.kTextHeight { + appearance.kWindowHeight -= (appearance.kTextHeight - ht) + appearance.setkTextHeight(ht) } } // Done button - if showCloseButton { + if appearance.showCloseButton { addButton(completeText ?? "Done", target:self, selector:#selector(SCLAlertView.hideView)) } //hidden/show circular view based on the ui option - circleView.hidden = !showCircularIcon - circleBG.hidden = !showCircularIcon + circleView.hidden = !appearance.showCircularIcon + circleBG.hidden = !appearance.showCircularIcon // Alert view colour and images circleView.backgroundColor = viewColor @@ -571,8 +630,8 @@ public class SCLAlertView: UIViewController { } } circleView.addSubview(circleIconView!) - let x = (kCircleHeight - kCircleIconHeight) / 2 - circleIconView!.frame = CGRectMake( x, x, kCircleIconHeight, kCircleIconHeight) + let x = (appearance.kCircleHeight - appearance.kCircleIconHeight) / 2 + circleIconView!.frame = CGRectMake( x, x, appearance.kCircleIconHeight, appearance.kCircleIconHeight) for txt in inputs { txt.layer.borderColor = viewColor.CGColor diff --git a/SCLAlertViewTests/SCLAlertViewPropertiesTests.swift b/SCLAlertViewTests/SCLAlertViewPropertiesTests.swift index ee9a7ce..b0ea157 100644 --- a/SCLAlertViewTests/SCLAlertViewPropertiesTests.swift +++ b/SCLAlertViewTests/SCLAlertViewPropertiesTests.swift @@ -23,91 +23,91 @@ class SCLAlertViewPropertiesTests: XCTestCase { } func testSCLAlertViewShadowOpacity() { - XCTAssertTrue(alert.kDefaultShadowOpacity == 0.7) + XCTAssertTrue(alert.appearance.kDefaultShadowOpacity == 0.7) } func testSCLAlertViewCircleTopPosition() { - XCTAssertTrue(alert.kCircleTopPosition == -12.0) + XCTAssertTrue(alert.appearance.kCircleTopPosition == -12.0) } func testSCLAlertViewBackgroundTopPosition() { - XCTAssertTrue(alert.kCircleBackgroundTopPosition == -15.0) + XCTAssertTrue(alert.appearance.kCircleBackgroundTopPosition == -15.0) } func testSCLAlertViewCircleHeight() { - XCTAssertTrue(alert.kCircleHeight == 56.0) + XCTAssertTrue(alert.appearance.kCircleHeight == 56.0) } func testSCLAlertViewIconHeight() { - XCTAssertTrue(alert.kCircleIconHeight == 20.0) + XCTAssertTrue(alert.appearance.kCircleIconHeight == 20.0) } func testSCLAlertViewTitleTop() { - XCTAssertTrue(alert.kTitleTop == 30.0) + XCTAssertTrue(alert.appearance.kTitleTop == 30.0) } func testSCLAlertViewTitleHeight() { - XCTAssertTrue(alert.kTitleHeight == 40.0) + XCTAssertTrue(alert.appearance.kTitleHeight == 40.0) } func testSCLAlertViewWindowWidth() { - XCTAssertTrue(alert.kWindowWidth == 240.0) + XCTAssertTrue(alert.appearance.kWindowWidth == 240.0) } func testSCLAlertViewWindowHeight() { - XCTAssertTrue(alert.kWindowHeight == 178.0) + XCTAssertTrue(alert.appearance.kWindowHeight == 178.0) } func testSCLAlertViewTextHeight() { - XCTAssertTrue(alert.kTextHeight == 90.0) + XCTAssertTrue(alert.appearance.kTextHeight == 90.0) } func testSCLAlertViewTextFieldHeight() { - XCTAssertTrue(alert.kTextFieldHeight == 45.0) + XCTAssertTrue(alert.appearance.kTextFieldHeight == 45.0) } func testSCLAlertViewTextButtonHeight() { - XCTAssertTrue(alert.kButtonHeight == 45.0) + XCTAssertTrue(alert.appearance.kButtonHeight == 45.0) } - func testSCLAlertViewDefaultFont() { - XCTAssertTrue(alert.kDefaultFont == "HelveticaNeue") + func testSCLAlertViewTitleFont() { + XCTAssertTrue(alert.appearance.kTitleFont == UIFont.systemFontOfSize(20)) } - func testSCLAlertViewButtonFont() { - XCTAssertTrue(alert.kButtonFont == "HelveticaNeue-Bold") + func testSCLAlertViewTextFont() { + XCTAssertTrue(alert.appearance.kTextFont == UIFont.systemFontOfSize(14)) } + func testSCLAlertViewButtonFont() { + XCTAssertTrue(alert.appearance.kButtonFont == UIFont.boldSystemFontOfSize(14)) + } + func testSCLAlertViewColor() { XCTAssertTrue(alert.viewColor.isKindOfClass(UIColor.self)) } - func testSCLAlertViewPressBrightnessFactor() { - XCTAssertTrue(alert.pressBrightnessFactor == 0.85) - } - func testSCLAlertViewShowCloseButton() { - XCTAssertTrue(alert.showCloseButton == true) + XCTAssertTrue(alert.appearance.showCloseButton == true) } func testSCLAlertViewShowCircularIcon() { - XCTAssertTrue(alert.showCircularIcon == true) + XCTAssertTrue(alert.appearance.showCircularIcon == true) } func testSCLAlertViewContentViewCornerRadius() { - XCTAssertTrue(alert.contentViewCornerRadius == 5.0) + XCTAssertTrue(alert.appearance.contentViewCornerRadius == 5.0) } func testSCLAlertViewFieldCornerRadius() { - XCTAssertTrue(alert.fieldCornerRadius == 3.0) + XCTAssertTrue(alert.appearance.fieldCornerRadius == 3.0) } func testSCLAlertViewButtonCornerRadius() { - XCTAssertTrue(alert.buttonCornerRadius == 3.0) + XCTAssertTrue(alert.appearance.buttonCornerRadius == 3.0) } func testSCLAlertViewHideWhenBackgroundViewIsTapped() { - XCTAssertTrue(alert.hideWhenBackgroundViewIsTapped == false) + XCTAssertTrue(alert.appearance.hideWhenBackgroundViewIsTapped == false) } func testSCLAlertViewBaseView() {