Skip to content
vbenkevichPublic

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Latest commit

 

History

49 Commits

Folders and files

Repository files navigation

JetLayout

CI Status Version License Platform

JetLayout is a swift based layout system. It has a syntax like SwiftUI, but JetLayout could be used with iOS 11. Layout engine is based on Autolayout, so JetLayout's widgets could be easily integrated into an existing application. RxSwift is used to wiring UI and data. Since all layouts has written in code it possible to use plugins like R.swift to provide strong typed access to assets.

Requirements

iOS 11

Swift 5.2

Installation

JetLayout is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'JetLayout'

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Usage

Sample of the layout:

VStack(spacing: 8) {
    Image(#imageLiteral(resourceName: "Logo"))
    
    Text("Email").addMargin(top: 8)
    Field(viewModel.$email)
        .contentType(.emailAddress)
        .placeholder("email@example.com")

    Text("Password").addMargin(top: 8)
    Field(viewModel.$password)
        .isSecureTextEntry(true)
        .placeholder("strong password")
        .addMargin(bottom: 24)
    
    Button(type: .system, title: "Sign In")
        .corner(radius: 8)
        .size(height: 32)
        .font(.boldSystemFont(ofSize: 16))
        .align(left: 16, right: 16)
}

Sample of wrapping existing UIView into Widget:

Widget(UIActivityIndicatorView())
    .alignment(.center())
    // setup before adding to layout
    .setup(block: { view in
        view.hidesWhenStopped = true
        view.color = .red
    })
    // UIView hold reference to the dispose bag
    .bind(viewModel.$showActivity) { (view, show) in
        if (show) {
            view.startAnimating()
        } else {
            view.stopAnimating()
        }
    }

Complex UI can be easily separated into small blocks:

struct AddItemView: View {
    
    let onAddClicked: (String) -> Void
    
    @Observed
    private var itemName: String? = "Add new item"

    var body: Layout {
        HStack(spacing: 16) {
            Field(self.$itemName).placeholder("Item mame")
            
            Button(type: .contactAdd)
                .disabled(source: self.$itemName.isEmpty)
                .tap {
                    self.onAddClicked(self.itemName ?? "")
                    self.itemName = ""
                }
        }
    }
}

TableView example:

struct ItemsTable: View {
    
    let items: Observed<[String]>
    
    var body: Layout {
        Table {
            // Cells registration
            ItemCell.register()
            
            // Static section at top
            TSection {
                Image(#imageLiteral(resourceName: "Logo"))
                    .alignment(.fill())
                    .size(height: 80)
                    .contentMode(.scaleAspectFit)
            }
            
            // Dynamic section
            TSection(source: self.items)
        }
        .preserveParentPadding()
    }
}

class ItemCell: ViewBasedTableCell<String> {
    
    override var view: View {
        HStack {
            Text(self.$model)
        }
        .preserveParentPadding()
    }
}

Wiring toogether and attaching layout to UIViewController:

@Observed
var items: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()
    title = "Dynamic table view"
    
    VStack(spacing: 24) {
        AddItemView { [weak self] in self?.items.append($0) }
        
        ItemsTable(items: self.$items)
    }
    .root(of: self)
}

View could be alligned both superview's bounds and superview's margins. View also can preserve superview margins.

ZStack {
    // View 20x20 in the top-right corner. distance to top = 10, distance to rignt = 0
    Empty(color: .green, size: CGSize(width: 20, height: 20))
        .alignment(Alignment.top().right())
        .align(topPadding: true, rightPadding: false)
    
    // this stack alligned to superview's bounds but preserve superview paddings
    HStack {
        Empty(color: .red)
            .align(toPadding: false)
            .align(leftPadding: true)
        
        Empty(color: .blue)
            .align(bottomPadding: false)
    }
    .distribution(.fillEqually)
    .padding(12) // own padding (at least 12)
    .preserveParentPadding() // keep superview padding (result padding: horizontal = 12, vertical = 16)
}
.padding(vertical: 16)

Animation sample:

@Observed
var termsAccepted = false

VStack(spacing: 8) {
    HStack(spacing: 8) {
        Text("I accept terms and conditions: ").numberOfLines(2)
        Switch(self.$termsAccepted)
    }
            
    Button(type: .system, title: "Sign In")
        .add(Animation.expanded(self.$termsAccepted))
}

Author

License

JetLayout is available under the MIT license. See the LICENSE file for more info.

About

No description, website, or topics provided.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages