-
Attributes
- 下面是在pureLayout中经常使用的五个参数(There are 5 specific attribute types, which are used throughout most of the API)
1.ALEdge
2.ALDimension
3.ALAxis
4.ALMargin available in iOS 8.0 and higher only
5.ALMarginAxis available in iOS 8.0 and higher only - 以上的所有参数类型都是ALAttribute枚举中的一员。拿ALEdge来说
ALAttribute-> ALEdgeLeft
且有ALEdge->ALEdgeLeft
根据框架中的源代码可以知道 ALEdgeLeft == NSLayoutAttributeLeft - Additionally, there is one generic attribute type, ALAttribute
, which is effectively a union of all the specific types. You can think of this as the "Supertype" of all of the specific attribute types, which means that it is always safe to cast a specific type to the generic ALAttribute
type. (Note that the reverse is not true -- casting a generic ALAttribute to a specific attribute type is unsafe!) - 使用方法
-
UIView
的对象方法
- autoSetContent(CompressionResistance|Hugging)PriorityForAxis: - autoCenterInSuperview(Margins) // Margins variant iOS 8.0+ only
- autoAlignAxisToSuperview(Margin)Axis: // Margin variant iOS 8.0+ only
- autoPinEdgeToSuperview(Edge:|Margin:)(withInset:) // Margin variant iOS 8.0+ only
- autoPinEdgesToSuperview(Edges|Margins)(WithInsets:)(excludingEdge:) // Margins variant iOS 8.0+ only
- autoPinEdge:toEdge:ofView:(withOffset:)
- autoAlignAxis:toSameAxisOfView:(withOffset:|withMultiplier:)
- autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:)
- autoSetDimension(s)ToSize:
- autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:)
- autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset: // iOS only
- demo
-1.
蓝色的view位于父view的中心,且大小是50pt
// Blue view is centered on screen, with size {50 pt, 50 pt}
[self.blueView autoCenterInSuperview];
[self.blueView autoSetDimensionsToSize:CGSizeMake(50.0, 50.0)];
红色的View顶部与蓝色view底部位置一样,左边与蓝色的右边位置一样
宽度与蓝色的view一直,高度为40pt
// Red view is positioned at the bottom right corner of the blue view, with the same width, and a height of 40 pt
[self.redView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.blueView];
[self.redView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.blueView];
[self.redView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.blueView];
[self.redView autoSetDimension:ALDimensionHeight toSize:40.0];
黄色的view的顶部与红色的view底部+10pt位置一致,高度为25pt,左右距父控件均为25pt
// Yellow view is positioned 10 pt below the red view, extending across the screen with 20 pt insets from the edges,
// and with a fixed height of 25 pt
[self.yellowView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.redView withOffset:10.0];
[self.yellowView autoSetDimension:ALDimensionHeight toSize:25.0];
[self.yellowView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:20.0];
[self.yellowView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:20.0];
绿色的view顶部与黄色view底部间距10,与父view垂直居中,高度是黄色的view的高度的两倍,宽度为150
// Green view is positioned 10 pt below the yellow view, aligned to the vertical axis of its superview,
// with its height twice the height of the yellow view and its width fixed to 150 pt
[self.greenView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.yellowView withOffset:10.0];
[self.greenView autoAlignAxisToSuperviewAxis:ALAxisVertical];
[self.greenView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:self.yellowView withMultiplier:2.0];
[self.greenView autoSetDimension:ALDimensionWidth toSize:150.0];
效果:
-2.上面是一些UIView
的对象方法,下面这个demo是数组的对象方法,数组有两种,一种是UIView
的数组,一种是constraint
的数组,先来看UIView
的数组
方法:
// Arrays of Views
- autoAlignViewsToEdge:
- autoAlignViewsToAxis:
- autoMatchViewsDimension:
- autoSetViewsDimension:toSize:
- autoSetViewsDimensionsToSize:
- autoDistributeViewsAlongAxis:alignedTo:withFixedSpacing:(insetSpacing:)(matchedSizes:)
- autoDistributeViewsAlongAxis:alignedTo:withFixedSize:(insetSpacing:)
这是一个使用的demo
一次性将红色的view与黄色的view的高度设置为50,蓝色与绿色的高度为70,作者在方法的申明中写了如下注释:(注意数组里至少要有一个view,方法返回值是一个被添加了约束的数组)
/**
Sets all of the views in this array to a given size.
Note: This array must contain at least 1 view.
@param size The size to set each view's dimensions to.
@return An array of constraints added.
*/
// Apply a fixed height of 50 pt to two views at once, and a fixed height of 70 pt to another two views
[@[self.redView, self.yellowView] autoSetViewsDimension:ALDimensionHeight toSize:50.0];
[@[self.blueView, self.greenView] autoSetViewsDimension:ALDimensionHeight toSize:70.0];
NSArray *views = @[self.redView, self.blueView, self.yellowView, self.greenView];
创建一个包含四个view的数组,使数组里的view的宽度均一致,且使红色的view顶部到控制器的view的导航栏距离为20
NSArray *views = @[self.redView, self.blueView, self.yellowView, self.greenView];
// Match the widths of all the views
[views autoMatchViewsDimension:ALDimensionWidth];
// Pin the red view 20 pt from the top layout guide of the view controller
[self.redView autoPinToTopLayoutGuideOfViewController:self withInset:20.0];
使数组里的第一个view的左边粘着父view的左边,遍历数组中的每一个view依次粘着左边的view,完成遍历后,使数组里的最后一个view的右边粘着父view的右边,因为之前设置过数组里的每一个view等宽,所以完成了如下图的效果
// Loop over the views, attaching the left edge to the previous view's right edge,
// and the top edge to the previous view's bottom edge
[[views firstObject] autoPinEdgeToSuperviewEdge:ALEdgeLeft];
UIView *previousView = nil;
for (UIView *view in views) {
if (previousView) {
[view autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:previousView];
[view autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:previousView];
}
previousView = view;
}
[[views lastObject] autoPinEdgeToSuperviewEdge:ALEdgeRight];
self.didSetupConstraints = YES;
}
效果:
-3.用pureLayout实现动画效果
在view出现的时候开始执行动画函数animateLayoutWithRegularAnimation
同时设定一个属性用来记录动画执行的状态self.isAnimatingToEndState = YES;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
/**
Start the animation when the view appears. Note that the first initial constraint setup and layout pass has already occurred at this point.
To switch between spring animation and regular animation, comment & uncomment the two lines below!
(Don't uncomment both lines, one at a time!)
*/
self.isAnimatingToEndState = YES;
[self animateLayoutWithSpringAnimation]; // uncomment to use spring animation
// [self animateLayoutWithRegularAnimation]; // uncomment to use regular animation
}
通过标注动画状态属性设置约束属性,这个地方需要注意更改的是约束的constant属性。至于理由作者写的很清楚,可以很方便的更新现有的约束,而不用移除已有的约束再添加新的约束。
- (void)updateViewConstraints
{
static const CGFloat kBlueViewInitialHeight = 40.0;
static const CGFloat kBlueViewEndHeight = 100.0;
// Remember, this code is just the initial constraint setup which only happens the first time this method is called
if (!self.didSetupConstraints) {
[self.blueView autoPinToTopLayoutGuideOfViewController:self withInset:20.0];
[self.blueView autoAlignAxisToSuperviewAxis:ALAxisVertical];
[self.blueView autoSetDimension:ALDimensionWidth toSize:50.0];
self.blueViewHeightConstraint = [self.blueView autoSetDimension:ALDimensionHeight toSize:kBlueViewInitialHeight];
[self.redView autoSetDimension:ALDimensionHeight toSize:50.0];
[self.redView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionHeight ofView:self.blueView withMultiplier:1.5];
[self.redView autoAlignAxisToSuperviewAxis:ALAxisVertical];
self.didSetupConstraints = YES;
}
// Unlike the code above, this is code that will execute every time this method is called.
// Updating the `constant` property of a constraint is very efficient and can be done without removing/recreating the constraint.
// Any other changes will require you to remove and re-add new constraints. Make sure to remove constraints before you create new ones!
[self.redViewEdgeConstraint autoRemove];
if (self.isAnimatingToEndState) {
// Adjust constraints to be in the end state for the animation
self.blueViewHeightConstraint.constant = kBlueViewEndHeight;
self.redViewEdgeConstraint = [self.redView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:150.0];
} else {
// Adjust constraints to be in the initial state for the animation
self.blueViewHeightConstraint.constant = kBlueViewInitialHeight;
self.redViewEdgeConstraint = [self.redView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.blueView withOffset:20.0];
}
[super updateViewConstraints];
}
动画函数,这里需要注意的是在动画blockUIView animationWithDuration...
中的completion
里,改变了动画的执行状态并且再次调用该函数,也就形成了函数的重复执行。
/**
See the comments in viewDidAppear: above.
*/
- (void)animateLayoutWithSpringAnimation
{
// These 2 lines will cause -[updateViewConstraints] to be called again on this view controller, where the constraints will be adjusted to the new state
[self.view setNeedsUpdateConstraints];
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0
delay:0.0
usingSpringWithDamping:0.6
initialSpringVelocity:0
options:0
animations:^{
[self.view layoutIfNeeded]; // this is what actually causes the views to animate to their new layout
}
completion:^(BOOL finished) {
// Run the animation again in the other direction
self.isAnimatingToEndState = !self.isAnimatingToEndState;
if (self.navigationController) { // this will be nil if this view controller is no longer in the navigation stack (stops animation when this view controller is no longer onscreen)
[self animateLayoutWithSpringAnimation];
}
}];
}
最后是效果图: