自动布局第三方框架-pureLayout学习

  • 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];

效果:

屏幕快照 2016-04-14 下午6.01.20.png

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

效果:

屏幕快照 2016-04-14 下午5.59.56.png

-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];
                         }
                     }];
}

最后是效果图:

Untitled.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容