Swift中的程序化视图:视差和缩放

在使用Storyboard多年之后,我最近决定为我的个人项目切换到Programmatic Views和Programmatic Autolayout。

这种选择背后有几个原因,主要原因是“编程视图”使创建可重用的UI组件变得更加容易。 不依赖Storyboard或XIB文件,它更容易实现:

  • 使用新功能扩展UI组件。
  • 通过框架重新分发组件。

在这篇文章中,我将介绍程序化视图和程序化自动布局,我将通过构建一个有趣且具有挑战性的UI功能来做到这一点:视图控制器标题的视差和缩放效果。 最终结果将如下所示:

事不宜迟,让我们开始实现上述效果的旅程。

第一部分:程序化视图

在本节中,我将说明在创建新项目时如何使用程序化视图。 重构一个较旧的项目以使用Programmatic Views是绝对可能的,但是通常需要花费很多精力,并且需要自己的发布。

步骤1:摆脱情节提要

开始使用程序化视图的第一步是摆脱情节提要。 让我们创建一个全新的Xcode项目并将其命名为ParallaxAndScale 。 现在,我们只需要几个步骤就可以删除对Storyboard的依赖:

  • 删除自动生成的主Storyboard( Main.storyboard )。
  • 删除Info.plistMain storyboard file base name键。
  • 修改AppDelegate.swift以编程方式实例化主视图控制器。 我通常还将自动创建的ViewController.swift重命名为MainViewController.swift
AppDelegate.swift

我们将保留LaunchScreen.storyboard因为它需要能够正确启动应用程序。

现在,我们摆脱了对Storyboard的依赖,并准备好充分利用Programmatic View。 为了实现视差和缩放效果,我们将以下视图放置在主视图控制器中:

必要的意见

我们还将需要一些约束引用,以使UI在布局更改时表现适当(当用户通过上下滚动触发特定效果时):

必需的常量和约束引用

步骤2:以编程方式创建视图

对于这一步,我想包装代码以编程方式将每个视图创建到其自己的私有方法中。 这不是严格要求的,但我认为它使代码更整洁,更易于阅读。 我还喜欢采用一种功能方法,并让每种方法都返回它创建的视图实例。 这样的实例将在显示之前适当地添加到视图控制器中。

以编程方式创建视图

步骤3:以编程方式设置自动版式约束

可以将设置Autolayout约束的代码放在单个方法( arrangeConstraints() )中,也可以分为一组私有方法,每个视图一个。 对于此特定用例,我们不需要太多约束,因此将所有Autolayout代码包装到一个方法中就足够了:

以编程方式设置自动布局约束

第4步:结合程序视图和程序自动布局

现在我们已经准备好基本块,让我们看一下如何将它们组合起来以确保正确显示主视图控制器及其内容:

结合程序化视图和程序化自动布局

viewDidLoad内部,我们首先创建视图,然后将其正确添加到视图控制器中,最后设置Autolayout约束。

警告:记住在调用代码设置约束之前将视图添加到主视图控制器! 如果您不这样做,则应用程序将崩溃,因为自动布局无法找到所需的视图层次结构,并且您将看到类似于以下内容的错误消息:

  ***由于未捕获的异常“ NSGenericException”而终止应用程序,原因:“无法通过锚点激活约束和,因为他们没有共同的祖先。  约束或其锚点是否引用了不同视图层次结构中的项目?  那是非法的。 

第二部分:视差和缩放效果

在本节中,我将说明如何实现视差和缩放效果。 有几种不同的方法可以实现这种效果。 我选择了下面的特定解决方案,因为它很容易通过Programmatic Views和Programmatic Autolayout实施,并且运行良好。

步骤1:引用标头自动布局约束

我们要创建的效果需要在运行时动态更改某些约束。 特别是在用户滚动时,我们将更改以下约束:

  • 标题视图容器顶部约束( headerTopConstraint )。
  • 标头视图容器的高度约束( headerHeightConstraint )。

这是我们捕获这些约束的引用的主视图控制器的相关部分:

现在,我们已经在arrangeConstraints()设置并捕获了必需的约束,让我们看一下如何实现所需的效果。

步骤2:触发适当的效果

当用户滚动时,将发生以下情况:

  • 向上滚动:标题视图和内容视图(在这种情况下为UILabel )以视差效果向上移动。
  • 向下滚动:标头视图已缩放。

这是实现所需行为的代码:

让我们详细了解每种效果。

步骤2a:缩放效果

实施“缩放”效果相对容易。 在设置标题视图的约束时,在arrangeConstraints() ,我们:

  • 捕获了对标题视图容器高度约束的引用
  • 将标题视图容器的高度/宽度比设置为1

使用上述约束进行缩放后,标题就像通过将高度约束调整为与当前垂直滚动位置相对应的值一样简单:

实际上会减去当前滚动位置,因为向下滚动时其值为负。

步骤2b:视差效果

实现视差效果要复杂一些。 当用户向上滚动时,我们希望标题视图和其下方的内容视图以不同的速度向上滚动。

这是实现视差效果的代码:

让我们详细研究一下。

首先,我们执行一些计算以计算创建效果所需的偏移量:

然后,我们通过以下方式完成任务:

  • 确保标题视图容器的顶部约束保持在可见视图的顶部
  • 通过与当前垂直滚动位置相对应的值来调整标题视图容器的高度约束
  • 将标题视图图像上移一个与当前垂直滚动位置成比例的值

结论

您可以在这里找到本文的完整代码。

在这篇文章中,我说明了如何在全新的项目中利用Programmatic Views和Programmatic Autolayout,并就如何构建代码以使其清晰易读(和扩展)提出了一些最佳实践。 我还为视图控制器标头实现了基本的视差和缩放效果,以概述如何以纯编程方式实现复杂的UI行为。