Skip to content

Latest commit

 

History

History
525 lines (417 loc) · 18.6 KB

DEMOS.md

File metadata and controls

525 lines (417 loc) · 18.6 KB

Basic

Set*

set* operations directly put frame values

blueView.lx.set(x: 10, y: 10)
    .set(width: 100, height: 100)

greenView.lx.set(x: 120, y: 20, width: 50, height: 190)

redView.lx.set(x: 5)
    .set(y: 120)
    .set(width: 45)
    .set(height: 100)

Set* Set*

Center

hcenter (horizontally), vcenter (vertically) and center (both) operations allows to center view in superview. Insets can be used to adjust center point (see green view, 100 pt from bottom). Size of view usually should be set with previous operations

blueView.lx.set(y: 5)
    .set(width: 100, height: 100)
    .hcenter()

greenView.lx.set(x: 5)
    .set(width: 50, height: 120)
    .vcenter(topInset: 0, bottomInset: 100)

redView.lx.set(width: 45, height: 100)
    .center()

Center Center

Fill

hfill (horizontally), vfill (vertically) and fill (both) operations make view to fill its superview. Insets can be used to control how much space to be left unfilled from the superview edges

redView.lx.fill(inset: 5)

blueView.lx.set(y: 20)
    .set(height: 50)
    .hfill(inset: 10)

greenView.lx.set(x: 25)
    .set(width: 50)
    .vfill(topInset: 100, bottomInset: 15)

Fill Fill

Align

align* operations allow to put view relatively to edges of superview. Inset value can be used to set distance to edge. Size of view usually should be set with previous operations.

blueView.lx.set(width: 100, height: 100)
    .alignLeft(5)
    .alignTop(5)

greenView.lx.set(width: 50, height: 120)
    .alignLeft(10)
    .alignBottom(15)

redView.lx.set(width: 45, height: 100)
    .alignRight(25)
    .alignTop(25)

Align Align

SizeToFit

.value

sizeToFit operation fits view in defined box using -sizeThatFits: method. Box (width and height) can be defined using different options. .value option sets exact value for box. Result size will be equal or less than it.

icon.lx.sizeToFit(width: .value(100), height: .value(100))
    .alignTop(10)
    .hcenter()

label.lx.sizeToFit(width: .value(100), height: .value(100))
    .center()

title.lx.sizeToFit(width: .value(100), height: .value(100))
    .alignBottom(10)
    .hcenter()

.value .value

.max

.max option sets infinite value for fitting box. Result size will be most comfortable for view to display content. WARNING: multiline labels are comfortable with single line, don't use .max for width

icon.lx.sizeToFitMax()  //same as view.lx.sizeToFit(width: .Max, height: .Max)
    .alignTop(10)
    .hcenter()

label.lx.sizeToFit(width: .max, height: .max)
    .center()

title.lx.sizeToFit(width: .max, height: .max)
    .alignBottom(10)
    .hcenter()

.max .max

.current

.current option sets value for box with current frame's width or height.

icon.lx.set(size: CGSize(width: 200, height: 200))
    .sizeToFit(width: .current, height: .current)
    .alignTop(10)
    .hcenter()

label.lx.hfill(leftInset: 20, rightInset: 20)
    .sizeToFit() //same as view.lx.sizeToFit(width: .Current, height: .Current)
    .center()

title.lx.hfill(leftInset: 20, rightInset: 20)
    .sizeToFit(width: .current, height: .current)
    .alignBottom(10)
    .hcenter()

.current .current

.keepCurrent

.keepCurrent options sets value for box with current frame's width or height, but result size will be still equal to those original frame values. This is usefull to layout multiline labels. First you need to set somehow label width, and then call something like label.lx.sizeToFit(width: .keepCurrent, height: .max).

icon.lx.set(size: CGSize(width: 200, height: 200))
    .sizeToFit(width: .keepCurrent, height: .max)
    .alignTop(10)
    .hcenter()

label.lx.hfill(leftInset: 20, rightInset: 20)
    .sizeToFit(width: .keepCurrent, height: .max)
    .center()

title.lx.hfill(leftInset: 20, rightInset: 20)
    .sizeToFit(width: .keepCurrent, height: .max)
    .alignBottom(10)
    .hcenter()

.keepCurrent .keepCurrent

min/max constraints

sizeToFit operation also can have min, max or both constraints to limit resulted width/height.

label.lx.sizeToFitMax(widthConstraint: .max(100), heightConstraint: .min(300))
    .center()

min/max constraints min/max constraints

Follow

Corners

Follow operation makes one view's anchor to be the same with others view anchor (+/- inset). Anchors can be horizontal or vertical, and can be followed only with the anchors of same type. Anchor can follow anchors of other views at the same level of hierarchy, or parent anchors

blueView.lx.set(x: 10, y: 10)
    .set(width: 100, height: 100)

greenView.lx.set(width: 50, height: 190)
greenView.lx.leftAnchor.follow(blueView.lx.rightAnchor)
greenView.lx.topAnchor.follow(blueView.lx.bottomAnchor)

redView.lx.set(width: 30, height: 30)
redView.lx.leftAnchor.follow(blueView.lx.leftAnchor)
redView.lx.bottomAnchor.follow(greenView.lx.bottomAnchor)

heartView.lx.topAnchor.follow(greenView.lx.bottomAnchor)
heartView.lx.rightAnchor.follow(greenView.lx.rightAnchor)

Corners Corners

Center

There are not only edge anchors, but also center anchors

blueView.lx.set(x: 10, y: 10)
    .set(width: 200)
    .vfill(inset: 20)

greenView.lx.set(width: 50, height: 190)
greenView.lx.leftAnchor.follow(blueView.lx.rightAnchor)
greenView.lx.vcenterAnchor.follow(blueView.lx.vcenterAnchor)

redView.lx.set(width: 30, height: 30)
redView.lx.hcenterAnchor.follow(greenView.lx.hcenterAnchor)
redView.lx.vcenterAnchor.follow(greenView.lx.vcenterAnchor)

Center Center

Size

There are also size anchors

blueView.lx.set(x: 10)
    .set(width: 50)
    .vfill(inset: 100)

greenView.lx.heightAnchor.follow(blueView.lx.widthAnchor)
greenView.lx.widthAnchor.follow(blueView.lx.heightAnchor)
greenView.lx.leftAnchor.follow(blueView.lx.rightAnchor)
greenView.lx.topAnchor.follow(blueView.lx.bottomAnchor)

Size Size

Baseline

firstBaselineAnchor/lastBaselineAnchor anchors are special. Only Baselinable views have it. For the moment only UILabel is conforming this protocol

label.lx.hfill(inset: 20)
    .sizeToFit(width: .keepCurrent, height: .max)
    .center()

blueView.lx.set(height: 30)
    .hfill(inset: 20)

greenView.lx.set(height: 30)
    .hfill(inset: 20)

blueView.lx.bottomAnchor.follow(label.lx.firstBaselineAnchor)
greenView.lx.topAnchor.follow(label.lx.lastBaselineAnchor)

Baseline Baseline

Put

Fix

hput and vput operations successively layout views in superview in horizontal or vertical direction using intentions. Fix intention means that view size will take exact value, either directly defined or current one

self.lx.hput(
    Fix(50),
    Fix(blueView, 120),
    Fix(greenView, 40),
    Fix(10),
    Fix(redView, 60)
)
self.lx.vput(
    Fix(50),
    Fix(blueView, 120),
    Fix(greenView, 40),
    Fix(10),
    Fix(redView, 60)
)

Fix Fix

Flex

hput and vput operations successively layout views in superview in horizontal or vertical direction using intentions. Flex intention means that view size will take value based weight of flex value. Flex operates only with free space left after Fix intentions

self.lx.hput(
    Flex(blueView, 0.5),
    Flex(greenView, 1.0),
    Flex(redView, 0.5)
)
self.lx.vput(
    Flex(),
    Flex(blueView),
    Flex(greenView),
    Flex(redView),
    Flex()
)

Flex Flex

Fix+Flex

Biggest power comes when we combine Fix and Flex intentions

self.lx.hput(
    Fix(20),
    Fix(blueView, 100),
    Fix(20),
    Flex(greenView),
    Fix(20),
    Fix(redView, 100),
    Fix(20)
)
blueView.lx.vfill(inset: 40)
greenView.lx.vfill(inset: 40)
redView.lx.vfill(inset: 40)

Fix+Flex Fix+Flex

Fix+Flex center many views

It is really to easy to center bunch of views all together

self.lx.hput(
    Flex(),
    Fix(blueView, 70),
    Fix(10),
    Fix(greenView, 40),
    Fix(20),
    Fix(redView, 20),
    Flex()
)
blueView.lx.vfill(inset: 40)
greenView.lx.vfill(inset: 40)
redView.lx.vfill(inset: 40)

Fix+Flex center many views Fix+Flex center many views

Multi

Single intention can be defined for several views, all calculations are doing for first one, and others use this result as is

self.lx.hput(
    Flex(),
    Fix(blueView, 70),
    Fix(10),
    Fix(greenView, 40),
    Fix(20),
    Fix(redView, 20),
    Flex()
)
self.lx.vput(
    Fix(40),
    Flex([blueView, greenView, redView]),
    Fix(40)
)

Multi Multi

Fix+Flex grid

Elegant way to layout views in grid using just one hput and one vput

func putCols() {
    var r = [PutIntention]()
    for i in 0..<8 {
        
        var row = [Layoutable]()
        for j in 0..<8 {
            row.append(views[i*8 + j])
        }
        r.append(Flex(row))
    }
    self.lx.hput(r)
}

func putRows() {
    var r = [PutIntention]()
    
    for i in 0..<8 {
        
        var col = [Layoutable]()
        for j in 0..<8 {
            col.append(views[i + j*8])
        }
        r.append(Flex(col))
    }
    self.lx.vput(r)
}


putCols()
putRows()

Fix+Flex grid Fix+Flex grid

Put labels

hfillvfit is used to fill width and size to fit height for both labels. vput is used to center group of labels

titleLabel.lx.hfillvfit(inset: 20)
detailsLabel.lx.hfillvfit(inset: 20)
self.lx.vput(
    Flex(),
    Fix(titleLabel),
    Fix(20),
    Fix(detailsLabel),
    Flex()
)

Put labels Put labels

Digimax

AL Battle

let topSize = CGSize(width: 60, height: 60)
let topPadding: CGFloat = 10

let topLeftRightPadding: CGFloat = 20

topView1.lx.set(size: topSize)
    .alignTop(topPadding)
topView2.lx.set(size: topSize)
    .alignTop(topPadding)
topView3.lx.set(size: topSize)
    .alignTop(topPadding)

lx.hput(
    Fix(topLeftRightPadding),
    Fix(topView1),
    Flex(),
    Fix(topView2),
    Flex(),
    Fix(topView3),
    Fix(topLeftRightPadding)
)

let cardSize = bounds.width < bounds.height ? CGSize(width: 80, height: 120) : CGSize(width: 60, height: 90)
let cardLeftRightPadding: CGFloat = 25

cardView1.lx.set(size: cardSize)
cardView2.lx.set(size: cardSize)
cardView3.lx.set(size: cardSize)
cardView4.lx.set(size: cardSize)


if bounds.width < bounds.height {
    cardView1.lx.vcenter()
    cardView2.lx.vcenter()
    
    lx.hput(
        Fix(cardLeftRightPadding),
        Fix(cardView1),
        Flex(),
        Fix(cardView2),
        Fix(cardLeftRightPadding)
    )
    
    cardView3.lx.hcenter()
    cardView4.lx.hcenter()
    
    lx.vput(
        Flex(),
        Fix(cardView3),
        Fix(60),
        Fix(cardView4),
        Flex()
    )
} else {
    cardView1.lx.vcenter()
    cardView2.lx.vcenter()
    cardView3.lx.vcenter()
    cardView4.lx.vcenter()
    
    lx.hput(
        Fix(cardLeftRightPadding),
        Fix(cardView1),
        Flex(),
        Fix(cardView3),
        Flex(),
        Fix(cardView4),
        Flex(),
        Fix(cardView2),
        Fix(cardLeftRightPadding)
    )
}


bottomView.lx.set(height: 40)
    .hfill(inset: 100)
    .alignBottom(15)

Digimax Digimax

Wrap

Derivative from put operation. Accepts only Fix. Modifies parent frame to wrap childs. Method to perform selfsizing.

let maxLabelsWidth: CGFloat = 250

title.lx.sizeToFit(width: .value(maxLabelsWidth), height: .max)
details.lx.sizeToFit(width: .value(maxLabelsWidth), height: .max)

container.lx.hwrap(
    Fix(10),
    Fix([title, details], .max), //fixing for view with greatest width
    Fix(10)
)

container.lx.vwrap(
    Fix(10),
    Fix(title),
    Fix(10),
    Fix(details),
    Fix(10)
)

container.lx.center()

Wrap Wrap

Viewport

Demo

Viewport can be defined using anchors of any childview, or nil anchor if using superview edges

blueView.lx.hfill(inset: 20)

self.lx.vput(
    Fix(20),
    Fix(blueView, 20),
    Fix(20),
    Flex(greenView),
    Fix(20)
)

greenView.lx.alignLeft(20)
    .set(width: 20)

self.lx.inViewport(topAnchor: blueView.lx.bottomAnchor.insettedBy(5), leftAnchor: greenView.lx.rightAnchor.insettedBy(5), bottomAnchor: self.lx.bottomAnchor.insettedBy(-5), rightAnchor: self.lx.rightAnchor.insettedBy(-5)) {
    redView.lx.fill()
    heartView.lx.bottomAnchor.follow(self.lx.bottomAnchor)
    heartView.lx.rightAnchor.follow(self.lx.rightAnchor)
}

Demo Demo