Flexible UI Framework Designed for Swift

Overview

Overlay

Build Status Carthage Compatible CocoaPods Compatible

Overlay is a very flexible UI framework designed for Swift.

Note: Overlay is still under development and many things are subject to change.

Features

  • Protocol oriented design
  • Interface Builder support
  • Comprehensive unit test coverage
  • Complete documentation

Requirements

iOS 9+ / Xcode 9+ / Swift 4+

Installation

Carthage

Carthage is a decentralized dependency manager. To install Overlay, add the following line to your Cartfile:

github "TintPoint/Overlay" ~> 0.7

CocoaPods

CocoaPods is a centralized dependency manager. To install Overlay, add the following line to your Podfile:

pod 'Overlay', '~> 0.7'

Example

Overlay allows one to write declarative yet type-safe UI code, something looks like this:

@IBDesignable
class StandardTextField: UITextField, CustomTextColor, CustomPlaceholderTextColor, CustomFont, CustomTextAlignment {
    let textColorStyle: ColorStyle = Color.primary
    let placeholderTextColorStyle: ColorStyle = Color.secondary
    let fontStyle: FontStyle = Font.default
    let textAlignmentStyle: TextAlignmentStyle = TextAlignment.body
}

Getting Started

Define a custom class that conforms to protocols with Custom prefix (list of available protocols can be found here). For example, to customize the background color attribute of a view, write the following code.

class CustomView: UIView, CustomBackgroundColor {
    let backgroundColorStyle: ColorStyle = UIColor.white
}

The compiler will emit an error if CustomView's superclass (in this case, UIView) is not BackgroundColorCustomizable, or backgroundColorStyle is not implemented by CustomView. UIColor is already conformed to ColorStyle protocol so it can be used here. Font and other attributes can also be customized similarly.

CustomView can be used like other views, but it is recommended to use it with Interface Builder.

Open the storyboard file (or nib file), select the view you want to change, navigate to Identity Inceptor, and set Custom Class to CustomView.

Creating views programmatically is also supported.

let customView = CustomView()
customView.refresh() // make sure to call refresh() after initialization

Advanced Usage

Custom Style

In order to fully take advantage of the power of Swift's type checker, it is recommended to define custom enums (or structs with private initializers) that conform to protocols with Style postfix (list of available styles can be found here).

enum CustomColor: ColorStyle {
    case normal, disabled
    func normal() -> UIColor {
        switch self {
        case .normal: return UIColor.white
        case .disabled: return UIColor.black
        }
    }
}

Previous example can be rewritten as the following code.

class CustomView: UIView, CustomBackgroundColor {
    let backgroundColorStyle: ColorStyle = CustomColor.normal
}

Style Group

For views which have more than one states (e.g. UIButton), their appearance usually needs to change base on state changes. All custom styles have corresponding style groups that support this feature (list of available style groups can be found here).

class CustomButton: UIButton, CustomBackgroundColor {
    let backgroundColorStyle: ColorStyle = ColorGroup(normal: CustomColor.normal, disabled: CustomColor.disabled)
}

It is also possible to implement app-specific style groups by conforming to protocols with StyleGroup postfix.

enum CustomColorGroup: ColorStyleGroup {
    case standard
    func normal() -> UIColor {
        return UIColor.white
    }
    func disabled() -> UIColor? {
        return UIColor.black
    }
}

class CustomButton: UIButton, CustomBackgroundColor {
    let backgroundColorStyle: ColorStyle = CustomColorGroup.standard
}

States defined in a style group but aren't supported by the view using it will be ignored. Currently, it is required to call refresh() after changing the state.

button.isEnabled = true
button.refresh()

Other Attributes

Overlay supports customizing views' colors, fonts, images, texts and text alignments.

However, it is still possible to customize other attributes by adopting protocols with Design postfix.

class BorderView: UIView, CustomViewDesign {
    let design: (UIView) -> Void = { view in
        view.layer.borderWidth = 1
    }
}

Custom Layout

Most views contain subviews. Overlay is designed with this in mind, but it's not its goal to handle subview layouts. Overlay should only handle views' style attributes (like colors and fonts), and the main application should handle views' layouts (like origin and size). CustomLayout protocol allows Overlay to work with Interface Builder together seamlessly.

Define a custom class that conforms to CustomLayout protocol. Then create a nib file and set its File's Owner to the newly defined class.

class ComplexView: UIView, CustomLayout {
    let contentNib: UINib = UINib(nibName: "ComplexView", bundle: Bundle(for: ComplexView.self))
}

The first root view inside ComplexView.xib will be loaded and added as a content view of ComplexView. Note: Added view's background color usually should be clear color.

Create IBOutlet and connect them like usual, if needed.

class ComplexView: UIView, CustomLayout {
    let contentNib: UINib = UINib(nibName: "ComplexView", bundle: Bundle(for: ComplexView.self))
    @IBOutlet weak var button: CustomButton?
}

Reference

Available Protocols

Custom Cell

  • CustomCell
  • CustomHeaderFooterView
  • CustomReusableView

Custom Design

  • CustomActivityIndicatorViewDesign
  • CustomBarButtonItemDesign
  • CustomBarItemDesign
  • CustomButtonDesign
  • CustomCollectionViewDesign
  • CustomControlDesign
  • CustomDatePickerDesign
  • CustomDesign
  • CustomImageViewDesign
  • CustomLabelDesign
  • CustomNavigationBarDesign
  • CustomPageControlDesign
  • CustomPickerViewDesign
  • CustomProgressViewDesign
  • CustomScrollViewDesign
  • CustomSearchBarDesign
  • CustomSegmentedControlDesign
  • CustomSliderDesign
  • CustomStackViewDesign
  • CustomStepperDesign
  • CustomSwitchDesign
  • CustomTabBarDesign
  • CustomTabBarItemDesign
  • CustomTableViewDesign
  • CustomTextFieldDesign
  • CustomTextViewDesign
  • CustomToolbarDesign
  • CustomViewDesign
  • CustomWebViewDesign

Custom Layout

  • CustomLayout

Custom Color

  • CustomBackgroundColor
  • CustomBadgeColor
  • CustomBarTintColor
  • CustomBorderColor
  • CustomColor
  • CustomMaximumTrackTintColor
  • CustomMinimumTrackTintColor
  • CustomOnTintColor
  • CustomPlaceholderTextColor
  • CustomProgressTintColor
  • CustomSectionIndexBackgroundColor
  • CustomSectionIndexColor
  • CustomSectionIndexTrackingBackgroundColor
  • CustomSeparatorColor
  • CustomShadowColor
  • CustomTextColor
  • CustomThumbTintColor
  • CustomTintColor
  • CustomTitleColor
  • CustomTitleShadowColor
  • CustomTrackTintColor
  • CustomUnselectedItemTintColor

Custom Font

  • CustomFont
  • CustomTitleFont

Custom Image

  • CustomBackgroundImage
  • CustomDecrementImage
  • CustomHighlightedImage
  • CustomImage
  • CustomIncrementImage
  • CustomLandscapeImagePhone
  • CustomMaximumTrackImage
  • CustomMaximumValueImage
  • CustomMinimumTrackImage
  • CustomMinimumValueImage
  • CustomOffImage
  • CustomOnImage
  • CustomProgressImage
  • CustomScopeBarButtonBackgroundImage
  • CustomSearchFieldBackgroundImage
  • CustomSelectedImage
  • CustomShadowImage
  • CustomThumbImage
  • CustomTrackImage

Custom Text

  • CustomPlaceholder
  • CustomPrompt
  • CustomScopeButtonTitles
  • CustomSegmentTitles
  • CustomText
  • CustomTitle

Custom Text Alignment

  • CustomTextAlignment
  • CustomTitleTextAlignment

Available Styles

  • ColorStyle
  • ColorStyleGroup
  • FontStyle
  • FontStyleGroup
  • ImageStyle
  • ImageStyleGroup
  • TextAlignmentStyle
  • TextAlignmentStyleGroup
  • TextStyle
  • TextStyleGroup

Available Style Groups

  • ColorGroup
  • FontGroup
  • ImageGroup
  • TextAlignmentGroup
  • TextGroup

Available States

ViewHideable

  • UIView and its subclasses

ViewFocusable

  • UIView and its subclasses

ViewDisable

  • UIBarButtonItem
  • UIBarItem
  • UIButton
  • UIControl
  • UIDatePicker
  • UILabel
  • UIPageControl
  • UIRefreshControl
  • UISegmentedControl
  • UISlider
  • UIStepper
  • UISwitch
  • UITabBarItem
  • UITextField

ViewSelectable

  • UIButton
  • UIControl
  • UIDatePicker
  • UIPageControl
  • UIRefreshControl
  • UISegmentedControl
  • UISlider
  • UIStepper
  • UISwitch
  • UITableViewCell
  • UITextField

ViewHighlightable

  • UIButton
  • UIControl
  • UIDatePicker
  • UIImageView
  • UILabel
  • UIPageControl
  • UIRefreshControl
  • UISegmentedControl
  • UISlider
  • UIStepper
  • UISwitch
  • UITableViewCell
  • UITextField
Comments
  • Special UIButton Subclass Crashes Interface Builder

    Special UIButton Subclass Crashes Interface Builder

    Adding @IBDesignable to a UIButton subclass crashes Interface Builder, if the class contains instance variables cast to protocol types.

    Steps to Reproduce

    1. Create an project
    2. Add a button to Interface Builder
    3. Change the custom class to CustomButton
    4. Add the following code
    @IBDesignable class CustomButton: UIButton, CustomTitleColor {
        let titleColorStyle: ColorStyle = UIColor.white // ColorStyle is a protocol, IB will crash
    }
    

    Some Other Examples

    @IBDesignable class CrashedButton: UIButton {
        let foo: Any = "Text" // Any is a protocol, IB will crash
    }
    
    @IBDesignable class OKButton: UIButton {
        let foo: String = "Text" // String is not a protocol, OK
    }
    
    bug 
    opened by JustinJiaDev 1
  • Customizable Redesign

    Customizable Redesign

    Advantages

    1. This redesign allows us to remove duplicate protocols (e.g. CustomFont and CustomLabelFont) while still maintaining compile time check.
    2. This redesign allows third party views to support Overlay.
    enhancement high priority 
    opened by JustinJiaDev 1
  • Swift Limitations

    Swift Limitations

    Covariance in Generic Protocols

    If covariance in generic protocols is supported, we can replace all *Style protocols with a Style<T> protocol.

    Example Usage

    protocol Style<T> {
        func normal() -> T
    }
    
    protocol CustomFont: FontCustomizable {
        var fontStyle: Style<UIFont> { get }
    }
    
    class CustomLabel: UILabel, CustomFont {
        var fontStyle: Style<UIFont> = MyFont.standard // MyFont is an enum that conforms to Style<UIFont>
    }
    

    Blog post that explains the situation in detail: Generic Protocols and Their Shortcomings

    Related proposal (not useful but close): Swift 4 Proposal

    Property Observers in Extension

    If we can observe property changes inside class extension, users don't need to call refresh() explicitly after state changes.

    Workaround: Swift Method Swizzling

    enhancement help wanted 
    opened by JustinJiaDev 1
  • Implement Text Style

    Implement Text Style

    Implemented

    UIBarItem's subclasses

    var title: String? { get set }
    

    UIButton

    func setTitle(_ title: String?, for state: UIControlState)
    

    UILabel

    var text: String? { get set }
    

    UISearchBar

    var placeholder: String? { get set }
    var prompt: String? { get set }
    var text: String? { get set }
    var scopeButtonTitles: [String]? { get set }
    

    UITextField

    var text: String? { get set }
    var placeholder: String? { get set }
    

    UITextView

    var text: String! { get set }
    

    UISegmentedControl

    func setTitle(String?, forSegmentAt: Int)
    

    Won't Implement

    UILabel

    var text: String? { get set }
    var attributedText: NSAttributedString? { get set }
    

    UIButton

    func setAttributedTitle(NSAttributedString?, for: UIControlState)
    

    UITextField

    var attributedText: NSAttributedString? { get set }
    var attributedPlaceholder: NSAttributedString? { get set }
    

    UITextView

    var attributedText: NSAttributedString! { get set }
    

    UIMenuItem

    var title: String? { get set }
    

    UINavigationItem

    var title: String? { get set }
    

    UITableViewRowAction

    var title: String? { get set }
    
    enhancement good first issue 
    opened by JustinJiaDev 0
  • Add Style Expressible

    Add Style Expressible

    • Add ColorStyleExpressible
    • Add FontStyleExpressible
    • Add ImageStyleExpressible
    • Move selected and setColor to ColorStyleExpressible
    • Move selected to FontStyleExpressible
    • Move selected and setImage to ImageStyleExpressible
    • Update tests
    enhancement 
    opened by JustinJiaDev 0
  • Support Customizing Image with UIBarPosition and UIBarMetrics

    Support Customizing Image with UIBarPosition and UIBarMetrics

    A few methods haven't been implemented yet.

    UIToolbar

    func setBackgroundImage(_ backgroundImage: UIImage?, forToolbarPosition topOrBottom: UIBarPosition, barMetrics: UIBarMetrics)
    func setShadowImage(_ shadowImage: UIImage?, forToolbarPosition topOrBottom: UIBarPosition)
    

    UIBarButtonItem

    func setBackButtonBackgroundImage(_ backgroundImage: UIImage?, for state: UIControlState, barMetrics: UIBarMetrics)
    func setBackgroundImage(_ backgroundImage: UIImage?, for state: UIControlState, barMetrics: UIBarMetrics)
    func setBackgroundImage(_ backgroundImage: UIImage?, for state: UIControlState, style: UIBarButtonItemStyle, barMetrics: UIBarMetrics)
    

    UISegmentedControl

    func setImage(_ image: UIImage?, forSegmentAt segment: Int)
    func setBackgroundImage(_ backgroundImage: UIImage?, for state: UIControlState, barMetrics: UIBarMetrics)
    func setDividerImage(_ dividerImage: UIImage?, forLeftSegmentState leftState: UIControlState, rightSegmentState rightState: UIControlState, barMetrics: UIBarMetrics)
    

    UISearchBar

    func setBackgroundImage(_ backgroundImage: UIImage?, for barPosition: UIBarPosition, barMetrics: UIBarMetrics)
    func setImage(_ iconImage: UIImage?, for icon: UISearchBarIcon, state: UIControlState)
    func setScopeBarButtonDividerImage(_ dividerImage: UIImage?, forLeftSegmentState leftState: UIControlState, rightSegmentState rightState: UIControlState)
    

    UIStepper

    func setDividerImage(_ image: UIImage?, forLeftSegmentState leftState: UIControlState, rightSegmentState rightState: UIControlState)
    
    
    enhancement 
    opened by JustinJiaDev 0
Releases(0.7)
Owner
TintPoint
We make apps and other things.
TintPoint
NotSwiftUI is designed to help you create UI components quickly and efficiently with code!

NotSwiftUI NotSwiftUI is designed to help you create UI components quickly and efficiently with code! Capitalizing on the idea that most of the UI ele

Jonathan G. 50 Dec 20, 2022
Flexible Mustache templates for Swift

GRMustache.swift Mustache templates for Swift Latest release: October 23, 2016 • version 2.0.0 • CHANGELOG Requirements: iOS 8.0+ / OSX 10.9+ / tvOS 9

Gwendal Roué 569 Dec 27, 2022
TSnackBarView is a simple and flexible UI component fully written in Swift

TSnackBarView is a simple and flexible UI component fully written in Swift. TSnackBarView helps you to show snackbar easily with 3 styles: normal, successful and error

Nguyen Duc Thinh 3 Aug 22, 2022
TDetailBoxView is a simple and flexible UI component fully written in Swift

TDetailBoxView is a simple and flexible UI component fully written in Swift. TDetailBoxView is developed to help users quickly display the detail screen without having to develop from scratch.

Nguyen Duc Thinh 2 Aug 18, 2022
TSwitchLabel is a simple and flexible UI component fully written in Swift.

TSwitchLabel is a simple and flexible UI component fully written in Swift. TSwitchLabel is developed for you to easily use when you need to design a UI with Label and Switch in the fastest way without having to spend time on develop from scratch.

Nguyen Duc Thinh 2 Aug 18, 2022
A flexible container view featuring a solid background with rounded corners.

A flexible container view featuring a solid background with rounded corners.

Tim Oliver 13 Jan 22, 2022
Protocol oriented, type safe, scalable design system foundation swift framework for iOS.

Doric: Design System Foundation Design System foundation written in Swift. Protocol oriented, type safe, scalable framework for iOS. Features Requirem

Jay 93 Dec 6, 2022
Lightweight framework for Unsplash in Swift

Lightweight framework for Unsplash in Swift

Pablo Camiletti 12 Dec 30, 2022
Swift extensions for UIKit.framework.

XUIKit Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation XUIKit is a

FITZ 0 Oct 22, 2021
A child view controller framework that makes setting up your parent controllers as easy as pie.

Description Family is a child view controller framework that makes setting up your parent controllers as easy as pie. With a simple yet powerful publi

Christoffer Winterkvist 246 Dec 28, 2022
Material, a UI/UX framework for creating beautiful iOS applications

Material Welcome to Material, a UI/UX framework for creating beautiful applications. Material's animation system has been completely reworked to take

Cosmicmind 12k Jan 2, 2023
Neumorphism framework for UIKit.

NeumorphismKit is neumorphism framework for UIKit. Requirements iOS 12.0+ Swift 5.1+ Versions NeumorphismKit version Xcode version 1.0.0 Xcode 11+ 1.1

y-okudera 42 Dec 13, 2022
Full configurable spreadsheet view user interfaces for iOS applications. With this framework, you can easily create complex layouts like schedule, gantt chart or timetable as if you are using Excel.

kishikawakatsumi/SpreadsheetView has moved! It is being actively maintained at bannzai/SpreadsheetView. This fork was created when the project was mov

Kishikawa Katsumi 34 Sep 26, 2022
A framework which helps you attach observers to `UIView`s to get updates on its frame changes

FrameObserver is a framework that lets you attach observers to any UIView subclass and get notified when its size changes. It doesn't use any Method S

null 11 Jul 25, 2022
List tree data souce to display hierachical data structures in lists-like way. It's UI agnostic, just like view-model and doesn't depend on UI framework

SwiftListTreeDataSource List tree data souce to display hierachical data structures in lists-like way. It's UI agnostic, just like view-model, so can

Dzmitry Antonenka 26 Nov 26, 2022
The Napp Drawer module extends the Appcelerator Titanium Mobile framework.

Titanium Napp Drawer Module Description The Napp Drawer module extends the Appcelerator Titanium Mobile framework. The module is licensed under the MI

null 12 Sep 15, 2022
📹 Framework to Play a Video in the Background of any UIView

SwiftVideoBackground is an easy to use Swift framework that provides the ability to play a video on any UIView. This provides a beautiful UI for login

Wilson Ding 334 Jan 7, 2023
Shadow - Syntactic sugar for shadows in the SwiftUI framework

Shadow Syntactic sugar for shadows in the SwiftUI framework. import SwiftUI impo

Dima Koskin 2 Jan 31, 2022