适用于 iOS 的混合标记菜单/径向滑块 Swift 组件

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观


在过去的几周里,我一直在改进我原来的 iOS 标记菜单组件 ,并进行了一些非常重要的更改:

  • 将菜单项分布在一个完整的圆圈上意味着我的手指经常会隐藏一些项目。虽然将菜单定位在屏幕中央可以稍微缓解这种情况,但我现在将布局更改为从 9 点钟到 3 点钟的半圆形。
  • 标记菜单现在会在触摸位置弹出。
  • 标记菜单项现在可以是径向滑块以设置标准化值。径向滑块将自身定位在触摸位置下方。通过将触摸点从原点移开,从而增加径向刻度盘的半径,用户可以增加径向刻度盘的大小以进行非常精确的更改。
  • 标记菜单项可以被设置为 选中 和被赋予 类别

为了演示这些更改,我更新了演示应用程序。该应用程序允许用户添加不同的模糊和锐化滤镜,并更新模糊和锐化量以及亮度、饱和度和对比度。

顶层菜单包含三个项目: 模糊 锐化 颜色调整

Blur 包含三个用于选择模糊类型的项目和一张幻灯片。它在 Swift 中的定义如下所示:


 let blurAmountSlider = FMMarkingMenuItem(label: "Blur Amount", valueSliderValue: 0)
let blurTopLevel = FMMarkingMenuItem(label: FilterCategories.Blur.rawValue, subItems:[
    FMMarkingMenuItem(label: FilterNames.CIGaussianBlur.rawValue, category: FilterCategories.Blur.rawValue, isSelected: true),
    FMMarkingMenuItem(label: FilterNames.CIBoxBlur.rawValue, category: FilterCategories.Blur.rawValue),
    FMMarkingMenuItem(label: FilterNames.CIDiscBlur.rawValue, category: FilterCategories.Blur.rawValue),
    blurAmountSlider])

您可以在此处看到滑块使用 valueSliderValue 构造函数,该构造函数将其 isValueSlider 属性设置为 true。当用户标记该菜单项时,会弹出径向滑块。

您可能还会注意到其他三个项目有一个 类别 集。尽管标记菜单组件并不真正关心类别,但宿主应用程序可能会关心。在我的演示应用程序中,我只希望用户能够选择一种模糊类型; Gaussian Box Disc。

为此,所有三个项目共享相同的 Blur 类别,并且在我的 FMMarkingMenuItemSelected 委托方法中,我调用 setExclusivelySelected 以强制每个类别仅选择一个菜单项:


 let blurAmountSlider = FMMarkingMenuItem(label: "Blur Amount", valueSliderValue: 0)
let blurTopLevel = FMMarkingMenuItem(label: FilterCategories.Blur.rawValue, subItems:[
    FMMarkingMenuItem(label: FilterNames.CIGaussianBlur.rawValue, category: FilterCategories.Blur.rawValue, isSelected: true),
    FMMarkingMenuItem(label: FilterNames.CIBoxBlur.rawValue, category: FilterCategories.Blur.rawValue),
    FMMarkingMenuItem(label: FilterNames.CIDiscBlur.rawValue, category: FilterCategories.Blur.rawValue),
    blurAmountSlider])

选定的菜单项为红色,并且其 isSelected 属性设置为 true。

布局的变化是由一些布尔属性设置的。如果以及当我将此组件发布到 OS X 时(使用鼠标意味着我的胖手指不会隐藏菜单),可以通过将 layoutMode 设置为 FMMarkingMenuLayoutMode.Circular 将布局返回到完整的圆形。

这个版本的 FMMarkingMenu 是在 Xcode 7 下用 Swift 2.0 编写的,我只能在运行 iOS 9 的 iPad 上对其进行测试。该代码自由使用了我非常喜欢的新守卫语法(请参阅 Natasha 的这篇精彩文章机器人 了解更多关于 守卫的信息 )。能够选择性地绑定大量常量,并在其中一个方法失败时轻松提前退出方法,这使得编码变得轻而易举:


 let blurAmountSlider = FMMarkingMenuItem(label: "Blur Amount", valueSliderValue: 0)
let blurTopLevel = FMMarkingMenuItem(label: FilterCategories.Blur.rawValue, subItems:[
    FMMarkingMenuItem(label: FilterNames.CIGaussianBlur.rawValue, category: FilterCategories.Blur.rawValue, isSelected: true),
    FMMarkingMenuItem(label: FilterNames.CIBoxBlur.rawValue, category: FilterCategories.Blur.rawValue),
    FMMarkingMenuItem(label: FilterNames.CIDiscBlur.rawValue, category: FilterCategories.Blur.rawValue),
    blurAmountSlider])

我希望这篇文章能让您深入了解该组件。如果您有任何问题或意见,请通过 Twitter ( @FlexMonkey ) 与我联系。该项目的源代码位于 我的 GitHub 存储库 中。

最后,关于专利问题的说明。我已经联系 Autodesk 询问专利侵权问题,但没有成功。我确信我的组件与他们的完全不同(尤其是最近发生的所有这些变化),因此没有侵权。此外,还有大量“现有技术”(例如 Don Hopkins 多年来一直在模拟人生中使用径向菜单 )和其他应用程序(例如 Modo Blender )使用类似的交互范例。