Spinner Icon

RVS_Spinner 控件

这是一个特殊的控件类,它实现了一个“弹出式微调器”控件。

你可以将一组值与微调器关联,当用户点击控件中心时,这些值将呈现给用户。

该控件将弹出一个“扇形”的值,可以像旋钮一样滚动,或者弹出一个 UIPickerView

它是完全独立的。你只需要实例化控件,在视图中给它一个位置(就像任何其他控件一样),并将一组值与它关联。

这些值应该附带图像。

微调器的操作和外观可以高度定制,无论是在运行时,还是通过 IB Inspectable 属性。

它解决了什么问题?

移动设备在穿梭选择器和选择器方面存在困难。Apple 的 UIPickerView 是解决动态选择问题的一个极佳方法,但存在一些问题。

首先,UIPickerView 非常大。它们占据了大量宝贵的屏幕空间。这是必要的。

此外,它们使用 DataSource 模式,在这种模式下,您在运行时以 JIT 方式提供数据。这是一个极好的方法,但它相当复杂。你牺牲了简单性来换取力量。

RVS_Spinner 是一个小图标,直到被触摸和展开。它也被设计成可以用拇指操作。

它还使用一个相当简单的 Array 数据提供程序。只需将一个 Array 的结构体与控件关联,它就被排序了。

获取方式

作为 Swift Package

你可以使用 Swift Package Manager 包含微调器,只需引用 它的 GitHub 仓库 URI (SSH: git@github.com:RiftValleySoftware/RVS_Spinner.git 或 HTTPS: https://github.com/RiftValleySoftware/RVS_Spinner.git)。

然后,你需要导入模块,通过将以下内容添加到将访问微调器的源文件中

import RVS_Spinner

使用 Carthage

你可以使用 Carthage 作为你的依赖管理器来安装它。

只需将以下内容添加到你的 Cartfile

github "RiftValleySoftware/RVS_Spinner"

这将把项目带入一个 "Carthage" 目录。

你应该添加项目中的单个文件(而不是产品)。可以在 "Checkins" 中找到它。

如果你这样做,那么就不需要导入。

如果你包含产品(在 "Build" 子目录中),你将需要导入模块,通过将以下内容添加到将访问微调器的源文件中

import RVS_Spinner

请注意,Carthage 可能不会对模块进行签名,你可能在提交时遇到问题。

直接从 GitHub

这是该项目的 GitHub 仓库。

由于整个控件只包含在一个文件中,你也可以选择直接获取该源文件(RVS_Spinner/RVS_Spinner.swift 文件),并将其包含在你的项目中;在这种情况下,你不需要 import 该模块。

事实上,我建议这样做。我不是很喜欢 "live" 依赖关系(我通常会 "snapshot" 代码依赖关系并将它们包含在项目 repo 中),而且它实际上会稍微减少开销。

这是该项目的在线文档页面。

要求

微调器以 Swift-only 静态库(或 动态框架)的形式提供,支持 iOS 13.0 及以上版本。

这是专门为 iOS (UIKit) 设计的。

依赖项

在你的项目中使用这个类没有任何依赖项。它可以作为单个源文件包含(不需要构建或库链接)。

操作

径向微调器

它的工作方式是,“静止”控件很小。默认情况下,它是一个椭圆形或圆形;可能包含图像或文本,或者只是一个图像。

点击此图像会“弹出”一个周围的图像环,可以像奖品轮或旋钮一样围绕中心旋转。

Prize Wheel Display

此弹出窗口是一个 UIControl,在控件的父视图中打开,因此父视图(控件的容器)必须能够支持添加更大的视图。此容器将约束控件弹出时的大小。

你可以在运行时或在 Interface Builder/Storyboard Editor 中指定弹出窗口或 UIPickerView 的半径。图像的大小将调整以适应圆形。

你可以使用手势控制打开的微调器。它被设计成用拇指控制;包括一个“奖品轮”微调器,你可以让控件以减速旋转的方式旋转。顶部(最可见)的值将被选中。点击旋转控件将停止它。你也可以单次点击打开的控件的任一侧,以将控件前进(递减)一个。

选择器视图变体

你也可以让标准的 UIPickerView 出现,这对于大量值,或者对于喜欢更标准的 Apple 用户体验的开发者来说可能更好。

UIPickerView Wheel Display

实现

要在你的项目中使用 RVS_Spinner,请将该框架导入到你的 Swift 4.0 或更高版本的项目中。主微调器类称为 "RVS_Spinner",你可以在故事板中使用此类。

UIPickerView 不同,微调器是自包含的。你提供给它一个 RVS_SpinnerDataItem 实例的 Array,其中至少包含一个图标(UIImage)和一个标题(String)。这些由微调器在打开时显示(微调器变体仅显示图标,但选择器变体同时显示两者)。

微调器有一个 RVS_Spinner.selectedIndex 属性,表示哪个 Array 元素是选定的值。

为了在 Interface Builder/Storyboard Editor 中使用它,你需要拖入一个 UIView,然后使其成为 RVS_Spinner 的实例。模块将是 "RVS_Spinner" (如果你使用了框架)

Interface Builder/Storyboard Editor 选项

一旦你将 RVS_Spinner 类分配给 UIView,许多选项将出现在微调器的 Attributes Inspector 中

The Spinner Attributes Inspector Options

  1. 打开背景颜色 这是在打开的径向微调器或选择器后面显示的颜色。默认情况下,它是透明的。

  2. 微调器模式 这是一个整数,有 3 个值

    • -1 仅使用径向微调器(忽略 微调器阈值 值)。
    • 0 在径向微调器和选择器之间切换(基于 微调器阈值 值)。这是默认值。
    • 1 仅使用选择器(忽略 微调器阈值 值)。
  3. 微调器阈值 这是一个整数,从 0 到你希望的任何值,它表示一个值的 Array 从径向微调器切换到选择器的点。这仅在 微调器模式 选项设置为 0(两者)时适用。

  4. 声音是否开启 这指定是否使用可听反馈。当 Alerts(铃声)设置关闭时,声音将被禁用。

  5. 触觉反馈是否开启 这指定是否使用 触觉反馈(在可以播放触觉的设备上)。

  6. 中心图像 这允许你指定一个固定图像以显示在中心。如果图像是模板模式,它将使用 UIView.tintColor 属性绘制。默认值表示中心图像将使用选定值的图像。

  7. 替换中心图像 这仅在应用 "centerImage" 时有效。如果设置为 True(开启),那么,当控件打开时,显式分配的中心图像将被当前值图标替换。关闭控件会将图标替换为分配的中心图像。

  8. Hud 模式 如果设置为 ON(默认为 OFF),则控件将在 "HUD 模式" 下渲染,其中背景将是透明的,并且不会在图像周围绘制边框。

此外,View 背景颜色 用于建立图标周围的颜色,而 Tint 颜色用于设置图标周围的边框颜色,以及选择器中显示的文本。如果图像是模板模式,它将使用此颜色绘制。

How the Options Affect the Spinner

How the Options Affect the Picker

How the Options Affect the HUD Center

如果 UIView Background Color 是透明的,并且 UIView Tint 是透明的,则图标将显示得略大,周围没有环(顺便说一句:你可以通过编程方式更改环的形状。圆形/椭圆形是默认值)。

如果 Tint 是透明的,则 UIPickerView 文本将为黑色。

编程选项

使用 RVS_Spinner 的一个重要部分是应用 RVS_SpinnerDataItem 实例的 Array

这是一个结构体,包含用于显示的图标(一个 UIImage)和一个 String(图像的标题)。 您还可以选择将更详细的描述 String 附加到数据项。

在旋转选择器弹出窗口中,仅显示图像,但在 PickerView 变体中,也会显示文本。 将文本设置为 "" 将仅在选择器中显示图像。

您还可以将任何任意数据项附加到 RVS_SpinnerDataItem 的实例。 有一个名为 value 的属性,它是一个 Any? 属性。 您可以将您想要的任何数据与 RVS_Spinner 数据项相关联。 选择 RVS_Spinner.value 的计算属性,RVS_Spinner 实例将返回整个选定的数据项。 这些是值类型,而不是引用类型

您需要以编程方式提供此数组。 您将其分配给 RVS_Spinner.values 属性,数据将立即可用。

旋转

您可以旋转控件,并且中心可以补偿。 有一个名为“isCompensatingForContainerRotation”的属性,它将强制中心中的图标始终垂直,无论控件如何旋转。 默认情况下,这是正确的。 将其设置为 false 将导致中心图标旋转以匹配控件旋转。

你不应该旋转控件。 相反,您应该旋转封闭视图(约束和定义打开的旋转器和选择器的视图)。 这确保了所有手势也被正确旋转。

旋转应该通过编程方式完成,通过设置旋转器的父视图的 transform 属性

代码示例

这是一个代码片段示例(来自 Test Harness 应用程序)

首先,我们设置要设置为控件的数据数组

func setUpDataItemsArray(_ inNumberOfItems: Int) {
    _dataItems = []
    let items = subsetOfShapes(inNumberOfItems)
    items.forEach {
        _dataItems.append(RVS_SpinnerDataItem(title: $0.name, icon: $0.image, value: _associatedText[$0.index]))
    }
    setUpSpinnerControl()
}

注意 value: _associatedText[$0.index]。 这就是我们将任意数据与数据项关联的方式。 在这种情况下,数据是简单的 String 实例,但它们可以是您喜欢的任何内容。 请记住,数据数组是值类型,而不是引用类型

func setUpSpinnerControl() {
    spinnerView.values = _dataItems
    spinnerView.selectedIndex = _dataItems.count / 2
    spinnerView.backgroundColor = _colorList[innerColorSegmentedControl.selectedSegmentIndex]
    spinnerView.tintColor = _darkColorList[borderColorSegmentedControl.selectedSegmentIndex]
    spinnerView.openBackgroundColor = _colorList[radialColorSegmentedControl.selectedSegmentIndex]
    spinnerView.delegate = self
}

请注意 spinnerView.delegate = self。 这是因为测试工具 UIViewController 应用了 RVS_SpinnerDelegate 协议。

委托

旋转器使用 Delegate 模式与实现交互。 您可以选择在不分配委托的情况下使用该控件,但拥有委托可以实现更大的交互性和响应性。

为了成为委托,您应该将 RVS_SpinnerDelegate 指定为类的基本 协议。 你的类不必是 @objc 类。 委托协议是一个纯 Swift 协议(这也是为什么你不能在 Interface Builder 中分配委托的原因)。

RVS_Spinner 类确实发送传统的 UIControl Target/Action 事件。 特别是,UIControl.Event.valueChangedUIControl.Event.touchUpInside。 您可以监听这些事件。 旋转器变体将在旋转时连续发送 UIControl.Event.valueChanged,而选择器变体只有在其完成滚动后才会发送它们。

当点击控件的中心以打开、关闭或表现得像一个按钮时,会调用 UIControl.Event.touchUpInside

子类化和修改

可以对 RVS_Spinner 进行子类化和扩展。

您也可以修改所有类型的其他内容。 RVS_Spinner 被设计为一个“基线”控件。

您可以通过将新值设置为 RVS_Spinner.displayFont 属性来修改用于在选择器变体中显示标题字符串的字体。

用法

此处已涵盖了很多内容,测试工具应用程序将有助于展示一些实际的实现,但是您可以通过更改 RVS_Spinner.selectedIndex 中的基于 0 的索引来更改所选索引(哪个项目被选为当前值)。 无法设置 RVS_Spinner.value。 这是一个只读属性。

基本测试工具应用程序

基本测试工具目标导入编译后的框架,因此它确实提供了 RVS_Spinner 的实际应用。

此应用程序可以访问旋转器的许多“旋钮和按钮”。

这是一个简单的单视图应用程序,只有一个窗口

The Test Harness Screen

这些控件在控制面板上方显示的 RVS_Spinner 的实例上实时运行

白色"关联文本#XX (XXXXX)*"是一个标签,显示与用于测试的 20 个数据项中的每个数据项相关联的测试数据。 每个项目的 value 属性设置为 String,当选择该项目时,该字符串将显示为该项目。

禁用项目”分段开关将随机影响各个项目的“isEnabled”属性。

旋转器/选择器阈值”分段开关将影响上面描述的“旋转器阈值”属性。 它仅对“两者”旋转器模式启用(如下所述)

触觉反馈”和“声音”开关控制是否开启每个属性。 默认开启。

下面是“旋转器模式”分段开关。 如果选择“仅旋转器”,则无论 values 数组属性中提供了多少值,该控件都将仅弹出一个旋转器。 如果选择了此项,则“旋转器/选择器阈值”分段开关将被禁用。

如果选择“仅选择器”,则仅显示选择器。 “旋转器/选择器阈值”分段开关也被禁用。

如果选择“两者”,则“旋转器/选择器阈值”分段开关将启用,并描述了许多值,这些值将 RVS_Spinner 实例的行为从旋转器弹出窗口更改为选择器弹出窗口。

边框和文本颜色”分段开关有一些预设,应用于 UIView.tintColor 属性。

打开控件背景颜色”分段开关会影响上面讨论的“打开背景颜色”属性。

中心背景颜色”分段开关会影响 UIView.backgroundColor 属性,并影响中心圆的填充以及打开的控件中图标周围的任何“框架”。

值的数量”分段开关将最多 20 个可用值的子集应用于控件。 如果选择“1”,则控件不会弹出,但其行为有点像常规 UIButton

测试工具应用程序经过精心设计,非常简单,应为使用 RVS_Spinner 提供一个极好的“起点”。

简单示例

这里有两个简单的示例,以测试工具应用程序为特色,展示了如何在你的项目中实现 RVS_Spinner

这些链接将下载 .zip 文件,这些文件将展开到小的项目目录中。

选项卡式测试工具应用程序

还有另一个测试工具应用程序,它使用选项卡式布局,通过使用棘手的自动布局技术,在一些不同的场景中显示控件。

The First Tab

第一个选项卡是一个简单的居中控件。 您可以选择要使用的数据集,以及是否将其强制为旋转器或选择器。

The Second Tab

第二个选项卡是一个一直挤到右下角的控件,并逆时针旋转 45 度。

The Third Tab with Rotation Compensation On

第三个选项卡演示了旋转。 滑块控制旋转,封闭视图显示为略微暗淡的正方形。

上图显示了旋转补偿已开启。 请注意,尽管控件已旋转,但中心图标是垂直的。

The Third Tab with Rotation Compensation Off

此图像显示旋转补偿已关闭。 请注意,中间的图标现在是倾斜的。

The Fourth Tab

第四个选项卡有点疯狂。 它是四个独立的控件,被分成屏幕的四个象限,并且每个象限都偏离平面旋转 45 度,但中间互相嵌入。

泄漏测试工具应用程序

有一个小的、简单的应用程序,它存在的唯一目的:以“Profile”模式运行,并检查框架是否存在内存泄漏之类的问题。

The Leak Test App

HUD 模式测试工具应用程序

这是一个较新的应用程序,它只是测试和演示了新的(自 2.4.0 版本起)HUD 模式和中心图像。

The HUD Mode Test App

中心图像”分段开关允许您更改中心图像。

“空白”分段意味着没有指定中心图像。这意味着中心图像由所选值确定。在这种情况下,它将以模板模式显示,因此它将通过 UIView.tintColor 属性进行着色。

“地球”分段将使中心图像成为“原始模式”图像(来自太空的地球照片)。 这也将实现“替换中心图像”选项。

“地球仪”分段将使中心使用来自资源的模板模式图像。

“问号”分段将使用来自系统 SF Symbols 自动生成的图像(模板模式)。

高亮颜色”分段开关允许您更改 UIView.tintColor 属性。

The HUD Mode Test App (Original Image)

The HUD Mode Test App (Template Resource Image)

The HUD Mode Test App (Template SF Symbols Image)

许可协议

MIT 许可

特此授予任何人免费获得本软件和相关文档文件(“软件”)的副本的许可,以不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件的副本的权利,并允许向其提供本软件的人员这样做,但须符合以下条件:

上述版权声明和本许可声明应包含在所有副本或本软件的实质性部分中。

本软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于适销性、特定用途适用性和非侵权保证。 在任何情况下,作者或版权持有人均不对因使用本软件或与本软件相关的任何索赔、损害或其他责任承担责任,无论是在合同诉讼、侵权诉讼或其他诉讼中。

The Great Rift Valley Software Company: https://riftvalleysoftware.com