-
Attributes
PureLayout-CommonAttributes.png - 下面是在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];
}
}];
}
最后是效果圖: