圆形视图布局–丹尼斯·沃尔什–中

我的一个朋友要我帮助她在她正在重写并升级到Swift的现有应用程序上学习自动布局,并添加一些新功能。 该应用程序是夏威夷瓦胡岛上使用的一种教育工具,旨在帮助孩子们对学习环境产生兴趣。 我们准备更新Storyboard中的许多现有视图控制器,添加UIStackViews并设置约束。 大部分设置都非常简单,我们只需要确保针对新的较大手机尺寸正确更新了按钮,图像和文本视图即可。

该应用程序的主要重点之一是在Hèeia池塘周围,其中包含传感器信息,该应用程序可以显示该信息以向孩子们显示池塘中任何给定时刻的情况。 这是设计的新功能,其想法是在池塘周围有一系列按钮,以指示位于池塘中的传感器。 基本上,我们需要将按钮排列成半圆形,以近似池塘的边缘。

我最初的想法是使用贝塞尔曲线路径在池塘周围创建弧线,然后沿弧线放置视图。 不幸的是,没有一种简单的方法可以访问组成UIBezierPath的点。 关于Stackoverflow有一个答案,但这似乎比我需要的要复杂(但可以肯定地说更准确)。

相反,我选择对高中几何和三角学课进行噩梦般的回忆。 我先要说的是,高中时代对我来说早已不存在,而几何学就我所能达到的程度而言,我做得并不好。 可以说,正是这堂课让我不喜欢数学。 即使我的计算机科学学位三角学需要所有数学运算,也从来没有真正提出太多。

问题似乎比实际上要难得多,实际上是一旦您将注意力放在数学上。 我们都(希望地)记住一个直角三角形的勾股定理:a²+b²=c²。 这与我的旧克星正弦余弦一起变得非常方便。 如果您有兴趣,可以在这里查看数学,我将跳过它,仅声明如果您有一个圆的半径和一个角度(通常由ThetaΘ表示),则可以使用余弦(Θ)函数和使用正弦(Θ)函数的y坐标。 这给了我们一个简单的公式,可以找到圆上给定点的一对(x,y)坐标。

x坐标=半径*余弦(Θ)
y坐标=半径*正弦(Θ)

我想对视图应在屏幕上出现的位置进行可视化参考,因此我使用UIBezierPath创建了一个圆,池塘的左边缘大致充当了圆的中心。 由于自然不喜欢做完美的圆,因此我们的位置将是一个近似值。 我们使用贝塞尔曲线路径绘制对齐圆,并将圆与池塘近似中心的偏移量居中。 这为我们提供了一个很好的参照视图。

接下来,我们使用一个简单的循环对视图进行布局,以计算每个视图沿假想圆放置时Theta(角度)的变化。 由于总共有9个视图和一个半圆(2π是一个完整的圆),我们将π/ 9除以得到每个视图的角度。 我们将180 °除以9,得到的角度增量为20 ° (20 ° ,40 ° ,60 °等)。 我们将初始视图的中心点设置为大约池塘的顶部,并通过增加每个视图的Theta 并使用余弦正弦函数更新初始点的(x,y)坐标,将其余视图沿圆以均匀间隔沿圆放置。新Theta作为输入。 这给我们一个很好的平滑的圆形排列。

您可以从代码库布局图像中看到,我们可以很好地近似池塘的外部边缘(足够靠近政府工作),并且使用基于代码的布局,视图将针对不同尺寸的设备(不包括设备旋转)正确调整。 唯一需要注意的是要记住,如果使用自动布局,则直到调用viewDidLayoutSubviews之后才设置基本视图的边界(在这种情况下为背景图像)。 因此,我们不想在viewDidLoad调用我们的方法,而是在viewDidLayoutSubviews调用,否则我们的数学计算将被关闭(基于Storyboard中视图的大小,它们的计算将不正确)。 我们的最终布局为池塘提供了一个近似的外观,并以对称的图案布置了优美的景色。

资源
单位圆—数学很有趣
单位圆—三角函数与几何定义
沿贝塞尔曲线路径放置图像
是否可以在路径周长上对齐视图?