Detailed intrinsiccontentsize and constraint priority/content hugging/content Compression resistance [turn]

Source: Internet
Author: User

Before we get to know intrinsiccontentsize, we need to understand 2 concepts:

    • What's AutoLayout doing?
    • What does the constraint precedence mean.

If you do not understand these two concepts, see Intinsic content size does not make any sense.
Note: Because the above concepts are for UIView or its subclasses (Uilabel,uiimageview, etc.). So the following uiview are used to refer to.

What AutoLayout is doing – a UIView wants to be displayed on the screen, with only 2 elements to be identified, one for position, and two for size. As long as 2 are determined, UIView can be displayed correctly, as for the content displayed, it is up to UIView to decide (drawrect).

Without AutoLayout, we need to specify the location and size of UIView by initWithFrame: (CGRect).

The process of using AutoLayout is to determine the position and size of the uiview through constraints.

Constraint precedence – Why do constraints require precedence? Because there are times when 2 constraints can be conflicting. For example: There is a uiview distance from the parent UIView is 0, this is 2 constraints, at this time to add a width constraint to this uiview, such as specifying a width of 100, then there will be a constraint conflict.

Because, these two kinds of constraints can not exist at the same time, only to meet one, then meet who? By default, the constraint precedence for UIView is 1000, which is the highest priority, indicating that the constraint must be met.

So this conflict cannot be allowed by iOS. At this point, you need to modify the priority level. Change the priority of any one of these constraints to a value less than 1000.

iOS can compare the precedence of two conflicting constraints, ignoring a constraint of low priority to achieve the correct layout.

Select the width constraint with the mouse, and then, in the menu on the right side of the screen, modify the priority, such as:

So there is no constraint conflict. Because if there are two constraint conflicts, the system automatically ignores the low priority constraint.

The example above is somewhat extreme, because the above two constraints are deterministic values and are absolute collisions. So if this is the case, it might be more appropriate to choose to delete a constraint.

The constraint precedence is more often used to solve the problem of a conflict between fuzzy constraints (as opposed to the above deterministic value constraints).
For example, there is a problem:

    • UIView1 has four constraints: the left and the top of the parent UIView are determined, and the width and height are also determined.
    • UIView2 under the UIView1, there are also 4 constraints: The above distance UIView1 determined, the left with UIView1 alignment, with UIView1 and other high and equal width.
      At this point these two uiview should look like this:

This is a very common application scenario, assuming I want to have an effect: I want the UIView2 width to be no more than 50. When the width of the UIView1 is less than 50, the widths of the two are equal, and when the UIView1 width is greater than 50, the UIVIEW2 is not affected by the UIView1 width.
So I added a constraint to UIView2: Width <=50. Here comes the conflict:
Because the width of the UIView1 is fixed, while the UIVIEW2 and UIView1 are wide. Then the width of the UIView2 is determined.

Obviously, there are two cases (depending on the width of the UIView1):

    • If the width of the UIView1 is greater than 50,uiview2, it must be greater than 50, which is in conflict with the constraint of the newly added limit width <=50.
    • Otherwise, it does not conflict.

Worse, in practice, the width of the UIView1 may not be a definite value. It may be affected by other view on the page, may also change at run time, and does not guarantee that its actual width must be less than 50. Therefore, once a constraint conflict occurs, it can have an indeterminate effect on the application: It may show confusion, or the program may crash.

So we should deal with this in order to get the right result:

    1. When the UIView1 width is less than or equal to 50, the constraint does not conflict, and the change priority is the same as the result.
    2. When the UIView1 width is greater than 50, the equal width constraint is ignored, that is, the equal-width constraint priority is reduced.

So we changed the priority of the equal-width constraint to 999. Above two are satisfied, problem solved.

When it comes to fuzzy constraints, content hugging/content Compression resistance is a fuzzy constraint with 2 uiview.
The condition of these two constraints is that UIView must specify the intrinsic Content Size.
Before you understand these two fuzzy constraints, you must understand what intrinsic Content size is.

Intrinsic contenet size–intrinsic Content size: intrinsic size. As the name implies, in AutoLayout, it acts as a property of UIView (not a grammatical attribute), meaning I know my size, and if you do not specify size for me, I will follow this size. For example: We all know that in the use of AutoLayout, Uilabel is not specified size, just specify the location, is because, as long as the text content, font and other information, it can calculate the size of its own.

These components, such as Uilabel,uiimageview,uibutton, and some of the system components that contain them, have the intrinsic Content Size property.
In other words, if you encounter these components, you only need to specify a location for them. Size just use intrinsic Content size on the line.

In the code, the above system controls override the-(cgsize) Intrinsiccontentsize: Method in UIView.
and call when you need to change this value: The Invalidateintrinsiccontentsize method, which notifies the system that the value has changed.

So when we're writing custom components that inherit from UIView and want to have intrinsic Content size, we can do this easily.

Intrinsic conflict – after a uiview has intrinsic Content size, you can specify only the location without specifying the size. And the above two constraints may be triggered. But again, for the above-mentioned UIView, it is sometimes problematic to specify the location without specifying the size. Let's use Uilabel for example (all components that support intrinsic Content Size have this problem). 2 Uilabel,uilabel1 (text content: UILabel1) and UILabel2 (text content: UILabel2), whose contents follow the layout described below:-2 Uilabel distance from the top bar is 50 points. -UILabel1 and left column distance is 10,uilabel2 to left UILabel1 10 points. Because both have the intrinsic property, you do not need to specify size. The location should also be clear.

Now the problem comes, and then add a constraint to UILabel2, the right side is 10 points from the right column.

Obviously, if you are laying out according to constraints, there is no way to satisfy 2 uilabel using intrinsic content size, at least one uilabel width is greater than intrinsic content size. In this case, we call it a "intrinsic conflict" between the 2 components.

There are 2 ways to solve the "intrinsic conflict" scenario:

    1. None of the two Uilabel use the intrinsic Content Size. Adds a new constraint for two uilabel to explicitly specify their size. such as: to 2 Uilabel to increase the width and height constraints or equal width and other high constraints and so on.
    1. You can have one of the Uilabel use the intrinsic Content Size, and the other label automatically takes up the remaining space. This is the time to use the content hugging and content Compression resistance! Specific practices are described below.

One sentence summarizes "intrinsic conflicts": two or more components that can use intrinsic content size because other constraints are added to the component, and intrinsic content size cannot be used at the same time.

Content hugging/content Compression resistance– First, both of these concepts are uiview properties. Suppose two components produce a "intrinsic conflict": 1. The Content hugging constraint (does not want to be a large constraint) means that if the component has a higher precedence than the other component of this property, then the component remains unchanged and the other can be stretched when it is needed. The properties are divided in 2 directions in both landscape and portrait orientation. 2. Content Compression resistance constraint (does not want to be a small constraint) means that if the component has a higher precedence than the other component, the component will remain unchanged and the other can be compressed when it needs to be compressed. The properties are divided in 2 directions in both landscape and portrait orientation. The meaning is obvious. In the example above Uilabel, it is clear that if one Uilabel uses intrinsic Content size, the other needs to be stretched. So we need to adjust the priority of the Content hugging constraint for the two uilabel. On this page you can adjust the priority level (pull to the bottom).

Different results can be obtained by adjusting the priority of the Content hugging of two Uilabel respectively:

Content Compression Resistance The situation is not much to say, the same principle.

Modify these two priority levels of UIView in your code
    setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];    [label setContentCompressionResistancePriority: UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
    • 1
    • 2

Priority is an enum:

typedef float Uilayoutpriority;static Const uilayoutpriority uilayoutpriorityrequired Ns_available_ios (6_0) =1000;  A required constraint. Donot exceed This.static const uilayoutpriority Uilayoutprioritydefaulthigh Ns_available_ios (6_0) =750; Thisis theWith which a button resists compressing its content.static const uilayoutpriority Uilayoutprioritydefaultlow NS_AVAILABLE _ios (6_0) =250; Thisis the which a button hugs its contents horizontally.static const uilayoutpriority Uilayoutpriorityfitti Ngsizelevel Ns_available_ios (6_0) = 50;//when you send-[UIView Systemlayoutsizefittingsize:], the size fitting most closely to the target size (the argument) is computed. Uilayoutpriorityfittingsizelevel is the priority level with Which the view wants to conform to the target size in that computation. Itis generally not appropriate to Make a constraint at exactly this priority. You want to is higher or lower.      
    • 1
    • 2
    • 3
    • 4
    • 5

Axis indicates landscape and portrait:

typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {    UILayoutConstraintAxisHorizontal = 0,    UILayoutConstraintAxisVertical = 1};
    • 1
    • 2
    • 3
    • 4
To create a custom component with the intrinsic Content Size feature

The code and comments are as follows:

//IntrinsicView.h#import <UIKit/UIKit.h>@interface IntrinsicView : UIView@property (nonatomic) CGSize extendSize;@end
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
intrinsicview.m#import"IntrinsicView.h"StaticBOOL Closeintrinsic =FalseTest the effect of closing intrinsic@implementationintrinsicview-(instancetype) init{Self = [Super Init];if (Self) {Not compatible with legacy Autoreizingmask, use only AutoLayoutIf yes, the frame and bounds properties of the view are automatically converted to constraints in AutoLayout.Self. translatesautoresizingmaskintoconstraints =NO; }ReturnSelf;}When the user sets Extendsize, the system intrinsiccontentsize changes. -(void) Setextendsize: (cgsize) extendsize{_extendSize = Extendsize; //if you do not add this sentence, after the view display (such as delay a few seconds), then set the extendsize will not be effective. //in this case, the Testinvalidateintrinsic method does not produce the desired effect. [self invalidateintrinsiccontentsize];} //modifies the size of the view's intrinsiccontentsize by overriding the intrinsic function-(CGSize ) intrinsiccontentsize{if (closeintrinsic) {return Cgsizemake (Uiviewnointrinsicmetric, uiviewnointrinsicmetric); } else {return Cgsizemake (_extendsize .width, _extendsize.height);}}  @end             
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
Test code#import"ViewController.h"#import"NewViewCtlViewController.h"#import"IntrinsicView.h"@interfaceViewcontroller ()@end@implementationviewcontroller-(void) viewdidload{[Super Viewdidload]; [Self Testintrinsicview];} +-(void) testintrinsicview{Intrinsicview *intrinsicview1 = [[Intrinsicview alloc] init]; intrinsicView1. extendsize = Cgsizemake (100,100); IntrinsicView1. backgroundcolor = [Uicolor Greencolor]; [Self. View Addsubview:intrinsicview1]; [Self. View addconstraints:@[100 points from Superview [Nslayoutconstraint constraintwithitem:intrinsicview1 attribute:nslayoutattributetop RelatedBy : Nslayoutrelationequal Toitem:Self. View Attribute:nslayoutattributetop Multiplier:1 constant:100],Distance Superview left 10 points [Nslayoutconstraint constraintwithitem:intrinsicview1 attribute:nslayoutattributeleft RelatedBy : Nslayoutrelationequal Toitem:Self. View Attribute:nslayoutattributeleft Multiplier:1 constant:10], []]; Intrinsicview *intrinsicview2 = [[Intrinsicview alloc] init]; IntrinsicView2. extendsize = Cgsizemake (100,30); IntrinsicView2. backgroundcolor = [Uicolor Redcolor]; [Self. View Addsubview:intrinsicview2]; [Self. View addconstraints:@[220 points from Superview [Nslayoutconstraint constraintwithitem:intrinsicview2 attribute:nslayoutattributetop RelatedBy : Nslayoutrelationequal Toitem:Self. View Attribute:nslayoutattributetop Multiplier:1 constant:220], // From Superview to the left 10 points [Nslayoutconstraint constraintwithitem:intrinsicview2 attribute:nslayoutattributeleft relatedBy: Nslayoutrelationequal toitem:self.view attribute: Nslayoutattributeleft multiplier:1 constant:10], []]; [self performselector: @selector (testinvalidateintrinsic:) Withobject:intrinsicview2 afterdelay:2];} -(void) Testinvalidateintrinsic: (Intrinsicview *) view{view .extendsize = Cgsizemake (100, 80) ;}  @end             
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

The code works as follows:

Detailed intrinsiccontentsize and constraint priority/content hugging/content Compression resistance [turn]

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.