AutoLayout 汇总

一、

《AutoLayout(III):浅析动画》

http://www.vienta.me/2015/05/18/AutoLayout-%E6%B5%85%E6%9E%90%E5%8A%A8%E7%94%BB%EF%BC%88III%EF%BC%89/


在讲动画之前,先讲几个常见的可能会混淆的方法。

1.AutoLayout相关的几个易混淆的方法

setNeedsLayout
layoutIfNeeded
layoutSubViews
setNeedsUpdateConstraints
updateConstraitsIfNeed
updateConstraints

子视图在界面上的显示大概经过了:更新约束-通过约束依赖关系得到具体的frame-展示到界面。上面几个是和autolayout相关的方法,有必要大概了解一下这些方法具体是怎么用的以及在什么情况下触发。

1.[layoutView setNeedsUpdateConstraints]:告诉layoutView需要更新约束,在下次计算或者更新约束会更新约束
2.[layoutView updateConstraintsIfNeeded]:告诉layoutView立即更新约束,
3.updateConstraints:系统更新约束的实际方法

总结上面的3点就是,setNeedsUpdateConstraints确保了在将来某一时刻调用updateConstraintsIfNeeded之后会接着调用updateConstraints,从而达到更新view的约束的目的。但是要注意的是,如果仅仅单独调用2,不一定能够保证会调用updateConstraints,因为如果view上的约束是没有变动的且没有标记需要update的,这时就不会调用updateConstraints

4.[layoutView setNeedsLayout]:告诉layoutView页面需要更新,但不立即执行
5.[layoutView layoutIfNeeded]:告诉layoutView页面布局立即更新
6.layoutSubviews:系统重写布局的实际方法

总结以上3点,setNeedsLayout确保了在将来某个时刻通过调用layoutIfNeeded之后会调用系统的layoutSubviews,从而重写对view重新布局。同样的如果单独调用5,不一定能够保证调用layoutSubviews。[注:笔者写了个demo发现,调用setNeedsLayout会直接调用layoutSubviews]。如果想要每次都能立即更新布局,那就要把两个方法一起用,同样也适用于1和2。

系统调用layoutSubViews时,就会调用updateConstraintsIfNeeded,通过更新约束,用superView到subView的层次顺序,来计算frame,反向确定布局。

stackoverflow上有关于上面几个方法的深入解答并分享了作者的实用经验:

  • 如果仅想要立即改变约束,调用setNeedsLayout
  • 如果改变view的一些属性(如offsets)可能会导致布局的改变,那么调用setNeedsUpdateConstraints,更多的时候后面需要加setNeedsLayout
  • 如果想要立即改变布局,如会形成新的frame,那么需要在调用layoutIfNeeded

2.AutoLayout与动画

###[UIView animateWithDuration]方法

传统的动画主要是通过计算frame来进行动画,在autolayout下,主要是利用约束,动画的本质实际上是从一种约束状态变成另一种约束状态,从而来达到动画的目的。

这个例子的Demo在这里

ViewController.h文件中:

@property (weak, nonatomic) IBOutlet UIView *animateView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *leftConstraint;

通过改变leftConstraint的值来实现具体的平移动画,具体代码如下:

self.leftConstraint.constant = 200;

[UIView animateWithDuration:2 animations:^{
    [self.view layoutIfNeeded];
}];

对于这类简单动画,只需要在animation的block中调用layoutIfNeeded即可,从经验来看,只要调用这个方法即可。

=========================================================================================================================

二、

《iOS中AutoLayout相关方法及流程》 http://blog.csdn.net/u012703795/article/details/42969133


关于UIView的Layer,iOS提供了三个方法:

1、layoutSubviews

在iOS5.1和之前的版本,此方法的缺省实现不会做任何事情(实现为空),iOS5.1之后(iOS6开始)的版本,此方法的缺省实现是使用你设置在此view上面的constraints(Autolayout)去决定subviews的position和size。 UIView的子类如果需要对其subviews进行更精确的布局,则可以重写此方法。只有在autoresizingconstraint-based behaviors of subviews不能提供我们想要的布局结果的时候,我们才应该重写此方法。可以在此方法中直接设置subviews的frame。 我们不应该直接调用此方法,而应当用下面两个方法。

2、setNeedsLayout

此方法会将view当前的layout设置为无效的,并在下一个upadte cycle里去触发layout更新。

3、layoutIfNeeded

使用此方法强制立即进行layout,从当前view开始,此方法会遍历整个view层次(包括superviews)请求layout。因此,调用此方法会强制整个view层次布局。


基于约束的AutoLayer的方法:

1、setNeedsUpdateConstraints

当一个自定义view的某个属性发生改变,并且可能影响到constraint时,需要调用此方法去标记constraints需要在未来的某个点更新,系统然后调用updateConstraints.

2、needsUpdateConstraints

constraint-based layout system使用此返回值去决定是否需要调用updateConstraints作为正常布局过程的一部分。

3、updateConstraintsIfNeeded

立即触发约束更新,自动更新布局。

4、updateConstraints

自定义view应该重写此方法在其中建立constraints. 注意:要在实现在最后调用[super updateConstraints]

Auto Layout Process 自动布局过程

与使用springs and struts(autoresizingMask)比较,Auto layout在view显示之前,多引入了两个步骤:updating constraints 和laying out views。每一个步骤都依赖于上一个。display依赖layout,而layout依赖updating constraints。 updating constraints->layout->display

第一步:updating constraints,被称为测量阶段,其从下向上(from subview to super view),为下一步layout准备信息。可以通过调用方法setNeedUpdateConstraints去触发此步。constraints的改变也会自动的触发此步。但是,当你自定义view的时候,如果一些改变可能会影响到布局的时候,通常需要自己去通知Auto layout,updateConstraintsIfNeeded。

自定义view的话,通常可以重写updateConstraints方法,在其中可以添加view需要的局部的contraints。

第二步:layout,其从上向下(from super view to subview),此步主要应用上一步的信息去设置view的center和bounds。可以通过调用setNeedsLayout去触发此步骤,此方法不会立即应用layout。如果想要系统立即的更新layout,可以调用layoutIfNeeded。另外,自定义view可以重写方法layoutSubViews来在layout的工程中得到更多的定制化效果。

第三步:display,此步时把view渲染到屏幕上,它与你是否使用Auto layout无关,其操作是从上向下(from super view to subview),通过调用setNeedsDisplay触发,

因为每一步都依赖前一步,因此一个display可能会触发layout,当有任何layout没有被处理的时候,同理,layout可能会触发updating constraints,当constraint system更新改变的时候。

需要注意的是,这三步不是单向的,constraint-based layout是一个迭代的过程,layout过程中,可能去改变constraints,有一次触发updating constraints,进行一轮layout过程。

注意:如果你每一次调用自定义layoutSubviews都会导致另一个布局传递,那么你将会陷入一个无限循环中。 


三、

《UIView常用的setNeedsDisplay和setNeedsLayout》  http://www.jianshu.com/p/33a28bb14749

  • 1.UIView的setNeedsDisplay和setNeedsLayout方法
    首先两个方法都是异步执行的。而setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到 UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调用layoutSubViews,
    就可以 处理子视图中的一些数据。
    综上所诉,setNeedsDisplay方便绘图,而layoutSubViews方便出来数据。

  • layoutSubviews在以下情况下会被调用:

    • 1、init初始化不会触发layoutSubviews。
    • 2、addSubview会触发layoutSubviews。
    • 3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
    • 4、滚动一个UIScrollView会触发layoutSubviews。
    • 5、旋转Screen会触发父UIView上的layoutSubviews事件。
    • 6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
    • 7、直接调用setLayoutSubviews。
  • drawRect在以下情况下会被调用:

    • 1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect调用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量值).
    • 2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
    • 3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
    • 4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
      以上1,2推荐;而3,4不提倡
  • drawRect方法使用注意点:

    • 1、若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或者 setNeedsDisplayInRect,让系统自动调该方法。
    • 2、若使用CAlayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法
    • 3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

  

参考 : http://ibloodline.com/articles/2016/03/02/autolayout-questions.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值