簡單操作 Surface Dial

Surface Dial 是 2016 微軟推出的新設備,可以讓 App 跟它整合帶入更多除了 mouse, touch, pen 以外的操作體驗,目前有支援的 App 可以參考 Microsoft Surface Studio | App Partners 。 如果想要在自己的 App 也加入呢?該篇將介紹怎麽整合。

Surface Dial 支援 press 與hold, click, rotate 三種手勢:

  • press 與 hold: 負責呈現該 App 或系統預設有支援 commands 的 menu。預設 menu 出現在畫面的中間或是 Dial 擺放在 screen 上的位置,可以隨意移動。出現 menu 的時候,轉動 Dial 可以切換可選用的 command,而 click 的動作代表選擇那個 command。
  • rotate: Dial 被設計提供旋轉操作方式來選擇 command 或是調整 command 中的互動。
  • click: 代表選擇 menu 中的項目或是 App 自定義的項目。也是模擬 left mouse button。
 
menu 是按照 App 所定義的, As with all Windows input devices, you can customize and tailor the Surface Dial interaction experience to suit the functionality in your apps.

顯示的方式根據 Surface Dial 是否有放在 screen 上有不同的顯示方式,參考如下:

系統預設提供的 commands 有:system volume, scroll, zoom in/out, and undo/redo,在 Desktop 上還可以控制 system brightness;在播放音樂的話預設是 previous 與 next 。 更可以整合 Windows Ink Platform 的 controls (InkCanvasInkToolbar),詳細的説明可以參考<Surface Dial interactions>。 搭配 RadiaController 開發 App 專屬的 Dial commends menu。

代表一個專門的輸入設備或配件。重要的屬性跟事件如下:

Type Name Description
Method CreateForCurrentView Instantiates a radial controller object and binds it to the active application.
  IsSupported Retrieves a value that indicates whether the radial controller is supported by the system.
Property Menu Gets a reference to the popup menu of contextual app commands associated with the radial controller. 可以加入自定義的 RadialControllerMenuItem
  RotationResolutionInDegrees Gets or sets the minimum rotational value required to trigger a RotationChanged event. (default is 10 degress)
  UseAutomaticHapticFeedback
Gets or sets whether haptic feedback on the input device or accessory (represented by the radial controller object)is enabled.
設定是否啓用輸入設備或配件的觸覺回饋. 一般建議當 Resolution degrees 設定值小於 5 時應該 disable 該屬性。
Event ButtonClicked Occurs when the radial controller button is activated.
  ControlAcquired Occurs when the app associated with the radial controller is brought to the foreground.
  ControlLost Occurs when the app associated with the radial controller is sent to the background.
  RotationChanged Occurs when the radial controller is rotated. 捕捉該事件調整用戶選擇對象的值。此為主要事件一定要處理。
  ScreenContactContinued Occurs after ScreenContactStarted, while contact continues to be detected between the input device or accessory (represented by the radial controller object) and the digitizer surface.
  ScreenContactEnded Occurs when the input device or accessory (represented by the radial controller object) that is in contact with the digitizer surface is removed (or is no longer detected).
  ScreenContactStarted
Occurs when initial contact is detected between the input device or accessory (represented by the radial controller object) and the digitizer surface.
當 Dial 被 press 時設備如果在 screen 上就會觸發這個事件。

[範例程式] 利用 Dial 控制圖片的透明程度。 1. XAML 裏面放入一個 Slider 跟 Image 分別顯示 Dial 調整的幅度跟圖片結果。


<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="0" Margin="10,5">
         <Slider x:Name="SliderOpacity" Minimum="0" Maximum="100" Header="Opacity" Margin="0,10" Value="100" />
    </StackPanel>
    <Image Grid.Row="1" x:Name="ImageControl" Source="ms-appx:///Assets/sample.jpg" Stretch="UniformToFill" />
</Grid>

2. 取得 RadialController 並加入一個專用的 item 。


RadialController dialController;

private void CreateDialControllerMenu()
{
    dialController = RadialController.CreateForCurrentView();

    // 建立一個 icon 給 menu item 使用
    RandomAccessStreamReference icon =
  RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/StoreLogo.png"));

    // 建立 menu item 并且設定 icon 跟 display text
    RadialControllerMenuItem opacityItem = RadialControllerMenuItem.CreateFromIcon("Opacity", icon);
    opacityItem.Invoked += MenuItem_Invoked;

    // 將 menu item 加入到 RadialController menu
    dialController.Menu.Items.Add(opacityItem); 

    // 處理 RotationChanged 的事件
    dialController.ButtonClicked += Controller_ButtonClicked;
    dialController.RotationChanged += Controller_RotationChanged;
}

如果加入多個 item 的話,在建立 RadialControllerMenuItem 時加入 Invoke 事件捕捉目前用戶使用的是哪一個 item。 3. 處理 RotationChanged 調整圖片的透明度


private void Controller_RotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
{
    // 更新 Slider 的 value 與調整 Image 的透明度
    SliderOpacity.Value += args.RotationDeltaInDegrees;
    ImageControl.Opacity = SliderOpacity.Value / 100;
}

這裏要注意,dial 預設的 RotationDeltaInDegrees 是 10 (往右轉(+10);往左轉(-10))。 [補充]

  • 如果想調整預設 Dial 的 commands, 可以到 Windows Settings -> Devices -> Wheel page, 如下圖:

  • 自定義 App 支援 Dial 的行為有幾個 guide 需要注意:
    1. Ensure your tools correspond to the current context
    2. Minimize the number of app tools as much as possible 把重點功能提供在 Dial 上面讓用戶在對象上可以快速使用功能,或是提供讓用戶可以自訂的選項。
    3. Dynamically update the collection of tools 因爲 Dial menu items 不支援 disable state,所以建議根據目前 user 在的内容上動態加入或移除 tools (including built-in, default tools)。加入項目時要自己確認是否已經有存在的項目以免重複。
    4. Don’t remove the built-in system volume setting tool volume control 是 always user 需要的,因為可能同時聼音樂邊使用你的 App,所以不要拿掉 volume control 與 next track control (next track control 由系統發現有在 media 正在播放就會加入)
    5. Be consistent with menu organization
    6. Provide high-quality icons consistent with the built-in icons提供高畫質的 64x46 pixel PNG image (44x44 是最小需求) 確定背景色要是透明
      一個白色的圖示應該有一個黑色的輪廓,可見在高對比模式下
    7. Use concise and descriptive names
    8. Apps should respond when the Surface Dial is detected on-screen

====== 新的設備如果有機會購買到的話,快來試看看吧!希望對大家有所幫助。謝謝。 References