Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/wordlessj/Bamboo

Auto Layout (and manual layout) in one line.
https://github.com/wordlessj/Bamboo

auto autolayout ios layout manual swift

Last synced: 3 months ago
JSON representation

Auto Layout (and manual layout) in one line.

Awesome Lists containing this project

README

        

![Bamboo](https://raw.githubusercontent.com/wordlessj/Bamboo/master/Assets/Logo.png)


[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](#carthage)
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Bamboo.svg)](#cocoapods)
![Swift 4.2](https://img.shields.io/badge/Swift-4.2-orange.svg)
![Platform](https://img.shields.io/badge/platform-iOS%209.0%2B%20%7C%20macOS%2010.11%2B%20%7C%20tvOS%209.0%2B-lightgrey.svg)
[![Build Status](https://travis-ci.org/wordlessj/Bamboo.svg?branch=master)](https://travis-ci.org/wordlessj/Bamboo)

Auto Layout (and manual layout) in one line.

## Quick Look

```swift
view.bb.centerX().below(view2).size(100)
```

It’s equivalent to iOS 9 API:

```swift
view.centerXAnchor.constraint(equalTo: view.superview!.centerXAnchor).isActive = true
view.topAnchor.constraint(equalTo: view2.bottomAnchor).isActive = true
view.widthAnchor.constraint(equalToConstant: 100).isActive = true
view.heightAnchor.constraint(equalToConstant: 100).isActive = true
```

As you can see, Bamboo eliminated a lot of redundant code.

- Using chaining style, you can write view’s name just once.
- All methods are grouped in `bb` extension, so their names can be simple and short.
- Superview and anchor are usually implied.
- More higher level methods like `below()` and `size()` make things easier.

## Installation

### Carthage

```
github "wordlessj/Bamboo" ~> 1.0
```

### CocoaPods

```
pod 'Bamboo', '~> 1.0'
```

## Usage

### Basics

All basic anchors on `UIView` and `UILayoutGuide` are provided with suffix `Anchor` stripped, e.g., `left` instead of `leftAnchor`.

```swift
// view.left == superview.left
view.bb.left()

// Or use it on UILayoutGuide.
layoutGuide.bb.left()
```

To specify another view’s corresponding anchor, simply pass the view to the method.

```swift
// view1.left == view2.left
view1.bb.left(view2)
```

Of course, you can use a specific anchor.

```swift
// view1.left == view2.right
view1.bb.left(view2.rightAnchor)
```

Including a constant is straightforward using operator `+` or `-`.

```swift
// view1.left == view2.right + 10
view1.bb.left(view2.rightAnchor + 10)

// Specific view or anchor can be omitted.
// view.left == superview.left + 10
view.bb.left(10)
```

For dimension anchors, when only a constant is specified, it sets the dimension to the constant, instead of matching to superview.

```swift
// view.width == 10
view.bb.width(10)
```

> `width()` and `width(0)` are different, the former match to superview and the latter set to 0.

In iOS 11, you can use `SystemSpacing` in place of constant, pass multiplier to the initializer, only `+` operator is supported.

```swift
// view1.left == view2.right + 2 * SystemSpacing
view1.bb.left(view2.rightAnchor + SystemSpacing(2))
```

Similarly, use `>=` or `<=` to specify equality.

```swift
// view1.left >= view2.right + 10
view1.bb.left(>=view2.rightAnchor + 10)
```

To specify priority, use operator `~`.

```swift
// view1.left == view2.right + 10 (priority 500)
view1.bb.left(view2.rightAnchor + 10 ~ 500)
```

For dimension anchors, multiplier can be specified with `*` or `/`.

```swift
// view1.width == 2 * view2.width
view1.bb.width(2 * view2)
```

### Expression

Expressions are passed to basic anchor methods. Full form:

```
( >= or <= ) item + constant ~ priority
```

For dimension anchors:

```
( >= or <= ) item * multiplier + constant ~ priority
```

`item` can be `UIView`, `UILayoutGuide` or `NSLayoutAnchor`. You can use `/` and `-` instead of `*` and `+`. If equality is not specified, `multiplier` can be put before `item` to be more like linear functions. More complex expressions can be created, but for simplicity, it’s not recommended.

### Constraints

You can get a single constraint created from the method for later use.

```swift
let c: NSLayoutConstraint = view.bb.left().constraint
```

Or get all constraints accumulated from the chain.

```swift
let c: [NSLayoutConstraint] = view.bb.left().top().constraints
```

### Activate and Deactivate

Constraints can be activated and deactivated easily so you can better control the layout change.

```swift
// Deactivate after creation.
let c: [NSLayoutConstraint] = view.bb.left().top().constraints.deactivate()

// Activate later when appropriate.
c.activate()
```

### Higher Level Methods

#### Aspect Ratio

```swift
// view.width == 2 * view.height
view.bb.aspectRatio(2)
```

#### Center and Size

Both methods are similar to basic anchor methods.

- `center()`, consists of `centerX` and `centerY`.
- `size()`, consists of `width` and `height`.

There are two more methods to set size.

```swift
let cgSize: CGSize
view.bb.size(cgSize)

view.bb.size(width: 10, height: 20)
```

#### Fill

```swift
// Pin all edges.
fill()

// Pin corresponding edge and adjacent edges.
// e.g., fillLeft() pin left, top and bottom.
fill[Left|Right|Top|Bottom|Leading|Trailing]()

// Pin edges on corresponding axis.
// e.g., fillWidth() pin leading and trailing.
fill[Width|Height]()
```

All fill methods take two optional arguments, first is either `UIView` or `UILayoutGuide` to be filled, `nil` for its superview, second is a `UIEdgeInsets`.

```swift
// view1 fills view2 with insets.
let insets: UIEdgeInsets
view1.bb.fill(view2, insets: insets)

// If all edge insets are the same, you can pass a single value.
// view1 fills view2 with insets 10.
view1.bb.fill(view2, insets: 10)
```

#### Around

- `before()`
- `after()`
- `above()`
- `below()`

These methods take two optional arguments like fill methods, except the second one is spacing.

```swift
// view1.trailing == view2.leading - 10
view1.bb.before(view2, spacing: 10)
```

#### Offset

In iOS 10, use `-` operator to create an offset anchor between two axis anchors, then use `offset()` to create a constraint. It does not matter which view is used before `bb`.

```swift
// view2.left - view1.right == view3.left - view2.right
view1.bb.offset(view2.leftAnchor - view1.rightAnchor, view3.leftAnchor - view2.rightAnchor)
```

### Multiple Items

You can constrain on multiple items at once. There are two fundamental methods on which other methods are built.

```swift
// Constrain on each item.
// e.g., Set each item's width to 10.
[view1, view2, view3].bb.each {
$0.bb.width(10)
}

// Constrain between every two items.
// e.g., view1.left == view2.left, view2.left == view3.left
[view1, view2, view3].bb.between {
$0.bb.left($1)
}
```

Most basic methods on single item are available on multiple items.

```swift
// Anchor methods take no arguments and align all items' corresponding anchor.
// e.g., Align all views' left.
[view1, view2, view3].bb.left()

// For dimension anchors, you can set values for all items.
// e.g., Set all views' width to 10.
[view1, view2, view3].bb.width(10)
```

You can distribute items along an axis with fixed spacing or equal spacing.

- `distributeX()`
- `distributeY()`
- `distributeXEqualSpacing()`
- `distributeYEqualSpacing()`

```swift
// [view1]-10-[view2]-10-[view3]
[view1, view2, view3].bb.distributeX(spacing: 10)
```

All `distribute` methods come with an optional `inset` parameter, you can specify no insets, fixed insets or equal insets.

```swift
// |-[view1]-[view2]-[view3]-|, spacings are all equal.
[view1, view2, view3].bb.distributeXEqualSpacing(inset: .equal)
```

### Group

If you want to activate/deactivate a set of constraints in response to some events, you can use `group()` to collect constraints into an array.

```swift
let constraints: [NSLayoutConstraint] = group {
view1.bb.fill()
view2.bb.left().top().size(100)
view3.bb.fillBottom().height(100)
}
```

## Manual Layout

Why manual layout when there is Auto Layout? Well, Auto Layout is good, but it has some performance issues, that’s when you may want to switch to manual layout.

[Manual Layout Guide](https://github.com/wordlessj/Bamboo/blob/master/Documentation/Manual%20Layout%20Guide.md)

## Panda

[Panda](https://github.com/wordlessj/Panda) is a framework which creates view hierarchies declaratively, together with Bamboo, they make creating views in code incredibly simple and easy.

## License

Bamboo is released under the MIT license. See LICENSE for details.