`
啸笑天
  • 浏览: 3461168 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

UIView的layoutSubviews和drawRect

 
阅读更多

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

综上两个方法都是异步执行的,layoutSubviews方便数据计算,drawRect方便视图重绘。

 

先大概看下ios layout机制相关的这几个方法:

- (CGSize)sizeThatFits:(CGSize)size

- (void)sizeToFit

——————-

- (void)layoutSubviews

- (void)layoutIfNeeded

- (void)setNeedsLayout

——————–

- (void)setNeedsDisplay

- (void)drawRect

 

一、

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。

8、直接调用setNeedsLayout。

在苹果的官方文档中强调:You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want. 

layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。

反过来的意思就是说:如果你想要在外部设置subviews的位置,就不要重写。

 

 刷新子对象布局

-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写

-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用

-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局

在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]

 

二、

drawRect在以下情况下会被调用:

1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).

2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。

sizeToFit会自动调用sizeThatFits方法;

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

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

sizeToFit可以被手动直接调用

sizeToFit和sizeThatFits方法都没有递归,对subviews也不负责,只负责自己

3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。

4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。

-setNeedsDisplay方法:标记为需要重绘,异步调用drawRect

-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘

以上1,2推荐;而3,4不提倡

 

drawRect方法使用注意点:

1、 若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate 的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或 者 setNeedsDisplayInRect,让系统自动调该方法。

2、若使用calayer绘图,只能在drawInContext: 中(类似鱼drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法

3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

 

三、

layoutSubviews对subviews重新布局

layoutSubviews方法调用先于drawRect

setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews

layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.根据Apple官方文档,layoutIfNeeded方法应该是这样的

layoutIfNeeded遍历的不是superview链,应该是subviews

drawRect是对receiver的重绘,能获得context

setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘

分享到:
评论
2 楼 啸笑天 2016-04-26  
http://reviewcode.cn/article.html?reviewId=14  在哪里写Autolayout布局最合适?
1 楼 云端月影 2015-10-13  
        

相关推荐

    uiview源码使用

    `layoutSubviews`方法在视图需要更新布局时被调用,开发者可以在其中调整子视图的位置和大小。 7. **遮罩和背景**:`UIView`的`backgroundColor`属性可以设置背景颜色,`maskLayer`属性则可以添加遮罩层,实现不...

    iOS布局渲染之UIView方法的调用时机详解

    开发者应根据实际情况合理利用`updateConstraints`、`layoutSubviews`和`drawRect:`,确保视图在正确的时间得到正确的更新和显示。在日常开发中,对这些基本原理的掌握能够帮助解决很多布局和性能问题。

    ios-波浪.zip

    在这个“WareViewTest”文件中,我们可以预期找到一个自定义的视图类,它可能扩展了`UIView`并重写了`layoutSubviews`或`drawRect:`方法来绘制波浪。同时,也可能会有一个对应的`ViewController`来展示这个自定义...

    DSCollectionView

    索引条部分使用UIView 的 layoutSubviews绘制字母和边框线 setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调用layoutSubViews,就...

    JBInterfaceController:向 WatchKit 界面控制器添加类似 UIViewController 的功能

    子类通过调用 updateInterface 方法(在 UIView drawRect 和 layoutSubviews 概念之后轻轻建模)使更新界面元素变得容易。 我的表行(我没有包括在这个例子中)是 JBInterface 子类,它们只是使自己无效。 然后...

    ios中自定义alert view,并实现动画组合

    例如,他们可能会创建一个自定义的UIView子类,重写`layoutSubviews`方法以适应自定义布局,然后在`awakeFromNib`或初始化方法中设置初始状态。在动画部分,可能使用`UIView.animate(withDuration:animations:...

    自定义视图 在storyBoard中使用,继承父视图的autoLayout

    4. 如果需要,重写`layoutSubviews`方法,以在视图布局发生变化时更新子视图的位置和大小。 5. 可选地,实现`drawRect:`方法,用于自定义视图的绘图。 描述中的“xib自定义UIView”是指使用 Interface Builder(XIB...

    自定义控件

    我们需要确保控件的约束设置正确,同时在`layoutSubviews()`方法中更新内部视图的位置和大小。 7. **优化性能**:在自定义控件的绘制过程中,尽量避免在`draw(_:)`或`drawRect:`方法中进行耗时的操作,如计算复杂...

    ios-彩色渐变旋转圆盘.zip

    在GYCircleView中,我们可以重写`layoutSubviews`方法来设置初始角度,然后使用`UIView.animate(withDuration:animations:)`方法来执行旋转动画。这个方法接收一个时间间隔和一个闭包,闭包中修改视图的transform...

    IOS应用源码之自定义的马赛克时间风格 .rar

    自定义视图需要适应不同屏幕尺寸和设备方向,因此需要实现`intrinsicContentSize`和`layoutSubviews`方法。同时,如果需要用户交互,如点击切换时间格式,还需要实现触摸事件响应。 7. **集成到项目**: 将自定义...

    IOS面试题2018总结188题

    - **自定义 UIView**:通常涉及重写 `drawRect:` 方法来绘制视图的图形内容。 - **自定义 UIControl**:除了绘图之外,还需要处理用户交互事件,例如触摸事件。 #### 8. 导入与包含 - **导入**:`import` 关键字...

    UITableViewCell的绘画

    8. **避免在`drawRect:`中使用`UIView`属性**:在`drawRect:`内设置`UIView`的属性,如`backgroundColor`,会导致系统重新绘制整个视图,效率较低。 9. **批量更新**:当需要更新多个单元格时,使用`beginUpdates`...

    IOS应用源码之AUISelectiveBordersView for iOS.rar

    源码中可能包含了`layoutSubviews`方法,该方法会在视图大小或子视图位置改变时被调用,用于更新视图的布局。 4. **绘图(Drawing)**:在iOS中,自定义视图的绘图通常在`drawRect:`方法中完成。...

    IOS应用源码——弹出列表框效果.zip

    这通常涉及到 `initWithFrame:` 初始化方法,`layoutSubviews` 布局更新,以及 `drawRect:` 绘制方法等。 2. **动画效果**:弹出列表框通常会有入场和退出的动画效果,例如渐显、滑动或缩放。开发者需要熟悉 Core ...

    IOS源码——ios适用于iOS 5、iOS 6和iOS 7的自定义NavigationBar.zip

    为了改变标题的显示方式,可以创建一个自定义的UIView作为TitleView,这样可以自由设计标题的布局和样式,如添加图片、文字和动画效果。 4. **自定义BarButtonItem**: 如果系统提供的BarButtonItem样式不符合...

    iOS游戏应用源代码——malcommac-DMScrollingTicker-770c1b0.zip

    DMScrollingTicker作为一个自定义视图,我们能学到如何在Objective-C中创建和定制自己的视图类,包括重写`drawRect:`方法进行绘图,以及`layoutSubviews`来管理子视图的布局。 4. **动画处理**: 滚动效果的实现...

    简单颜色选择器

    3. `- (void)drawRect:(CGRect)rect`:这个方法是UIView用来绘制自身内容的地方,可能会在这里实现颜色选择的界面渲染,比如创建一个色板。 4. `- (void)touchesBegan/Moved/Ended:(NSSet*> *)touches withEvent:(UI...

    LYSideslipCell-fm自定义侧滑删除按钮

    1. **UITableViewCell 的自定义**:在 iOS 开发中,通过继承 UITableViewCell 类并重写其 init 方法、layoutSubviews 方法以及复写 drawRect 方法,可以创建自定义的表格单元格。LYSideslipCell-fm 可能就是这样实现...

    IOS应用源码——图片倒影效果.zip

    5. **自定义UIView或CALayer子类**:开发者也可以选择创建自定义的UIView或CALayer子类,覆盖drawRect:或layoutSubviews方法来实现倒影。这样可以更灵活地控制倒影的生成和更新。 6. **说明.txt**:这个文件很可能...

Global site tag (gtag.js) - Google Analytics