Original: http://adad184.com/2014/09/28/use-masonry-to-quick-solve-autolayout/?sukey= Fc78a68049a14bb23f9904ceb1cee7693d4a59492bdc4ab7adac872bc75badc34b073acbbde493ba3e6a69360d89a4c4
Objective
1 |
MagicNumber, Autoresizingmask, AutoLayout |
These are the three times that the plain handwriting code has experienced about page layouts
In the IPHONE1-IPHONE3GS era the size of window is fixed to (320,480) we just need to calculate the relative position simply.
In the iphone4-iphone4s era, Apple launched the Retina screen but gave yards farmers a very large benefit: the size of window does not change
The size of the window changed in the iphone5-iphone5s era (320,568) then autoresizingMask
it came in handy (why not autolayout at this time?) because you have to support iOS5) simple adaptation can be
In the iphone6+ era, window width also changed (relative to the 5 and 5s screen ratio has not changed) finally it is time to abandon the autoresizingMask
switch to AutoLayout (do not support the ios5 of the diversity of screen adaptation is autoresizingMask
also outdated)
So how to get started quickly autolayout? To be honest, when IOS6 launched the new AutoLayout features I took a look at the official documents and the demo and threw it aside because it was too much 繁琐和啰嗦
(a friend of the experience would agree)
Until after Iphone6 was released, I knew it was imperative to use AutoLayout. This reminds me of a third-party library I've seen before on GitHub masonry I'll autolayout after a few hours of research use ( 重点是我并没有学习任何的官方文档或者其他的关于autolayout的知识
) That's why I wrote this article to recommend it.
Introduced
Masonry source
Masonry is a lightweight layout framework that has its own description syntax with a more elegant chained syntax encapsulation automatic layout is concise and highly readable而且同时支持 iOS 和 Max OS X
Let's take a look at the official sample code to get to know masonry.
1 2 3 |
[View1 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.edges.equalTo (Superview). With.insets (padding); }]; |
See the sentence inside the block:make edges equalTo superview with insets
Through the chain of natural language to the View1 to AutoLayout good is not easy to understand?
Use
Take a look at what properties masonry supports
1 2 3 4 5 6 7 8 9 10 11 |
@property (Nonatomic, Strong, ReadOnly) Masconstraint *left; @property (Nonatomic, Strong, ReadOnly) Masconstraint *top; @property (Nonatomic, Strong, ReadOnly) Masconstraint *right; @property (Nonatomic, Strong, ReadOnly) Masconstraint *bottom; @property (Nonatomic, Strong, ReadOnly) Masconstraint *leading; @property (Nonatomic, Strong, ReadOnly) Masconstraint *trailing; @property (Nonatomic, Strong, ReadOnly) Masconstraint *width; @property (Nonatomic, Strong, ReadOnly) Masconstraint *height; @property (Nonatomic, Strong, ReadOnly) Masconstraint *centerx; @property (Nonatomic, Strong, ReadOnly) Masconstraint *centery; @property (Nonatomic, Strong, ReadOnly) Masconstraint *baseline; |
The comparison of these attributes with Nslayoutattrubute is as follows
Masonry |
Nsautolayout |
Description |
left |
nslayoutattributeleft |
lh |
top |
Nslayoutatt Ributetop |
Upper |
right |
nslayoutattributeright |
RH |
Bottom |
Nslayoutattributebottom |
Lower side |
leading |
nslayoutattributeleading |
header |
trailing |
nslayoutattributetrailing |
tail |
width |
nslayoutattributewidth |
width |
height |
nslayoutattributeheight |
High |
CenterX |
nslayoutattributecenterx |
horizontal midpoint |
centery |
nslayoutattributecentery |
portrait midpoint |
Baseline |
nslayoutattributebaseline |
text baselines |
Where leading and left trailing are normally equivalent to right under normal circumstances, but when some layouts are in the correct-to-ieft (such as Arabic? No similar experience) will be reversed in other words is basically can not use left and right.
After the release of iOS8 has added a bunch of strange attributes (interested friends can go to look) masonry temporarily not supported (but you have to support IOS6,IOS7 there is no need to take care of so much)
Let's go to the point below (for the convenience of our test Superview is a size (300,300) of the UIView)
Here are some simple examples of how to 轻松愉快
use masonry:
1. [Base] Center displays a view
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-(void) viewdidload { [Super Viewdidload]; Do any additional setup after loading the view. UIView *SV = [UIView new]; [SV Showplaceholder]; Sv.backgroundcolor = [Uicolor blackcolor]; [Self.view ADDSUBVIEW:SV]; [SV mas_makeconstraints:^ (Masconstraintmaker *make) { Make.center.equalTo (Self.view); Make.size.mas_equalTo (Cgsizemake (300, 300)); }]; } |
Code effects
Using the Mmplaceholder I wrote between us, I can see that Superview has been centered and set to the right size as we expected.
So let's take a look at these lines of code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
From then on, we can basically abandon cgrectmake. UIView *SV = [UIView new];
You must first add the view to the Superview before you do the AutoLayout or you will get an error. [Self.view ADDSUBVIEW:SV];
Mas_makeconstraints is Masonry's AutoLayout add function to add the required constraints to the block row [SV mas_makeconstraints:^ (Masconstraintmaker *make) {
Center the SV (it's easy to understand?) Make.center.equalTo (Self.view); Set size to (300,300) Make.size.mas_equalTo (Cgsizemake (300, 300)); }];
|
Here are two questions to break down.
- First, there are three functions to add autolayout constraints in masonry
1 2 3 4 5 6 7 8 9 10 11 12 |
-(Nsarray *) Mas_makeconstraints: (void (^) (Masconstraintmaker *make)) block; -(Nsarray *) Mas_updateconstraints: (void (^) (Masconstraintmaker *make)) block; -(Nsarray *) Mas_remakeconstraints: (void (^) (Masconstraintmaker *make)) block;
/* Mas_updateconstraints for the above situation will update the constraints appearing in the block will not result in the occurrence of two identical constraints Mas_remakeconstraints clears all previous constraints to keep only the most recent constraints Three kinds of functions can be used to deal with all kinds of situations. */
|
- Secondly, what is the difference between Equalto and Mas_equalto? In fact, Mas_equalto is a macro
1 2 3 4 5 |
#define MAS_EQUALTO (...) Equalto (Masboxvalue (__va_args__)) #define MAS_GREATERTHANOREQUALTO (...) Greaterthanorequalto (Masboxvalue (__va_args__)) #define MAS_LESSTHANOREQUALTO (...) Lessthanorequalto (Masboxvalue (__va_args__))
#define Mas_offset (...) Valueoffset (Masboxvalue (__va_args__)) |
You can see that the mas_equalto is just a box operation (boxing) Masboxvalue the definition of its parameters specifically, you can see that the source code is too long to be posted.
Supported types are supported except for those numeric types CGPoint
CGSize
supported by NSNumberUIEdgeInsets
We'll go on with these questions. PS: The SV just defined will be the superview of all our next sample
2. [Beginner] Make a view slightly smaller than its superview (margin is 10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
UIView *SV1 = [UIView new]; [Sv1 Showplaceholder]; Sv1.backgroundcolor = [Uicolor Redcolor]; [SV Addsubview:sv1]; [Sv1 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.edges.equalTo (SV). With.insets (Uiedgeinsetsmake (10, 10, 10, 10)); /* Equivalent to Make.top.equalTo (SV). With.offset (10); Make.left.equalTo (SV). With.offset (10); Make.bottom.equalTo (SV). With.offset (-10); Make.right.equalTo (SV). With.offset (-10); */ /* is also equivalent to Make.top.left.bottom.and.right.equalTo (SV). With.insets (Uiedgeinsetsmake (10, 10, 10, 10)); */ }]; |
Code effects
Can see edges is actually top,left,bottom,right a simplified separate write can also be a word more convenient
So why is the offset in bottom and right negative? Because this is the absolute numerical calculation, the bottom needs to be less than the bottom height of the SV, so 10 is the same for right.
The interesting thing here is and
with
that these two functions do nothing.
1 2 3 4 5 6 7 |
-(Masconstraint *) with { return self; }
-(Masconstraint *) and { return self; } |
But in this chain of grammar is very clever and easy to understand the author's mind (although I will now basically omitted)
3. [Beginner] Let the two height 150 view vertical Center and equal width and equal interval arrangement interval is 10 (automatically calculate its width)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int padding1 = 10;
[Sv2 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.centerY.mas_equalTo (Sv.mas_centery); Make.left.equalTo (Sv.mas_left). With.offset (PADDING1); Make.right.equalTo (Sv3.mas_left). With.offset (-PADDING1); Make.height.mas_equalTo (@150); Make.width.equalTo (SV3); }];
[Sv3 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.centerY.mas_equalTo (Sv.mas_centery); Make.left.equalTo (sv2.mas_right). With.offset (PADDING1); Make.right.equalTo (sv.mas_right). With.offset (-PADDING1); Make.height.mas_equalTo (@150); Make.width.equalTo (SV2); }]; |
Code effects
Here we set the constraint between the two sub-view to see that their width is automatically calculated under the constraint.
4. [Intermediate] Arrange some view in Uiscrollview order and automatically calculate contentsize
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 46 47 48 |
Uiscrollview *scrollview = [Uiscrollview new]; Scrollview.backgroundcolor = [Uicolor Whitecolor]; [SV Addsubview:scrollview]; [ScrollView mas_makeconstraints:^ (Masconstraintmaker *make) { Make.edges.equalTo (SV). With.insets (Uiedgeinsetsmake (5,5,5,5)); }];
UIView *container = [UIView new]; [ScrollView Addsubview:container]; [Container mas_makeconstraints:^ (Masconstraintmaker *make) { Make.edges.equalTo (ScrollView); Make.width.equalTo (ScrollView); }];
int count = 10;
UIView *lastview = nil;
for (int i = 1; I <= count; ++i) { UIView *SUBV = [UIView new]; [Container ADDSUBVIEW:SUBV]; Subv.backgroundcolor = [Uicolor Colorwithhue: (arc4random ()% 256/256.0) Saturation: (Arc4random ()% 128/256.0) + 0.5 Brightness: (arc4random ()% 128/256.0) + 0.5 ALPHA:1]; [Subv mas_makeconstraints:^ (Masconstraintmaker *make) { Make.left.and.right.equalTo (container); Make.height.mas_equalTo (@ (20*i)); if (Lastview) { Make.top.mas_equalTo (Lastview.mas_bottom); } Else { Make.top.mas_equalTo (Container.mas_top); } }]; Lastview = SUBV; }
[Container mas_makeconstraints:^ (Masconstraintmaker *make) { Make.bottom.equalTo (Lastview.mas_bottom); }]; |
Head effect
Tail effect
From ScrollView's scrollindicator, we can see that the interior of ScrollView has been lined up as we'd like.
The key here is that container this view plays an intermediary role that automatically calculates the Uiscrollview contentsize
5. [Advanced] Horizontal or vertical gap arrangement a set of view
Unfortunately AutoLayout does not directly provide the method of equal clearance arrangement (there is no corresponding case in the official demo of Masonry) but reference case 3 we can do this with a little trick, so I wrote a category.
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
@implementation UIView (MASONRY_LJC)
-(void) Distributespacinghorizontallywith: (nsarray*) views { Nsmutablearray *spaces = [Nsmutablearray arraywithcapacity:views.count+1]; for (int i = 0; i < views.count+1; ++i) { UIView *v = [UIView new]; [Spaces ADDOBJECT:V]; [Self addsubview:v]; [v mas_makeconstraints:^ (Masconstraintmaker *make) { Make.width.equalTo (V.mas_height); }]; } UIView *v0 = spaces[0]; [V0 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.left.equalTo (Self.mas_left); Make.centerY.equalTo (((uiview*) views[0]). Mas_centery); }]; UIView *lastspace = V0; for (int i = 0; i < Views.count; ++i) { UIView *obj = views[i]; UIView *space = spaces[i+1]; [obj mas_makeconstraints:^ (masconstraintmaker *make) { Make.left.equalTo (Lastspace.mas_right); }]; [Space mas_makeconstraints:^ (Masconstraintmaker *make) { Make.left.equalTo (Obj.mas_right); Make.centerY.equalTo (Obj.mas_centery); Make.width.equalTo (V0); }]; Lastspace = space; } [Lastspace mas_makeconstraints:^ (Masconstraintmaker *make) { Make.right.equalTo (Self.mas_right); }]; }
-(void) Distributespacingverticallywith: (nsarray*) views { Nsmutablearray *spaces = [Nsmutablearray arraywithcapacity:views.count+1]; for (int i = 0; i < views.count+1; ++i) { UIView *v = [UIView new]; [Spaces ADDOBJECT:V]; [Self addsubview:v]; [v mas_makeconstraints:^ (Masconstraintmaker *make) { Make.width.equalTo (V.mas_height); }]; } UIView *v0 = spaces[0]; [V0 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.top.equalTo (Self.mas_top); Make.centerX.equalTo (((uiview*) views[0]). Mas_centerx); }]; UIView *lastspace = V0; for (int i = 0; i < Views.count; ++i) { UIView *obj = views[i]; UIView *space = spaces[i+1]; [obj mas_makeconstraints:^ (masconstraintmaker *make) { Make.top.equalTo (Lastspace.mas_bottom); }]; [Space mas_makeconstraints:^ (Masconstraintmaker *make) { Make.top.equalTo (Obj.mas_bottom); Make.centerX.equalTo (Obj.mas_centerx); Make.height.equalTo (V0); }]; Lastspace = space; } [Lastspace mas_makeconstraints:^ (Masconstraintmaker *make) { Make.bottom.equalTo (Self.mas_bottom); }];
}
@end |
A simple test.
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 46 47 |
UIView *sv11 = [UIView new]; UIView *SV12 = [UIView new]; UIView *sv13 = [UIView new]; UIView *sv21 = [UIView new]; UIView *sv31 = [UIView new];
Sv11.backgroundcolor = [Uicolor Redcolor]; Sv12.backgroundcolor = [Uicolor Redcolor]; Sv13.backgroundcolor = [Uicolor Redcolor]; Sv21.backgroundcolor = [Uicolor Redcolor]; Sv31.backgroundcolor = [Uicolor Redcolor];
[SV Addsubview:sv11]; [SV Addsubview:sv12]; [SV Addsubview:sv13]; [SV Addsubview:sv21]; [SV Addsubview:sv31];
Give different size test results
[Sv11 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.centerY.equalTo (@[sv12,sv13]); Make.centerX.equalTo (@[sv21,sv31]); Make.size.mas_equalTo (Cgsizemake (40, 40)); }];
[Sv12 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.size.mas_equalTo (Cgsizemake (70, 20)); }];
[Sv13 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.size.mas_equalTo (Cgsizemake (50, 50)); }];
[Sv21 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.size.mas_equalTo (Cgsizemake (50, 20)); }];
[Sv31 mas_makeconstraints:^ (Masconstraintmaker *make) { Make.size.mas_equalTo (Cgsizemake (40, 60)); }];
[SV Distributespacinghorizontallywith:@[sv11,sv12,sv13]]; [SV Distributespacingverticallywith:@[sv11,sv21,sv31]];
[SV Showplaceholderwithallsubviews]; [SV Hideplaceholder]; |
Code effects
perfect! It's simple and clear, it's what we want.
The trick here is to use a blank placeholder view to fill the side of our target view, which is shown by a blank callout on the graph.
Masonry Introduction and use Practice (Quick Start AutoLayout) (RPM)