您的位置:首页 > 移动开发 > IOS开发

iOS-setNeedsLayout等布局方法

2016-04-24 12:17 381 查看
列举下iOS layout的相关方法:

layoutSubviews

layoutIfNeeded

setNeedsLayout

setNeedsDisplay

drawRect

sizeThatFits

sizeToFit

大概常用的上面几个 , 具体的应该还有别的。

layoutSubviews


这个方法,默认没有做任何事情,需要子类进行重写 。 系统在很多时候会去调用这个方法:

1.初始化不会触发
layoutSubviews
,但是如果设置了不为
CGRectZero
frame
的时候就会触发。

2.
addSubview
会触发
layoutSubviews


3.设置
view
Frame
会触发
layoutSubviews
,当然前提是
frame
的值设置前后发生了变化

4.滚动一个
UIScrollView
会触发
layoutSubviews


5.旋转
Screen
会触发父
UIView
上的
layoutSubviews
事件

6.改变一个
UIView
大小的时候也会触发父
UIView
上的
layoutSubviews
事件

在苹果的官方文档中强调:

You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want.layoutSubviews,
当我们在某个类的内部调整子视图位置时,需要调用。反过来的意思就是说:如果你想要在外部设置
subviews
的位置,就不要重写。

setNeedsLayout


标记为需要重新布局,不立即刷新,但
layoutSubviews
一定会被调用

配合
layoutIfNeeded
立即更新

layoutIfNeeded


如果,有需要刷新的标记,立即调用
layoutSubviews
进行布局

这个动画中有用到 举个栗子 。

如图 , 上面有个
label
,中间有个按钮 ,
label
已经被自动布局到左上角 。 然后我们那个
left
constraint


@IBOutlet weak var leftContrain:NSLayoutConstraint!


viewDidLoad
中声明好,然后在
Main.storyboard
中进行连线。点击按钮的时候 ,我们把左边的距离改成
100


在按钮的点击事件里加上这句。

leftContrain.constant = 100


然后我们想要一个动画的效果。

如果这么做

UIView.animateWithDuration(0.8, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: UIViewAnimationOptions.AllowAnimatedContent, animations: {
self.leftContrain.constant = 100
}, completion: nil)


你会发现然并卵 。其实这句话
self.leftContrain.constant = 100
只是执行了
setNeedsLayout
标记了需要重新布局,但是没有立即执行。所以我们需要在动画中调用这个方法
layoutIfNeeded


所以代码应该这么写

leftContrain.constant = 100
UIView.animateWithDuration(0.8, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: UIViewAnimationOptions.AllowAnimatedContent, animations: {
self.view.layoutIfNeeded() //立即实现布局
}, completion: nil)


所以上面不管写多少约束的改变,只需要在动画里动用 一次
self.view.layoutIfNeeded()
,所有的都会已动画的方式 。如果一些变化不想动画 。在动画前执行

self.view.layoutIfNeeded()


drawRect


这个方法是用来重绘的。

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
实时刷新屏幕

sizeToFit
sizeToFit
会自动调用
sizeThatFits
方法;

sizeToFit
不应该在子类中被重写,应该重写
sizeThatFits


sizeThatFits
传入的参数是
receiver
当前的
size
,返回一个适合的
size


sizeToFit
可以被手动直接调用
sizeToFit
sizeThatFits
方法都没有递归,对
subviews
也不负责,只负责自己

文/大石头布(简书作者)

原文链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 布局