IOS Automatic Layout and elastic box

Source: Internet
Author: User

IOS Automatic Layout and elastic box

When my colleague asked me this question, I came up with the word "elastic box ".

Problem:

There is a Cell with four controls arranged side by side. The layout is shown in:


Hypothesis: <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Release/YvP6437bIus151/release/2Lz + release/YvP6/release/YvP6jqMLMyau/2Lz + release + PHA + export/2Lz + release/tL + release/2Lz + release/YvP61xL/release/2Lz + 1PLX1LavsrzC + sqjz8K1xL/release/rLYxuTW0NK7uPa/2Lz + release + pgltzybzcm9 "http://www.2cto.com/uploadfile/2015/1213/20151213030114863.jpg" alt = "\"/>

2. Similarly, the effects of hiding any two and three controls are shown in:


If HTML5 is used, it would be more appropriate to solve this problem using an elastic box. But the "elastic box" is newly added in CSS 3.0. iOS does not support elastic boxes. We can only solve this problem by ourselves.

Fortunately, iOS has an automatic layout, so we can use the automatic layout to solve this problem (of course, a little code is needed ).

I. UI design

Open the storyboard and drag four uiviews and three buttons to viewcontrollerz, as shown in:


What are these four uiviews and three UIButton respectively? I believe you can see at a glance. The button does not matter. Check the four views first.

The Automatic Layout constraint of the blue view is as follows:

Top: 24, leading: 16, height: 24, trailing: 10

The layout constraints of black, red, and green views are the same:

Width: 37, height: 24, top: 24, trailing: 10

The four uiviews are connected to the following IBOutlet:

Blue v1

Black v2

Red v3

Green v4

The click events of the three buttons are connected to the three ibactions respectively:

@ IBActionfunc hideGray (sender: AnyObject ){

Hide (v2)

}

@ IBAction func hideRed (sender: AnyObject ){

Hide (v3)

}

@ IBAction func hideGreen (sender: AnyObject ){

Hide (v4)

}

The hide () method will be introduced soon.

I. Elastic Box Design

When a view is hidden in black, red, or green (that is, the hidden attribute is true), the space occupied by the view is automatically released. We need to change the layout constraints According to the hidden attribute.

We can see from the above that their automatic layout constraints are mainly as follows:

Width, height, leading, and trailing.

These la s are closely related to the space occupied by the View. We don't need to worry about height, because when width = 0, the space occupied by them has been released, and the value of height is irrelevant.

That is to say, when the view is hidden, when the width, leading, and trailing of the view are both 0, the space occupied by the view is released.

Therefore, we need to get the width, leading, and trailing constraints at runtime and modify them according to the hidden attribute. Can we get the specified View constraint at runtime? The answer is yes.

We know that UIView has a constraints () method, and returns an NSLayoutConstraints array, including all its width and height, which belong to the view constrains, while leading and trailing belong to superview. We can traverse these two arrays to find the constraint we want.

We use a UIView extension to achieve this goal:

Extension UIView {

Func widthConstraint ()-> NSLayoutConstraint? {

For constraint in self. constraints (){

Let firstItem = constraint. firstItem? UIView

If firstItem = self & constraint. firstattriitem = NSLayoutAttribute. Width {

Println ("I gotit: \ (constraint )")

Return constraint? NSLayoutConstraint

}

}

Return nil

}

Func leadingConstraint ()-> NSLayoutConstraint? {

If self. superview = nil {

Return nil

}

For constraint in self. superview !. Constraints () {// This constraint is in superview

Let firstItem = constraint. firstItem? UIView

Let secondItem = constraint. secondItem? UIView

If firstItem = self & constraint. firstattriitem = NSLayoutAttribute. Leading {

Println ("I gotit: \ (constraint )")

Return constraint? NSLayoutConstraint

}

}

Return nil

}

Func trailingConstraint ()-> NSLayoutConstraint? {

If self. superview = nil {

Return nil

}

For constraint in self. superview !. Constraints () {// This constraint is in superview

Let firstItem = constraint. firstItem? UIView

If firstItem = self & constraint. firstattriitem = NSLayoutAttribute. Trailing {

Println ("I gotit: \ (constraint )")

Return constraint? NSLayoutConstraint

}

}

Return nil

}

}

Then we design an elastic box to manage the three views. The main purpose of the elastic box class is to save the values of the three constraints of these views to one place (for example, in a dictionary), and then when the hidden attribute of a View is set to false, restores the constraints to the original values and displays them.

Class FlexibleBox: NSObject {

StructViewSpace: Printable {

Var widthConstant: CGFloat = 0

Var leadConstant: CGFloat = 0

Var trailConstant: CGFloat = 0

Var description: String {

Return "width-\ (widthConstant) \ nleading-

\ (LeadConstant) \ ntrailing-\ (trailConstant )"

}

}

Var cachedConstraints = [UIView: ViewSpace] ()

Func addViews (views: [UIView]) {

For view in views {

AddView (view)

}

}

Func addView (v: UIView ){

Var space = ViewSpace ()

If let constraint = v. trailingConstraint (){

Space. trailConstant = constraint. constant

}

If let constraint = v. leadingConstraint (){

Space. leadConstant = constraint. constant

}

If let constraint = v. widthConstraint (){

Space. widthConstant = constraint. constant

}

CachedConstraints [v] = space

Println ("\ (space )")

}

Func freeViewSpace (v: UIView ){

V. widthConstraint ()?. Constant = 0

V. leadingConstraint ()?. Constant = 0

V. trailingConstraint ()?. Constant = 0

}

Func resumeViewSpace (v: UIView ){

Let space = cachedConstraints [v]? ViewSpace ()

V. trailingConstraint ()?. Constant = space. trailConstant

V. leadingConstraint ()?. Constant = space. leadConstant

V. widthConstraint ()?. Constant = space. widthConstant

}

Deinit {

CachedConstraints. removeAll (keepCapacity: false)

}

}

Ii. Use elastic box

Declare an elastic box in View Controller:

Let flexBox = FlexibleBox ()

Then in the viewDidLoad method:

FlexBox. addViews ([v2, v3, v4])

Then, when you click the button, call the following method to hide (or unhide) A View:

Func toggleViewHiddenStatus (v: UIView ){

If v. hidden = false {

FlexBox. freeViewSpace (v)

} Else {

FlexBox. resumeViewSpace (v)

}

V. hidden =! V. hidden

Self. view. setNeedsLayout ()

}

The last sentence self. view. setNeedsLayout () will cause all automatic layout constraints to be recalculated.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.