Jane books migration

# the premise

After some time, I find that there are few navigation tutorials online, and only one or two. Here I would like to compile some methods I would like to use for you to learn.

Navigation is a third-party library for AutoLayout. It uses the link syntax to retrieve the code you would like to retrieve. Therefore, learning costs will be significantly lower than those for AutoLayout and VFL.

# prepared

In making https://github.com/SnapKit/Masonry download configuration third-party libraries, basic usage also have instructions in the Readme, I will not go into, CocoaPods in my blog have related Settings introduced CocoaPods install and use


pod 'Masonry'

Copy the code

‘~> X.X.X ‘is not used to update the library.

Add to PCH file


#import "Masonry.h"

Copy the code

Can be used globally

# Basic usage

Can understand and Android five layout of the relative layout, the basic principle is the position of the control relative to a control, so the relative comparison needs to have a reference control

The basic calculation formula is

Control left = right of reference control + offset value (5) (control is to the right of reference control, 5px away)

make.left.equalTo(view.superview.mas_right).offset(10); // If left blank, the default is leftCopy the code

# Supported attributes


@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;

Copy the code

# # method

There are three ways to set constraints for navigation

Using updateconstraints for the first time, you will remove all of the previous constraintsCopy the code

Note: when circulating the cell where code is called repeatedly, use mas_remakeConstraints to prevent the same constraints being generated when circulating, which may be held in performance, even when used with make to prevent unnecessary constraints being generated

# Simple usage

Initializes a view with margins

UIView *view = [[UIView alloc] init]; view.backgroundColor = [UIColor redColor]; [self.view addSubview:view]; // Add the parent control first, [MASConstraintMaker *make] { make.edges.equalTo(view.superview).insets(UIEdgeInsetsMake(20, 20, 20, 20)); }];Copy the code

equivalent


[view mas_makeConstraints:^(MASConstraintMaker *make) {

make.left.right.top.bottom.equalTo(view.superview).insets(UIEdgeInsetsMake(20, 20, 20, 20));

Copy the code

Left,right, and other attributes, as literal

equivalent

[view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(view.superview).offset(20);  make.top.equalTo(view.superview).offset(20); make.right.equalTo(view.superview).offset(-20);  make.bottom.equalTo(view.superview).offset(-20); }];Copy the code

In chained syntax, and and with are both modifiers that don’t do anything and are easy to understand


make.bottom.and.top.equalTo(view.superview).with.offset(-20);

Copy the code

In the source


#pragma mark - Semantic properties

- (MASConstraint *)with {

return self;

}

- (MASConstraint *)and {

return self;

}

Copy the code

A child control is half the width of the parent control.

[view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(view.superview); Make. Top. EqualTo (view. Superview). Offset (20); make the width, height, equalTo (view. Superview.) multipliedBy (0.5);}];Copy the code

## is greater than or less than


make.width.greaterThanOrEqualTo(@200);

make.width.lessThanOrEqualTo(@400)

Copy the code

## Use constraints for judgment in BLCOK (when unifying some business)


[self.button mas_remakeConstraints:^(MASConstraintMaker *make) {

make.size.equalTo(self.buttonSize);

if (topLeft) {

make.top.and.left.offset(10);

} else{ make.bottom.and.right.offset(-10); }}]; Dead altitude 300 x 300Copy the code

## Modify the specified constraint

MASConstraint *topConstraint; // While generating constraints [view1 mas_makeConstraints:^(MASConstraintMaker *make) {topConstraint = make.top.equalTo(superview.mas_top); make.left.equalTo(superview.mas_left); }]; . // Modify the constraint later [topConstraint uninstall];Copy the code

## Write dead height 300 * 300

[view mas_makeConstraints:^(MASConstraintMaker *make) { make.center.equalTo(view.superview);  make.width.height.equalTo(@300); }];Copy the code

## About mas_equalTo use

You’ll find two ways to say equivalence: equalTo and mas_equalTo

Mas_equalTo is really just a macro with an extra layer of processing, because equalTo doesn’t support basic data types


#define mas_equalTo(...) equalTo(MASBoxValue((__VA_ARGS__)))

Copy the code

In the height 300 constraint, we could write it like this


mak.height.equalTo(@300);

Copy the code

You can also use mas_equalTo. In general, I will use mas_equalTo for all the encapsulation of basic data types


mak.height.mas_equalTo(300);

Copy the code

## Parallel sort – level or height

Often encounter a lot of need to equal width or height sorting requirements, the following is a method I use personally, you can refer to it, but it needs to be noted that the various uses of the relative layout are many, please think about it, the same effect, N kinds of writing

- (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *viewArray = [NSMutableArray array]; NSArray *colorArray = @[[UIColor redColor],[UIColor blueColor],[UIColor orangeColor],[UIColor purpleColor]];for (int i = 0; i < colorArray.count ; i++) {

UIView *view = [[UIView alloc] init];

view.backgroundColor = colorArray[i];

[self.view addSubview:view];

[viewArray addObject:view];

}

[self sortVerticalWithViews:viewArray LeftMargin:50 Width:100 BackViewHeight:300];

viewArray = [NSMutableArray array];

for (int i = 0; i < colorArray.count ; i++) {

UIView *view = [[UIView alloc] init];

view.backgroundColor = colorArray[i];

[self.view addSubview:view];

[viewArray addObject:view];

}

[self sortHorizontalWithViews:viewArray TopMargin:320 TopView:self.view Height:100];

}

#pragma mark sorts controls to update their operations (horizontal)- (void)sortHorizontalWithViews:(NSArray *)views TopMargin:(NSInteger)topMargin TopView:(UIView *)topView Height:(NSInteger)viewH { __block UIView *leftView; [views enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { UIView *tempView = obj;  [tempView mas_remakeConstraints:^(MASConstraintMaker *make) {if (idx == 0) {

make.left.equalTo(tempView.superview);

if([withmicrosoft isEqual: tempView superview]) {/ / if the incoming container view has no control over the make the top. The mas_equalTo (withmicrosoft). Offset (topMargin); }else {

make.top.mas_equalTo(topView.mas_bottom).offset(topMargin);

}

make.width.mas_equalTo(tempView.superview.mas_width).multipliedBy((CGFloat)1 / views.count);

make.height.mas_equalTo(viewH);

} else{ make.left.equalTo(leftView.mas_right); make.top.mas_equalTo(leftView); make.width.mas_equalTo(leftView); make.height.equalTo(leftView); }}]; leftView = tempView; }]; }#pragma Mark sorts controls and updates their operations (vertically)- (void)sortVerticalWithViews:(NSArray *)views LeftMargin:(NSInteger)leftMargin Width:(NSInteger)viewWidth BackViewHeight:(NSInteger)backViewHeight { __block UIView *topView; [views enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { UIView *tempView = obj;  [tempView mas_remakeConstraints:^(MASConstraintMaker *make) {if (idx == 0) {

make.left.equalTo(tempView.superview).offset(leftMargin);

make.top.mas_equalTo(tempView.superview);

make.width.mas_equalTo(viewWidth);

make.height.mas_equalTo(backViewHeight / views.count);

} else{ make.left.equalTo(topView); make.top.mas_equalTo(topView.mas_bottom); make.width.mas_equalTo(topView); make.height.mas_equalTo(topView); }}]; topView = tempView; }]; }Copy the code

# Animation problem

Animation problem, and the normal method implementation is similar, the emphasis is to modify the constraint after the call


[view.superview layoutIfNeeded];

Copy the code

[view mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(400); make.left.mas_equalTo(100);  make.size.mas_equalTo(CGSizeMake(100, 100)); }]; [view.superview layoutIfNeeded]; // If you need to animate the constraint before it is generated, force the refresh first before writing the animation. [UIView animateWithDuration:3 animations:^{[view mas_updateConstraints:^(MASConstraintMaker *make) { Make.left. Mas_equalTo (200);}]; [view.superview layoutIfNeeded];// Force draw}];Copy the code

Multiple controls are centered relative to the parent control

In this case, it is most convenient to put multiple child controls in a container, let the container adjust the width of the child controls, and center the container relative to the parent control

  • For convenience, I use a blank superView in the XIB to occupy the space, which is easy to adjust later

General steps:

  1. Add the parent control to the container
  2. Sets the position of the container relative to the parent control
  3. Loop to create child controls
- (void)initCouponType:(PPProductDetailViewModel *)viewModel { UIView *conView = [[UIView alloc] init]; [self.couponTypeContainer addSubview:conView]; / / parent to join container [conView makeConstraints: ^ (MASConstraintMaker * make) {make. Height. Top. CenterX. EqualTo (conView. Superview); //width is not set, so that it ADAPTS to the child control width}]; __block UIView *lastView = nil; For me. / / the viewModel couponTypeArray data source, configuration according to actual situationif(viewModel.couponTypeArray.count > 0) { [viewModel.couponTypeArray enumerateObjectsUsingBlock:^(GwCouponType *_Nonnull Coupontype, NSUInteger IDX, BOOL *_Nonnull stop) {UIButton *newBtn = [[UIButton alloc] init]; [newBtnsetTitle:coupontype.couponTypename forState:UIControlStateNormal]; // Add child controls to the container [conView addSubview:newBtn]; [newBtn makeConstraints:^(MASConstraintMaker *make) { // Left make.left. EqualTo (lastView? Lastview.mas_right: Newbtn.superview).offset(3); // The last child control sets the right aligned containerif(idx == viewModel.couponTypeArray.count - 1) { make.right.equalTo(newBtn.superview).offset(3); } // Align the child with the parent in the Y-axis of make.centery. EqualTo (newbtn.superview); // lastView lets the next control know what is to its left, setting the left attribute lastView = newBtn; }]; }]; }}Copy the code

#Cell height calculation

Reference star club Dai Ming @ method [AutoLayout frame Masonry use result] also can reference forkingdog FDTemplateLayoutCell (http://www.jianshu.com/p/24e4ff56bfea)

  • IOS8 above
tableView.rowHeight = UITableViewAutomaticDimension; tableView.estimatedRowHeight = 80; - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {returnUITableViewAutomaticDimension; }}Copy the code
  • iOS7
@interface DataModel: NSObject @property (copy, nonatomic) NSString *text; @property (assign, nonatomic) CGFloat cellHeight; @end - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {static CustomCell *cell; Cell static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CustomCell class])];  }); DataModel *model = self.dataArray[(NSUInteger) indexPath.row];if(model.cellHeight <= 0) { [cell makeupData:model]; / / use systemLayoutSizeFittingSize to obtain high model. CellHeight = [cell. The contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1; }return model.cellHeight;
}
Copy the code
  • For example, Autolayout – navigation implementation

# Problems encountered

AutoLayout is a new method just launched after iOS7, because in iOS7 system is not very perfect, often have some bugs, but in iOS8 relatively good processing

  • The most obvious problem is the contentSize of scorllView

  • System constraints are not drawn after they are set, but some time before the last ViewDidApper() function, and after each drawing (e.g., adding a new child control to scorllView, adding a new constraint), ScorllView’s contentOffset and contentSize are both initialized to 0, so they need to be reset each time (if you set contentSize before drawing), or you can use tableView instead of scorllView


- (void)viewDidAppear:(BOOL)animated

{

[super viewDidAppear:animated];

_scorllView.contentSize = CGSizeMake(200, 200);

}

Copy the code
  • Call if you need the frame value immediately after the constraint is set

[view.superview layoutIfNeeded];

Copy the code

And then it’s going to force the update constraint, and then you get the frame, and in iOS8 you just have to put contentSize in there to get a normal scrollView scrolling, but in iOS7 you don’t, notice that.

And if you find any difficult problems, AutoLayout will probably not be suitable for iOS. Therefore, you can search for the word “AutoLayout” directly, instead of searching for the word “navigation”.

  • The conflict contentView
  • The basic reason for the conflict between the content view and the content view is that the cell’s content view has a systematic constraint (height), and the navigation view will not manage the constraint that it will not generate itself. Therefore, the following attribute Settings should be added when the label imageview is used. Ensure priority to prevent conflicts
[_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
Copy the code

# essays

The reason why I started to write blog, just because, in the process of combing blog, I will let myself know more.

# Finally attached [irregularly updated]

I would like to post a post for you to learn from. I would like to post a video explaining all the navigation I would like to post.

Article on the development of Loin Stringer – introduction to navigation and Its Use

Article on the development of Loin String – “How to design complex Cells using navigation”

Deming Of Starlight Society – Tips on using AutoLayout Frame navigation

The Little Wolf — The Pursuit of Navigation

Interesting Autolayout example – navigation implementation