CI COV License: MIT

摇杆

一个 Swift 中的自定义 UIView,提供一个简单的摇杆界面。该自定义视图由两个 UIImageView 实例组成,一个用于底座,一个用于手柄。当用户移动手柄时,它会根据其相对于摇杆底座的位置报告一个值。报告的信息类型取决于安装的监听器类型。

let monitor: JoyStickViewPolarMonitor = {
    print("\(String(format: "%.2f°", $0.angle)) \(String(format: "%.3f", $0.displacement))")
}

joystick.monitor = .polar(monitor: monitor2)

自 3.0.1 起,还支持使用 Objective-C 代码块作为监听器,但类型安全性略有降低。setPolarMonitorsetXYMonitor 都接受一个闭包,该闭包接受两个 CGFloat 参数,并且不返回值。Objective-C 代码块和 Swift 闭包都可以用于这些方法。自 3.1.0 起,还有一个 tappedBlock 属性,可用于在用户点击摇杆手柄时接收通知。

该视图支持一个选项 (movable),当用户将手柄移动到超过 1.0 的位移时,该视图将移动。当应用程序中摇杆的初始位置对于用户的手指不理想时,这很有用。双击摇杆会将其移回原始位置。

在上面的动画中,有两个摇杆,一个是绿色的,一个是洋红色的。绿色摇杆是固定的,即使触摸动作导致大于 1.0 的位移也不会移动。然而,洋红色摇杆是可移动的,底座跟随触摸动作。对于可移动的摇杆,底座的运动可以选择限制在 movableBounds 属性中的 CGRect 中,就像上面的演示动画中那样,洋红色摇杆无法移出粉红色条带。

其他属性

以下是 JoyStickView 的一些其他可配置功能:

版本

代码

Xcode 工作区包含三个组件:

playground 和应用程序都依赖于 JoyStickView UIView 的框架。

⚠️ 注意: 由于 CocoaPods 的管道,在 Xcode 中编辑时,请打开工作区 JoyStickView.xcworkspace,而不是项目 JoyStickView.xcodeproj

Xcode playground 代码设置了显示环境并安装了两个摇杆,一个是固定的(绿色),另一个是可移动的(黄色)。两个摇杆都在两个标签中报告它们的位置,一个用于角度,另一个用于位移。

JoyStickView.swift 文件定义了摇杆视图和行为。它位于 JoyStickView Swift 包中,以及 CocoaPods 中的 BRHJoyStickView 框架中。在那里你还会找到一个名为 CoreGraphics+Additions.swift 的文件,它包含一些 CoreGraphics 结构体的各种扩展,这些扩展允许 JoyStickView 代码中一些简化的数学表达式。

默认情况下,JoyStickView 类使用在 Assets 容器中找到的两个图像资源。文件夹

两者都以三种分辨率存在,适用于当今的各种 iOS 设备。它们是使用强大的 Opacity 应用程序生成的。Opacity 文档包含在本仓库的 Resources 目录中,用于 JoyStickViewApp 演示应用程序。

要使用你自己的图像,只需使用你想使用的 UIImage 设置 baseImage 和/或 handleImage 属性。

文档

请参阅 代码文档 获取更多信息。

CocoaPods

有一个简单的 CocoaPods 规范文件可用,因此你可以通过将 "BRHJoyStickView" 添加到你的 Podfile 文件并使用 import BRHJoyStickView 导入来添加代码和资源。目前,一切或多或少都可以工作,除了通过 Interface Builder (IB) 指向图像资源将导致无效的 UImage 结果,因为这些文件将无法在 IB 能够找到它们的地方找到。唯一的解决方案是手动定位这些文件并在你的视图加载代码中设置它们。类似以下的内容应该会有所帮助:

extension Bundle {

    /**
     Locate an inner Bundle generated from CocoaPod packaging.

     - parameter name: the name of the inner resource bundle. This should match the "s.resource_bundle" key or
       one of the "s.resoruce_bundles" keys from the podspec file that defines the CocoPod.
     - returns: the resource Bundle or `self` if resource bundle was not found
    */
    func podResource(name: String) -> Bundle {
        guard let bundleUrl = self.url(forResource: name, withExtension: "bundle") else { return self }
        return Bundle(url: bundleUrl) ?? self
    }
}

在你的设置代码中,你需要做类似这样的事情:

    override func viewDidLoad() {
        super.viewDidLoad()
        let bundle = Bundle(for: JoyStickView.self).podResource(name: "BRHJoyStickView")
        joystick.baseImage = UIImage(named: "FancyBase", in: bundle, compatibleWith: nil)
        joystick.handleImage = UIImage(named: "FancyHandle", in: bundle, compatibleWith: nil)
    }

podResource 方法尝试定位一个命名的内部 bundle,如果找不到,则默认为原始 bundle。viewDidLoad 代码将然后在 UIImage 构造函数中使用正确的 bundle 对象。