数码表冠

「Apple Watch 应用开发系列」数码表冠

数码表冠(Digital Crown)是 Apple Watch 的主要硬件输入,让人们能够翻滚屏幕内容、切换到不同的应用程序以及运用 Siri。

咱们将了解在开发中,怎么操控数码表冠。

需要留意的点

developer.apple.com/design/huma…

依据 Apple Human Interface Guidelines,咱们测验为 watchOS App 增加与数码表冠的交互时,需要留意:

  • 供给视觉反应以响应数码表的交互。例如,当用户运用 Digital Crown 时,挑选器会更改当时显示的值。假如开发中盯梢数码表的旋转,请运用接收到的旋转数据来更新 App 的界面。假如开发中不供给视觉反应,用户可能会以为旋转数码表对 App 有任何影响。

  • 以数码表旋转相对应的速度更新界面。数字表冠的旋转应该让用户对界面进行准确操控。考虑运用旋转速度来确认进行更改的速度。避免用户难以舒适的更新内容。

  • 在 App 中运用默许的触觉反应。例如能够调整表格视图的触觉反应行为,让它们运用线性定位而不是基于行的定位,给用户带来更共同的体会。

Swift & SwiftUI

数码表冠绑定数字

构建项目

咱们创立一个独立的 watchOS App 项目 DigitalCrownDemo。并将 Interface 挑选为 SwiftUI

「Apple Watch 应用开发系列」数码表冠

「Apple Watch 应用开发系列」数码表冠

调整 ContentView.swift 代码,以展现当时数字:

struct ContentView: View {
    @State var number: Float = 0
    var body: some View {
        Text("\(number, specifier: "%.1f")")
    }
}

「Apple Watch 应用开发系列」数码表冠

与数码表冠绑定

调整代码:

Text("\(number, specifier: "%.1f")")
    .focusable()
    .digitalCrownRotation($number)

默许情况下,Text 不会承受焦点,由于它不是交互式元素。 运用 digitalCrownRotation 修饰符时,需要在调用之前立即运用 .focusable()

digitalCrownRotation 一直将绑定作为任何实现 BinaryFloatingPoint 协议的第一个参数,例如 Float、Double。

构建并运转项目。 这一次,当咱们翻滚数字表冠时,咱们会看到数字发生了改变。

「Apple Watch 应用开发系列」数码表冠

约束翻滚规模

通常上述的体现不是咱们期望的。咱们更多的是给定一个可操作的规模。请持续调整代码:

.digitalCrownRotation($number, from: 0.0, through: 10.0)

咱们增加了数码表冠的翻滚约束,从 0.0 ~ 10.0,构建并运转项目,咱们会发现实际情况有些不符合预期:

「Apple Watch 应用开发系列」数码表冠

「Apple Watch 应用开发系列」数码表冠

咱们发现翻滚会显示下限值 -0.1 和上限值 10.1。 咱们有必要再增加一个参数来告诉数码表冠更改值的起伏。

.digitalCrownRotation($number, from: 0, through: 10, by: 0.1)

再次构建并运转项目。 这次咱们会得到预期的结果。

咱们深入看一下这里,持续调整代码,并翻滚数码表冠:

Text("\(number, specifier: "%.1f")")
    .focusable()
    .digitalCrownRotation($number, from: 0, through: 10, by: 0.1)
    .onChange(of: number) { newValue in
        print(newValue)
    }

「Apple Watch 应用开发系列」数码表冠

咱们会发现,绑定特点更新的值咱们幻想的要多得多。同时旋转停止时,绑定特点通常不受by:参数的约束。

假如咱们需要对浮点数执行相等性检查,请运用舍入办法,如下所示:

if (value * 100).rounded(.towardZero) / 100 == 9.75 {
  ...
}

developer.apple.com/documentati…

(5.2).rounded(.towardZero)// 5.0

(5.5).rounded(.towardZero)// 5.0

(-5.2).rounded(.towardZero) // -5.0

(-5.5).rounded(.towardZero)// -5.0

rounded(.towardZero) 向零舍入来将供给的值舍入为整数值。你乘以 10^X 并除以 10^X ,其间 X 是咱们要比较的小数位数。

如案例代码,9.75 有两位小数,咱们的 value 为 9.755,9.755 * 10^2 = 975.5 -> 975 -> 975 / 100 = 9.75,此刻,结果为 true。

灵敏度、循环与触觉反应

有时候,咱们需要调整数字表冠的灵敏度来使交互更加流通。持续调整代码:

「Apple Watch 应用开发系列」数码表冠

构建并运转项目,能够将值从 .high 更改为 .medium 再更改为 .low 并进行体会。当值为 .low时,咱们有必要将数码表冠转动得更多。 这里的默许值为 .high。

关于数字规模停止是有意义的。 在其他情况下咱们可能期望值是循环的,用户能够正常翻滚到 10.0,但假如用户持续翻滚,该值将变为 0.0 并再次核算。 苹果称之为接连翻滚(Continuous scrolling)。 默以为 false:

Text("\(number, specifier: "%.1f")")
    .focusable()
    .digitalCrownRotation(
        $number,
        from: 0,
        through: 10,
        by: 0.1,
        sensitivity: .low,
        isContinuous: true
    )

再次构建并运转。 接连翻滚数字表冠,你会看到数字能够进行循环。

默许情况下,翻滚数码表冠会向用户供给少量触觉反应。 假如对咱们的 App 没有意义,咱们能够运用 相关参数将其封闭:

.digitalCrownRotation(
    $number,
    from: 0,
    through: 10,
    by: 0.1,
    sensitivity: .low,
    isContinuous: true,
    isHapticFeedbackEnabled: false
)

Swift & Storyboard

数码表冠绑定数字

咱们将测验运用 Storyboard 实现上述 Demo。首要创立项目,将 Interface 设置为 Storyboard

「Apple Watch 应用开发系列」数码表冠

拖入 Lable 并进行样式的调整:

「Apple Watch 应用开发系列」数码表冠

「Apple Watch 应用开发系列」数码表冠

InterfaceController.swift 中,进行 numberLabel text 的设置:

class InterfaceController: WKInterfaceController {
    private var number = 0.0
    @IBOutlet var numberLabel: WKInterfaceLabel!
    override func awake(withContext context: Any?) {
        // Configure interface objects here.
        updateUI()
    }
    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
    }
    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
    }
    private func updateUI() {
        numberLabel.setText(String(format: "%.1f", number))
    }
}

「Apple Watch 应用开发系列」数码表冠

InterfaceController 类增加代码,需要为 CrownSequencer 增加代理,并使他聚集:

override func didAppear() {
    crownSequencer.delegate = self
    crownSequencer.focus()
}

WKCrownSequencer 是报告数字表冠当时状态的目标,包含其运动时的旋转速度。咱们不要自己创立此类的实例,而是从当时 InterfaceController 的特点中检索一个表冠序列器目标。

在其能够接收数据之前,咱们有必要调用它的 focus() 办法。在任何给定时间,咱们的界面中只要一个目标能够具有焦点,因此假如咱们的界面还包含挑选器目标或具有可翻滚的场景,您有必要相应地协调焦点的改变。

由于表冠序列器不绑定到特定的界面目标,所以咱们能够将其用作应用程序的一般输入。

WKCrownSequencer 供给两个状态特点:

  • var rotationsPerSecond: Double表冠的旋转速度,以每秒转数为单位。转速是绝对值。不管旋转方向怎么,它一直为正。

  • var isIdle: Bool一个布尔值,指示表冠是否处于停止状态。

WKCrownSequencer 有一个触觉反应特点:

  • var isHapticFeedbackEnabled: Bool { get set } 一个布尔值,用于确认是否启用数码表冠的触觉反应。

持续修改咱们的 InterfaceController 使其符合 WKCrownDelegate 协议。

extension InterfaceController : WKCrownDelegate {}

WKCrownDelegateextension 增加代码:

func crownDidRotate(_ crownSequencer: WKCrownSequencer?, rotationalDelta: Double) {
    print(rotationalDelta)
}
func crownDidBecomeIdle(_ crownSequencer: WKCrownSequencer?) {
    print("End")
}
  • crownDidRotate(rotationalDelta:) 当用户旋转数字表冠时调用。自前次更新以来表冠旋转的量。1.0 的值表明一整圈。值的符号表明旋转的方向,但符号会依据表冠的方向进行调整。正值一直表明向上翻滚手势,而负数表明向下翻滚手势。用户能够在手表的设置中更改数字表冠的方向。

developer.apple.com/documentati…

  • crownDidBecomeIdle() 当用户停止旋转表冠时调用。

developer.apple.com/documentati…

运转项目并查看输出。

「Apple Watch 应用开发系列」数码表冠

调整代码,核算咱们当时需要展现的值:

func crownDidRotate(_ crownSequencer: WKCrownSequencer?, rotationalDelta: Double) {
    number = number + rotationalDelta
    if number < 0.0 { number = 10.0 }
    if number > 10.0 { number = 0.0 }
    updateUI()
}

运转项目,此刻咱们的数码表冠现已和数字绑定:

「Apple Watch 应用开发系列」数码表冠

「Apple Watch 应用开发系列」数码表冠