Eine neue Interaktionsmöglichkeit für Windows: das Surface Dial


surfacedial_5_featurepanelrightalign_v1
Gleichzeitig mit Windows Ink im Windows Anniversary Update hat Microsoft die Eingabe per Stift und Touch eingeführt – der Beginn einer revolutionären Änderung in der Interaktion mit Windows. In diesem Blogeintrag wird besprochen, wie Sie die APIs, mit denen Sie für die Touch-Eingabe bereits vertraut sind, benutzen können, um gleichzeitig mit der Verarbeitung von Stift- und Touch-Eingaben umzugehen. Angesichts der kürzlich erfolgten Microsoft-Hardwareankündigungen möchten wir Ihnen eine weitere Innovation bei der Eingabe vorstellen: das Surface Dial.

Mit dem Surface Dial wird in Windows eine völlig neue Interaktionsmöglichkeit eingeführt. Beim Surface Dial handelt es sich um eine neue Kategorie von Eingabegeräten, die wir als radiale Controller bezeichnen. Für den Kreativprozess stellt dies ein revolutionäres neues Tool dar. Da Tools und Tastenkürzel stets zur Hand sind, können Benutzer sich mit dem Surface Dial auf das konzentrieren, was am Wichtigsten ist. Mit einfachen Bewegungen lassen sich Bilder bearbeiten, die Lautstärke einstellen, Farbtöne verändern und vieles mehr. Mit einem Surface Dial in der einen Hand und einem Surface Pen in der anderen wird der Kreativprozess produktiver und angenehmer. Außerdem können Sie das Surface Dial direkt auf dem Bildschirm eines Surface Studios ablegen und haben damit Ihre Lieblingstools – wie etwa die Farbauswahl oder das Lineal – zur Hand und auf Ihrem digitalen Zeichentisch in griffbereiter Nähe.

Wenn das Surface Dial über Bluetooth mit einem Windows 10 Anniversary Update-PC gekoppelt wird, bietet es Anwendern ein breites Angebot an neuen Benutzererfahrungen und eröffnet völlig neue Möglichkeiten. Ziel dieses Blogs ist es, Ihnen Schritt für Schritt darzustellen, wie Sie in Ihrer Anwendung eigene Benutzererfahrungen für das Surface Dial entwickeln können.

Wir stellen vor: der Radial Controller

Bei Windows stellt das Surface Dial eine völlig neue Sorte Eingabegerät im System dar, das wir als Radial Controller bezeichnen. Passend zu dieser nagelneuen Eingabemethode hat Windows eine integrierte Benutzererfahrung entwickelt, die es Anwendern erleichtert, Einstellungen an ihre individuellen Anforderungen anzupassen und das zu tun, was sie lieben – und das mit nur einem Dreh des Dials.

Das Surface Dial erkennt eine einfache Gruppe von Bewegungen: Es kann gedreht werden, wie eine Taste gedrückt werden und auf dem Bildschirm des Surface Studios abgelegt werden. Diese Bewegungen sind Benutzern unmittelbar vertraut und daher leicht zu erlernen. Wenn man das Surface Dial wie eine Taste drückt und hält, erscheint ein Menü mit ansteuerbaren Tools. Die Tools bieten vielfältige Funktionen, durch die die Arbeitsabläufe von Benutzern verbessert werden und es ihnen ermöglicht werden soll, sich von ihrer kreativen Arbeit nicht ablenken zu lassen. Sie ermöglichen Blättern und Zoomen, die Lautstärkeregelung, das Abspielen von Medien, Rückgängigmachen und Wiederherstellen, individuell angepasste Tastenkürzel und vieles mehr. Das Surface Dial lässt sich auch mit einem breiten und wachsenden Angebot an Apps von Drittanbietern integrieren, wodurch neue Tools in Windows Ink Workspace, Office, Maps, Groove Music, Sketchable, Bluebeam Revu, Moho 12, Drawboard PDF und mehr verfügbar werden. Mit dem Surface Dial erschließen sich Benutzern neue Funktionen in allen Windows-Apps, was sie dazu anregen wird, herauszufinden, welchen Nutzen das Dial bei ihren Lieblings-Apps entfalten kann. Dank der Erweiterbarkeit, die durch die universelle Windows-Plattform möglich wird, ist es für Ihre App einfach, Benutzern das gewünschte hervorragende Surface Dial-Erlebnis zu bieten.

Als erster und einfachster Ansatz, mit dem Surface Dial Nutzen zu stiften, empfehlen sich die Windows-Inbox-Komponenten, bei denen die Surface Dial-Integration bereits vorinstalliert ist. Für Entwickler, die die Windows Ink-Plattform benutzen, um es ihren Anwendern zu ermöglichen, mit dem Stift zu schreiben, zu zeichnen und kreativ zu sein, füllen die InkCanvas- und InkToolbar-XAML-Steuerelemente das Surface Dial-Menü mit neuen Tools, sodass Benutzer schnell die Attribute der Tinte verändern, die Linienstärke der Tinte beim Schreiben anpassen und das Bildschirmlineal steuern können. So bekommen Sie im Windows Ink-Arbeitsbereich dieselbe ansprechende Surface Dial-Integration wie in den Sketchpad- und Screen Sketch-Apps.

picture2 Bei der Benutzung von InkToolbar und InkCanvas ist die Surface Dial-Integration automatisch miteingeschlossen.

picture3 Während das Bildschirmlineal angezeigt wird, lassen sich mit dem Surface Dial Winkel und Position des Lineals einstellen.

Bei der Medienwiedergabe ermöglicht das Dial dank der Integration mit SystemMediaTransportControls dieselben Möglichkeiten, die Wiedergabe anzuhalten, abzuspielen und Spuren zu überspringen wie bei Groove Music und Spotify.

Für Entwickler, die über die im System bereits vorhandene Standardintegration hinausgehen und etwas wirklich Einmaliges schaffen wollen, ist es mit Windows einfach, dieses Menü über die RadialController-Plattform mit eigenen Tools zu ergänzen. Die universellen RadialController-APIs machen es möglich, eigene Tools für das Surface Dial-Menü zu entwickeln und Dial-Eingaben sowohl von Universal Windows Platform-Apps als auch klassischen Win32-Apps zu verarbeiten. Sie haben die Möglichkeit, auf die auf allen Windows-Geräten verfügbaren Schaltflächen- und Rotationseingaben zu reagieren, oder Sie können einen Schritt weitergehen und immersive Benutzeroberflächen-Erlebnisse dafür entwickeln, wenn das Surface Dial auf dem Surface Studio-Bildschirm aufliegend benutzt wird.

Schauen wir uns zunächst an, was es erfordert, für das Surface Dial eine benutzerdefinierte Tool-Erfahrung zu entwickeln.

Entwicklung eines benutzerdefinierten Tools für das Surface Dial

Benutzerdefinierte Tools für das Surface Dial sind der beste Ansatz, um Anwendern eine ansprechende und vielseitige Dial-Erfahrung zu bieten. Da benutzerdefinierte Tools auf die Anforderungen Ihrer Anwendung zugeschnitten sind, können Sie die Tastenkürzel und Funktionen festlegen, die für den Benutzer am Wichtigsten sind, und sie dem Benutzer an die Hand geben. Durch die Optimierung seiner Arbeitsabläufe und der Integration der App-Benutzeroberfläche kann der Benutzer sich dank Ihres benutzerdefinierten Tools mehr fokussieren und bei der Arbeit, beim Spiel oder bei der Gestaltung mit dem Dial produktiver sein.

Um mit der Entwicklung eines benutzerdefinierten Tools für das Surface Dial zu beginnen, muss als erstes eine Instanz der RadialController-Schnittstelle erstellt werden. Sie wird verwendet, um das Gerät darzustellen und während der Lebensdauer Ihrer Anwendung mit dem Surface Dial-Menü zu interagieren. Über Ihre RadialController-Instanz können Sie auf das RadialControllerMenu zugreifen, das es Ihnen ermöglicht, Ihre eigenen, anwendungsspezifischen Tools in das Surface Dial-Menü hinzuzufügen oder daraus zu entfernen. Über den RadialController bekommen Sie auch Zugriff auf alle Eingabeereignisse für das Surface Dial, sodass Sie für Ihr benutzerdefiniertes Tool ansprechende Benutzererfahrungen erstellen können.

Sehen wir uns an, wie man in einer Beispielanwendung ein benutzerdefiniertes Tool entwickelt. Wir beginnen hier mit einer einfachen Freihandanwendung, die InkCanvas- und InkToolbar-Steuerelemente benutzt, die bereits Surface Dial-Integration zur Veränderung von Freihandattributen und des Lineals bieten.

<Grid x:Name="Container" 
          Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid x:Name="CanvasGrid">
            <InkCanvas x:Name="myCanvas"/>
            <InkToolbar x:Name="myToolbar" 
                        VerticalAlignment="Top" 
                        TargetInkCanvas="{x:Bind myCanvas}" />
        </Grid>
        <StackPanel x:Name="ToolPanel" 
                    HorizontalAlignment="Right" 
                    VerticalAlignment="Top" 
                    Orientation="Vertical" 
                    Width="300" 
                    Background="White" 
                    BorderBrush="Black" 
                    BorderThickness="2">
            <StackPanel>
                <TextBlock Text="Red" Margin="20,5,20,5"/>
                <Slider x:Name="RValue" 
                        LargeChange="1" 
                        Maximum="255" 
                        Margin="20,5,20,5"/>
            </StackPanel>
            <StackPanel>
                <TextBlock Text="Green" Margin="20,5,20,5"/>
                <Slider x:Name="GValue" 
                        LargeChange="1" 
                        Maximum="255" 
                        Margin="20,5,20,5"/>
            </StackPanel>
            <StackPanel>
                <TextBlock Text="Blue" Margin="20,5,20,5"/>
                <Slider x:Name="BValue" 
                        LargeChange="1" 
                        Maximum="255" 
                        Margin="20,5,20,5"/>
            </StackPanel>
            <StackPanel>
                <Grid x:Name="Preview" 
                      Height="100" Width="250" 
                      Margin="0,20,0,20"/>
            </StackPanel>
        </StackPanel>
    </Grid>

Als Nächstes ergänzen wir eine tiefere Integration mit den RadialController-APIs und stellen es so ein, dass das Surface Dial die Hintergrundfarbe kontrolliert. Wir beginnen, indem wir im Menü ein benutzerdefiniertes Tool ergänzen:

RadialController myController;
 
       public MainPage()
       {
           this.InitializeComponent();
           UpdatePreview();
           highlightedItem = RValue;
 
           //Hide our custom tool's UI until it is activated by the Dial
           ToolPanel.Visibility = Visibility.Collapsed;
 
           // Create a reference to the RadialController.
           myController = RadialController.CreateForCurrentView();
 
           // Create a menu item for the custom tool.
           RadialControllerMenuItem myItem =
             RadialControllerMenuItem.CreateFromKnownIcon("Background", RadialControllerMenuKnownIcon.InkColor);
 
           //Add the custom tool's menu item to the menu
           myController.Menu.Items.Add(myItem);
 
           //Create a handler for when the menu item is selected
           myItem.Invoked += MyItem_Invoked;
 
           //Create handlers for button and rotational input
           myController.RotationChanged += MyController_RotationChanged;
           myController.ButtonClicked += MyController_ButtonClicked;
 
           //Remove Scroll/Zoom/Undo tools as app doesn't support them
           RadialControllerConfiguration config = RadialControllerConfiguration.GetForCurrentView();
           config.SetDefaultMenuItems(new RadialControllerSystemMenuItemKind[] { RadialControllerSystemMenuItemKind.Volume });
 
           …
       }
 
       #region Handling RadialController Input
       private void MyItem_Invoked(RadialControllerMenuItem sender, object args)
       {
           //Make RGB panel visible when the custom menu item is invoked
           ToolPanel.Visibility = Visibility.Visible;
       }

picture4

Da wir die InkToolbar benutzt haben, ist das Menü bereits mit Freihandtools aufgefüllt.

picture5

Sie können das neue Tool sehen, das wir hinzugefügt haben.

Die RadialController-API bietet einfache Ereignisse für den Umgang mit Eingaben vom Dial – vom Drücken der Schaltfläche über die Rotation bis hin zur Position auf dem Bildschirm. Im letzten Codeausschnitt haben wir Ereignishandler für die Surface Dial-Eingabeereignisse RotationChanged und ButtonClicked festgelegt. Anhand dieser Ereignisse können wir es einrichten, dass die Eingabe vom Dial die roten, grünen und blauen Werte unseres Hintergrunds verändert:

Slider selectedItem = null;
       FrameworkElement highlightedItem = null;
 
       private void MyController_ButtonClicked(RadialController sender, RadialControllerButtonClickedEventArgs args)
       {
           if(highlightedItem == Preview)
           {
               //Click on the Preview, update the background
               UpdateBackground();
           }
 
           else if (selectedItem != null)
           {
               //Click on a selected slider, unselect the slider
               selectedItem = null;
               UpdateHighlight(highlightedItem);
               //decrease sensitivity to make it more comfortable to navigate between items
               myController.RotationResolutionInDegrees = 10;
           }
 
           else if (selectedItem == null)
           {
               //No selection, select a slider
               UpdateSelection(highlightedItem as Slider);
               //increase sensitivity to make it easier to change slider value
               myController.RotationResolutionInDegrees = 1;
           }
       }
 
       private void MyController_RotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
       {
           if (selectedItem != null)
           {
               //Change the value on the slider
               selectedItem.Value += args.RotationDeltaInDegrees;
               UpdatePreview();
           }
           else if(args.RotationDeltaInDegrees > 0)
           {
               //Rotation is to the right, change the highlighted item accordingly
               if (highlightedItem == RValue)
               {
                   UpdateHighlight(GValue);
               }
               else if (highlightedItem == GValue)
               {
                   UpdateHighlight(BValue);
               }
               else if (highlightedItem == BValue)
               {
                   UpdateHighlight(Preview);
               }
           }
           else if (args.RotationDeltaInDegrees < 0)
           {
               //Rotation is to the left, change the highlighted item accordingly
               if (highlightedItem == GValue)
               {
                   UpdateHighlight(RValue);
               }
               else if (highlightedItem == BValue)
               {
                   UpdateHighlight(GValue);
               }
               else if (highlightedItem == Preview)
               {
                   UpdateHighlight(BValue);
               }
           }
       }
 
       private void UpdateHighlight(FrameworkElement element)
       {
           StackPanel parent;
 
           //Remove highlight state from previous element
           if (highlightedItem != null)
           {
               parent = highlightedItem.Parent as StackPanel;
               parent.BorderThickness = new Thickness(0);
           }
 
           //Update highlight state for new element
           highlightedItem = element;
 
           parent = highlightedItem.Parent as StackPanel;
           parent.BorderBrush = new SolidColorBrush(Windows.UI.Colors.Black);
           parent.BorderThickness = new Thickness(2);
       }
        
       private void UpdateSelection(Slider element)
       {
           selectedItem = element;
 
           //Update selection state for selected slider
           StackPanel parent = element.Parent as StackPanel;
           parent.BorderBrush = new SolidColorBrush(Windows.UI.Colors.Cyan);
           parent.BorderThickness = new Thickness(4);
       }
        
       private void UpdatePreview()
       {
           Windows.UI.Color selectedColor = new Windows.UI.Color();
           selectedColor.A = 255;
           selectedColor.R = (byte) RValue.Value;
           selectedColor.G = (byte) GValue.Value;
           selectedColor.B = (byte) BValue.Value;
 
           Preview.Background = new SolidColorBrush(selectedColor);
       }
 
       private void UpdateBackground()
       {
           CanvasGrid.Background = Preview.Background;
       }

picture6

Wenn unser benutzerdefiniertes Tool ausgewählt ist, wird die Benutzeroberfläche des Tools sichtbar. Durch Rotation navigiert man im Menü, und indem man auf einen Farbwert klickt, lässt sich dieser verändern.picture7

Wenn Sie eine Farbe gefunden haben, die Ihnen gefällt, verändert sich durch Klicken auf das Vorschaubild die Hintergrundfarbe zu derjenigen, die sie individuell gestaltet haben.

Abgesehen davon, dass Sie konfigurieren können, wie die Rotation mit der Anwendung interagiert, geben Ihnen die RadialController-APIs auch die Möglichkeit zu beeinflussen, wie die Rotation an die App weitergegeben und vom Benutzer empfunden wird. Sie können die Eigenschaft RotationResolutionInDegrees benutzen, um zu konfigurieren, wie feinstufig die Sensibilität oder Auflösung eingestellt ist. Mit der UseAutomaticHapticFeedback-Eigenschaft können Sie festlegen, ob das haptische Feedback aktiviert oder deaktiviert ist. Im vorherigen Beispiel wurde es viel leichter, Schieberegler zu verstellen, nachdem die Rotation bei der Veränderung eines der RGB-Werte sensibler eingestellt wurde. Wenn nichts Anderes festgelegt ist, liegt der Standardwert für die Rotationssensibilität bei 10 Grad.

Umgang mit On-Screen-Eingaben bei Surface Studio

Wie zuvor erwähnt, gibt es zwei Modi für ein radiales Steuerungsgerät: Off-Screen und On-Screen. Wenn das Surface Dial auf dem Bildschirm des Surface Studios aufliegt, holt sich die RadialController-API den Ort und die Grenzen des Kontaktpunktes, sodass Sie umfangreichere und immersivere Erfahrungen für die Benutzer entwickeln können.

Wenn das Surface Dial im On-Screen-Modus benutzt wird, können Sie wunderschöne Benutzeroberflächen entwickeln, die um das Dial herum dargestellt werden und dem Anwender umfassendere Informationen über die Interaktionen zur Verfügung stellen, die er mit dem Dial beeinflussen kann. Dies erlaubt es dem Benutzer, sich auf die Steuerung und Platzierung seiner Hände zu konzentrieren, ohne sich um andere Menüs oder Steuerungsmöglichkeiten kümmern zu müssen. Se hen Sie sich zum Beispiel die umfangreiche Farbpalette an, die von den Technikern bei Sketchable entwickelt wurde, oder das von StaffPad entwickelte schnelle Menü zum Einfügen, mit dem Benutzer schnell häufige Notenschrift-Markups hinzufügen können.picture8picture9

Um das Ganze einen Schritt weiterzuführen, können Sie auch Kontextinformationen über die Absicht des Benutzers aus der On-Screen-Position ablesen, die dazu beitragen können, Ihre benutzerdefinierten Tools überzeugender werden zu lassen. Dies lässt sich z.B. darin erkennen, wie das Surface Dial im Sketchpad von Windows Ink Workspace das Bildschirmlineal führt und verwaltet. Die Techniker von Bluebeam und Drawboard verfolgen mit ihrem geteilten Zoom und Lineal einen ähnlichen Ansatz.

Ausgehend von dem oben beschriebenen Beispiel können wir die On-Screen-Position benutzen, um es für den Benutzer leichter erkennbar zu machen, welche Wirkungen seine Farbänderungen haben. Die relevante Benutzeroberfläche kann in der Nähe der On-Screen-Position des Surface Dials statt in einer Bildschirmecke dargestellt werden. Mit den ScreenContact*-Ereignissen können wir feststellen, wo sich das Surface Dial befindet, und unsere Benutzeroberfläche entsprechend aktualisieren:

bool isRightHanded;
 
public MainPage()
{
    …
 
    //Query the user’s handedness
    Windows.UI.ViewManagement.UISettings settings = new Windows.UI.ViewManagement.UISettings();
    isRightHanded = settings.HandPreference == Windows.UI.ViewManagement.HandPreference.RightHanded;
 
    //Create handlers for when RadialController provides an on-screen position
    myController.ScreenContactStarted += MyController_ScreenContactStarted;
    myController.ScreenContactContinued += MyController_ScreenContactContinued;
    myController.ScreenContactEnded += MyController_ScreenContactEnded;
 
}
 
private void MyController_ScreenContactStarted(RadialController sender, RadialControllerScreenContactStartedEventArgs args)
{
    UpdatePanelLocation(args.Contact);
}
 
private void MyController_ScreenContactContinued(RadialController sender, RadialControllerScreenContactContinuedEventArgs args)
{
    UpdatePanelLocation(args.Contact);
}
 
private void MyController_ScreenContactEnded(RadialController sender, object args)
{
    ResetPanelLocation();
}
 
private void UpdatePanelLocation(RadialControllerScreenContact contact)
{
    //When an on-screen position is provided, apply a transform to the panel
    TranslateTransform x = new TranslateTransform();
    if (isRightHanded)
    {
        //Render to the right of the RadialController
        x.X = contact.Position.X + contact.Bounds.Width / 2 + 50;
    }
    else
    {
        //Render to the left of the RadialController
        x.X = contact.Position.X - contact.Bounds.Width / 2 - 50 - ToolPanel.Width;
    }
    x.Y = contact.Position.Y - 200;
    ToolPanel.RenderTransform = x;
    ToolPanel.HorizontalAlignment = HorizontalAlignment.Left;
}
private void ResetPanelLocation()
{
    //When an on-screen position is not provided, clear the transform on the panel
    ToolPanel.RenderTransform = null;
    ToolPanel.HorizontalAlignment = HorizontalAlignment.Right;
}

Beim Umgang mit On-Screen-Eingaben sollten Sie im Auge behalten, ob Ihre Anwendung einen Fokus für Surface Dial-Eingaben hat. Wenn Ihre Anwendung minimiert ist, eine andere Anwendung in den Vordergrund gerückt oder wenn das Surface Dial-Menü geöffnet wird, verliert Ihre Anwendung den Eingabefokus und Sie müssen sicherstellen, dass Ihre On-Screen-Benutzeroberfläche entsprechend reagiert. Andererseits kann, wenn Ihre App in den Vordergrund gebracht und der Fokus wiederhergestellt wird, das Surface Dial bereits auf dem Surface Studio-Bildschirm abgelegt sein, und es wird kein ScreenContactStarted-Ereignis gemeldet. Hier ein Beispiel, wie man beim Surface Dial mit Fokusänderungen umgehen kann:

public MainPage()
    {
        …
 
        //Create handlers for when RadialController focus changes
        myController.ControlAcquired += MyController_ControlAcquired;
        myController.ControlLost += MyController_ControlLost;
    }
 
 
    private void MyController_ControlAcquired(RadialController sender, RadialControllerControlAcquiredEventArgs args)
    {
        //Ensure tool panel is rendered at the correct location when focus is gained
        if (args.Contact != null)
        {
            UpdatePanelLocation(args.Contact);
        }
 
        ToolPanel.Visibility = Visibility.Visible;
    }
 
    private void MyController_ControlLost(RadialController sender, object args)
    {
        //Hide tool panel when focus is lost
        ToolPanel.Visibility = Visibility.Collapsed;
        ResetPanelLocation();
    }

Anhand Ihrer neu erworbenen Kenntnisse über RadialController-APIs können Sie jetzt das Surface Dial in Ihre Anwendung integrieren, mit Eingaben umgehen und das Systemmenü entsprechend Ihren Anforderungen konfigurieren. Sie können eine riesige Anzahl ansprechender Features für Ihre Benutzer entwickeln – von der einfachen Änderung von Werten und Eigenschaften bis hin zu komplexen On-Screen-Benutzeroberflächen für Surface Dial-Nutzer mit Surface Studio.

Weitere Informationen über UX Design und Best Practices mit Dial finden Sie im Surface Dial Development Overview. Den gesamten in diesem Projekt benutzten Quellcode finden Sie auf GitHub.

Surface Dial und die RadialController-Plattform stellen für Microsoft einen neuen Investitionsbereich dar. Einer der wichtigsten Verbesserungsansätze für die Plattform – und eine Vorgehensweise, um sie flexibler und leistungsfähiger werden zu lassen – besteht darin, dass wir unsere Entwickler-Community um Feedback bitten. Sollten Sie Fragen oder Hinweise bezüglich der Entwicklung für das Surface Dial haben, schicken Sie uns bitte eine Nachricht an RadialController@microsoft.com.

Comments (0)

Skip to main content