iOS Views要点
发布日期:2022-03-18 08:27:39 浏览次数:38 分类:技术文章

本文共 6194 字,大约阅读时间需要 20 分钟。

iOS Views要点

UIView的safe area

在iOS11中,UIViewController的topLayoutGuidebottomLayoutGuideUIView的safe area替代了

@available(iOS 11.0, *)open var safeAreaInsets: UIEdgeInsets { get }@available(iOS 11.0, *)open var safeAreaLayoutGuide: UILayoutGuide { get }

,其含义是The layout guide representing the portion of your view that is unobscured by bars and other content表示不被bar和其它content这比的部分

其解释可参考:

如下的扩展:

extension UIView {    var sa_safeAreaInsets: UIEdgeInsets {        if #available(iOS 11, *) {
return safeAreaInsets } return UIEdgeInsets.zero } var sa_safeAreaFrame: CGRect { if #available(iOS 11, *) {
return safeAreaLayoutGuide.layoutFrame } return bounds }}

如下所示:

竖屏

横屏

可见现在的iPhone X在竖屏有top和bottom,在横屏的时候有Left、right和bottom的inset

- (void)viewWillLayoutSubviews{    [super viewWillLayoutSubviews];    NSLog(@"%f, %f, %f, %f", self.view.safeAreaInsets.top, self.view.safeAreaInsets.right,self.view.safeAreaInsets.bottom,self.view.safeAreaInsets.left          );}

在竖屏的safeAreaInsets输出为:44.000000, 0.000000, 34.000000, 0.000000

在横屏的safeAreaInsets输出为:0.000000, 44.000000, 21.000000, 44.000000

Subview与SuperView

view层级的一些效果:

  • view从其superview移除,那么view的subview也将移除
  • view的透明度会被subview继承

    • view的alpha属性会影响其子视图的透明性。如果一个superview的alpha值为0.5,那么它的所有子视图透明度都不会有超过0.5,因为无论它们的透明度为多少,都会相对0.5而绘制
  • view可以限制其subview的绘制,使它们在view外的任何部分都不显示。 这被称为clipping,可通过clipsToBounds属性设置

view的动态变化会有事件通知,可继承view,重写一些下面的方法:

  • willRemoveSubview(_:),didAddSubview(_:)
  • willMove(toSuperview:),didMoveToSuperview
  • willMove(toWindow:),didMoveToWindow

Frame与Bounds

1.修改bounds的size属性,会影响到其frame,但是view的center属性却不受其影响

如下的例子:

let v1 = UIView(frame:CGRect(x: 113, y: 111, width: 132, height: 194))            v1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1)            let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10))            v2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1)            mainview?.addSubview(v1)            v1.addSubview(v2)

当前显示效果为:

1

如果我们修改子view的bounds的size属性,如下:

v2.bounds.size.height += 20            v2.bounds.size.width += 20

会发现,view的frame有调整,但center却还在是原来的位置。此时子view完全覆盖父view,但view的center并没有改变

2

2.如果改变view的boundsorigin属性,则会移动其自身坐标系原点的位置

还是上面的例子,移动v1origin

v1.bounds.origin.x += 10            v1.bounds.origin.y += 10

移动后,效果如下,会发现改变父view的orgin,会影响子view的位置

3

如何理解这种改变呢?可以这样理解,v1的origin原来叫(0.0,0.0),现在把它改名了叫做(10.0,10.0),而此时v2(frame为(10.0, 10.0, 112.0, 174.0))的frame的origin刚好为(10.0,10.0),所以它们重合了

raywenderlich上有视频,利用改变父view的origin来实现一个自定义的scrollView

import UIKitclass RWScrollView: UIView {    required init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder);        //添加拖动手势        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panView(with:)))        addGestureRecognizer(panGesture)    }    //原理是:改变父view的origin的位置,会改变子view的位置    //注意添加@objc    @objc func panView(with gestureRecognizer: UIPanGestureRecognizer) {        let translation = gestureRecognizer.translation(in: self);        print("translation.y: \(translation.y)")        //动画        UIView.animate(withDuration: 0.20) {            self.bounds.origin.y = self.bounds.origin.y - translation.y        }        //reset 平移        gestureRecognizer.setTranslation(CGPoint.zero, in: self)    }}

效果如下:

scrollview效果

屏幕坐标

在iOS7和它之前的版本中,screen的坐标是不变的。而在iOS8之后则有了新的变化,screen的坐标会随着app旋转而改变。

参考:

在iOS 8上UIScreen提供了两个新的属性,这连个属性都遵守UICoordinateSpace协议:

  • coordinateSpace这个坐标的空间会旋转,它的原点总是位于左上角
  • fixedCoordinateSpace这个坐标的空间是不变的,是设备的左上角(相对于home键,这里应该是指portrait状态的设备,屏幕的左上角)

View Programming Guide for iOS

深入了解UIView,记录下中相关内容。

UIView的事件响应顺序

When a touch occurs inside a specific view, the system sends an event object with the touch information directly to that view for handling. However, if the view does not handle a particular touch event, it can pass the event object along to its superview. If the superview does not handle the event, it passes the event object to its superview, and so on up the responder chain. Specific views can also pass the event object to an intervening responder object, such as a view controller. If no object handles the event, it eventually reaches the application object, which generally discards it.

Content Modes

Each view has a content mode that controls how the view recycles its content in response to changes in the view’s geometry(几何结构) and whether it recycles its content at all. When a view is first displayed, it renders its content as usual and the results are captured in an underlying(潜在的) bitmap. After that, changes to the view’s geometry do not always cause the bitmap to be recreated. Instead, the value in the contentMode property determines whether the bitmap should be scaled to fit the new bounds or simply pinned to one corner or edge of the view.

如下的动作会导致content mode被应用:

  • Change the width or height of the view’s frame or bounds rectangles.
  • Assign a transform that includes a scaling factor to the view’s transform property.

contentmode


默认的view的frame超出superview的部分是不会被裁剪的,把clipsToBounds 设为YES可以达到裁剪的结果。裁剪之后,发生在view被裁剪区的触摸事件不会被deliver到view上。


setNeedsLayout vs layoutIfNeeded

参考

system会标记需要redrawn的view,在update cycle中来redrawing

setNeedsLayout告知system你想要layout并redraw所有的view及其子view,在update cycle的时候。这是一个异步的activity,你不知道update cycle什么时候会到来。

layoutIfNeeded是一个同步的过程,告知system你想要立即layout和redraw这个view及其子view,需要立即做,不要等待update cycle。

所以layoutIfNeeded会立即更新,而setNeedsLayout等待至下一个update cycle


View运行时交互模型(The Runtime Interaction Model for Views)

UIKit interactions with your view objects

  1. user触摸屏幕
  2. 硬件把touch event报告给UIKit
  3. UIKit把touch包装成一UIEvent对象,并把它分派到对应的view。
  4. view的事件处理code来响应event。例如,你的代码可能如下:

    • 改变view或者其subview的属性(frame, bounds, alpha等)
    • 调用setNeedsLayout方法,把view(或者其subview)mark为需要更新布局
    • 调用setNeedsDisplay或者setNeedsDisplayInRect:方法,把view(或者其subview)mark为需要被重绘
    • 通知controller改变部分数据
  5. 如果view的geometry有任何的改变,UIKit按照以下的规则来更新它的subviews:

    a. 如果你配置了autoresizing,UIkit根据这些规则来调整每个view
    b.如果view实现了layoutSubviews方法,UIKit会调用这个方法

  6. 如果view的一部分被mark为需要被redrawn,UIKit会要求view重绘它自身

  7. 更新后的view会与应用的其它可见的content合成,然后给硬件来显示
  8. 硬件把渲染后的内容显示在屏幕上

Windows

一个Window对象有如下的功能:

  • It contains your application’s visible content.
  • It plays a key role in the delivery of touch events to your views and other application objects.
  • It works with your application’s view controllers to facilitate orientation changes.

转载地址:https://windzen.blog.csdn.net/article/details/52702283 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:UIFont-动态字体
下一篇:iOS Concurrency-Operation

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月11日 11时18分46秒