UIView
一个管理屏幕上矩形区域内容的对象。
TIP
iOS 2.0+ iPadOS 2.0+ Mac Catalyst 13.1+ tvOS visionOS 1.0+
@MainActor
class UIView提到的内容
- 使用响应者和响应者链来处理事件
- 关于使用 UIKit 进行应用开发
- 自定义基于文档的应用程序的启动体验
- 自定义绘图
- 增强您的应用程序的流畅过渡
概述
视图是您应用程序用户界面的基本构建块,UIView 类定义了所有视图共有的行为。视图对象在其边界矩形内渲染内容,并处理与该内容的任何交互。UIView 类是一个具体类,您可以实例化并用来显示固定的背景颜色。您还可以对其进行子类化,以绘制更复杂的内容。要显示标签、图像、按钮和其他常见于应用程序的界面元素,请使用 UIKit 框架提供的视图子类,而不是尝试定义自己的视图。
由于视图对象是您的应用程序与用户交互的主要方式,因此它们有许多责任。以下是其中的一些:
- 绘图和动画
- 视图使用 UIKit 或 Core Graphics 在其矩形区域绘制内容。
- 您可以将某些视图属性动画到新值。
- 布局和子视图管理
- 视图可以包含零个或多个子视图。
- 视图可以调整其子视图的大小和位置。
- 使用自动布局来定义在视图层次结构发生变化时,调整大小和重新定位视图的规则。
- 事件处理
- 视图是 UIResponder 的子类,可以响应触摸和其他类型的事件。
- 视图可以安装手势识别器来处理常见手势。
视图可以嵌套在其他视图中,以创建视图层次结构,这为组织相关内容提供了一种方便的方法。嵌套视图会在嵌套的子视图(称为子视图 )和父视图(称为父视图 )之间创建父子关系。一个父视图可以包含任意数量的子视图,但每个子视图只能有一个父视图。默认情况下,当子视图的可见区域超出其父视图的边界时,子视图的内容不会被裁剪。使用 clipsToBounds 属性可以改变这种行为。
frame 和 bounds 属性定义了每个视图的几何形状。frame 属性定义了视图在其父视图坐标系统中的原点和尺寸。bounds 属性定义了视图内部的尺寸,视图以此为依据,其使用几乎完全用于自定义绘图代码。center 属性提供了一种方便的方法来重新定位视图,而无需直接更改其 frame 或 bounds 属性。 有关如何使用 UIView 类的详细信息,请参阅 iOS 视图编程指南 。
创建视图
通常,您可以通过将视图从库拖动到画布来在故事板中创建视图。您也可以通过编程方式创建视图。在创建视图时,您通常会指定其相对于未来父视图的初始大小和位置。例如,以下示例创建一个视图,并将其左上角放置在父视图坐标系统中的点 (10, 10) 处(当它被添加到该父视图时)。
let rect = CGRect(x: 10, y: 10, width: 100, height: 100)
let myView = UIView(frame: rect)要将一个子视图添加到另一个视图中,请在父视图上调用 addSubview(_:) 方法。您可以向一个视图添加任意数量的子视图,并且在 iOS 中,兄弟视图可以相互重叠而不会出现任何问题。每次调用 addSubview(_:) 方法时,新的视图会放置在所有其他兄弟视图的顶部。您可以通过使用 insertSubview(_:aboveSubview:) 和 insertSubview(_:belowSubview:) 方法来指定子视图的相对 z 顺序。您还可以使用 exchangeSubview(at:withSubviewAt:) 方法交换已添加子视图的位置。 创建视图后,创建自动布局规则以管理视图在视图层次结构其余部分发生变化时的大小和位置变化。有关更多信息,请参见自动布局指南 。
绘制视图
视图绘制是根据需要进行的。当视图首次显示,或由于布局变化而使其全部或部分可见时,系统会请求视图绘制其内容。对于使用 UIKit 或 Core Graphics 的自定义内容的视图,系统会调用视图的 draw(_:) 方法。您对该方法的实现负责将视图的内容绘制到当前的图形上下文中,该上下文在调用此方法之前由系统自动设置。这会创建视图内容的静态视觉表示,然后可以在屏幕上显示。
当您的视图的实际内容发生变化时,您有责任通知系统您的视图需要重新绘制。您可以通过调用视图的 setNeedsDisplay() 或 setNeedsDisplay(_:) 方法来实现。这些方法让系统知道它应该在下一个绘制周期中更新视图。由于它会等到下一个绘制周期才更新视图,您可以在多个视图上调用这些方法,以便同时更新它们。
注意
如果您使用 OpenGL ES 进行绘图,您应该使用 GLKView 类,而不是子类化 UIView。有关如何使用 OpenGL ES 绘图的更多信息,请参见 OpenGL ES 编程指南 。 有关视图绘制周期的详细信息以及您的视图在此周期中的角色,请参见 iOS 视图编程指南 。
动画化视图
对多个视图属性的更改可以进行动画处理——也就是说,更改属性会创建一个动画,从当前值开始,到您指定的新值结束。以下是 UIView 类的可动画属性:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
要动画化您的更改,请创建一个 UIViewPropertyAnimator 对象,并使用其处理程序块来更改视图属性的值。UIViewPropertyAnimator 类允许您指定动画的持续时间和时机,但它执行实际的动画。您可以暂停当前正在运行的基于属性的动画器,以中断动画并进行交互式驱动。有关更多信息,请参见 UIViewPropertyAnimator。
线程考虑事项
对应用程序的用户界面的操作必须在主线程上进行。因此,您应该始终在应用程序的主线程中调用 UIView 类的方法。唯一可能不严格必要的情况是创建视图对象本身,但所有其他操作都应在主线程上进行。
子类化说明
UIView 类是视觉内容的一个关键子类化点,同时也需要用户交互。虽然有很多好的理由去子类化 UIView,但建议仅在基本的 UIView 类或标准系统视图无法提供所需功能时才进行子类化。子类化需要您付出更多的工作来实现视图并调整其性能。 有关避免子类化的方法的信息,请参见替代子类化 。
可重写的方法
在子类化 UIView 时,您应该重写的只有少数几个方法,还有许多方法可以根据您的需求进行重写。由于 UIView 是一个高度可配置的类,因此还有许多方法可以实现复杂的视图行为,而无需重写自定义方法,这些方法在“替代子类化”部分中进行了讨论。与此同时,以下列表包括您可能考虑在您的 UIView 子类中重写的方法:
- 初始化:
init(frame:)- 建议您实现此方法。您还可以实现自定义初始化方法,作为此方法的补充或替代。init(coder:)- 如果您从故事板或 nib 文件加载视图,并且您的视图需要自定义初始化,请实现此方法。layerClass仅在您希望视图使用不同的 Core Animation 层作为其后备存储时使用此属性。例如,如果您的视图使用平铺来显示一个大的可滚动区域,您可能希望将该属性设置为 CATiledLayer 类。
- 绘图和打印:
draw(_:)- 如果您的视图绘制自定义内容,请实现此方法。如果您的视图不进行任何自定义绘制,请避免重写此方法。draw(_:for:)- 仅在您希望在打印时以不同方式绘制视图内容时实现此方法。
- 布局和约束:
requiresConstraintBasedLayout如果您的视图类需要约束才能正常工作,请使用此属性。updateConstraints()- 如果您的视图需要在子视图之间创建自定义约束,请实现此方法。alignmentRect(forFrame:),frame(forAlignmentRect:)- 实现这些方法以覆盖您的视图如何与其他视图对齐。didAddSubview(_:),willRemoveSubview(_:)- 根据需要实现这些方法以跟踪子视图的添加和移除。willMove(toSuperview:),didMoveToSuperview()- 根据需要实现这些方法以跟踪当前视图在视图层次结构中的移动。
- 事件处理:
gestureRecognizerShouldBegin(_:)- 如果您的视图直接处理触摸事件并可能希望防止附加的手势识别器触发额外的操作,请实现此方法。touchesBegan(_:with:)、touchesMoved(_:with:)、touchesEnded(_:with:)、touchesCancelled(_:with:)- 如果您需要直接处理触摸事件,请实现这些方法。(对于基于手势的输入,请使用手势识别器。)
替代子类化
许多视图行为可以在不需要子类化的情况下进行配置。在您开始重写方法之前,请考虑修改以下属性或行为是否能提供您所需的行为。
addConstraint(_:)- 为视图及其子视图定义自动布局行为。autoresizingMask- 当父视图的框架发生变化时,提供自动布局行为。这些行为可以与约束结合使用。contentMode- 提供视图内容的布局行为,而不是视图的 frame。此属性还影响内容如何缩放以适应视图,以及内容是被缓存还是重新绘制。isHidden或alpha- 改变视图整体的透明度,而不是隐藏或对视图渲染内容应用 alpha。backgroundColor- 设置视图的颜色,而不是自己绘制该颜色。- 子视图 - 与其使用
draw(_:)方法绘制内容,不如嵌入图像和标签子视图,以展示您想要呈现的内容。 - 手势识别器 - 与其通过子类化来拦截和处理触摸事件,不如使用手势识别器将动作发送到目标对象。
- 动画 - 使用内置的动画支持,而不是尝试自己动画化更改。Core Animation 提供的动画支持快速且易于使用。
- 基于图像的背景 - 对于显示相对静态内容的视图,考虑使用带有手势识别器的 UIImageView 对象,而不是子类化并自己绘制图像。或者,您也可以使用通用的 UIView 对象,并将您的图像分配为视图的 CALayer 对象的内容。
动画是另一种使视图可见变化的方法,无需您子类化并实现复杂的绘图代码。UIView 类的许多属性都是可动画的,这意味着对这些属性的更改可以触发系统生成的动画。启动动画只需一行代码即可指示后续的任何更改都应进行动画处理。有关视图动画支持的更多信息,请参见 动画视图 。