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。
顯示的方式根據 Surface Dial 是否有放在 screen 上有不同的顯示方式,參考如下:
系統預設提供的 commands 有:system volume, scroll, zoom in/out, and undo/redo,在 Desktop 上還可以控制 system brightness;在播放音樂的話預設是 previous 與 next 。 更可以整合 Windows Ink Platform 的 controls (InkCanvas 與 InkToolbar),詳細的説明可以參考<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 需要注意:
-
- Ensure your tools correspond to the current context
- Minimize the number of app tools as much as possible 把重點功能提供在 Dial 上面讓用戶在對象上可以快速使用功能,或是提供讓用戶可以自訂的選項。
- Dynamically update the collection of tools 因爲 Dial menu items 不支援 disable state,所以建議根據目前 user 在的内容上動態加入或移除 tools (including built-in, default tools)。加入項目時要自己確認是否已經有存在的項目以免重複。
- Don’t remove the built-in system volume setting tool volume control 是 always user 需要的,因為可能同時聼音樂邊使用你的 App,所以不要拿掉 volume control 與 next track control (next track control 由系統發現有在 media 正在播放就會加入)
- Be consistent with menu organization
- Provide high-quality icons consistent with the built-in icons提供高畫質的 64x46 pixel PNG image (44x44 是最小需求) 確定背景色要是透明
一個白色的圖示應該有一個黑色的輪廓,可見在高對比模式下
- Use concise and descriptive names
- Apps should respond when the Surface Dial is detected on-screen
- RadialControllerConfiguration 負責設定詳細的 RadialController Menu,例如:加入 menu item 或是清除。 有一個特別的 event: TrySelectDefaultMenuItem 可直接由 code 的方式選擇到 menu 裏面的項目。
- RadialControllerMenuItem 代表在 menu 裏面的一個 single custom tool 。
====== 新的設備如果有機會購買到的話,快來試看看吧!希望對大家有所幫助。謝謝。 References:
- Surface Dial interactions
- RadialController class
- Using the Surface Dial as a debug tool
- 新式應用程式 - 在 UWP 中運用音訊
- Audio graphs