Share via


使用方向感應器

了解如何使用方向感應器來判斷裝置方向。

重要 API

必要條件

您應該熟悉可擴充應用程式標記語言 (XAML)、Microsoft Visual C# 和事件。

您使用的裝置或模擬器必須支援方向感應器。

建立 OrientationSensor 應用程式

方向感應器是數種類型的環境感應器之一,可讓應用程式回應裝置方向的變更。

Windows.Devices.Sensors 命名空間包含兩種不同類型的方向感應器 API:OrientationSensorSimpleOrientation。 雖然這兩個感應器都是方向感應器,但該詞彙會超載,而且用於非常不同的用途。 不過,由於兩者都是方向感應器,因此本文涵蓋兩者。

OrientationSensor API 用於兩個取得四元數和旋轉矩陣的 3D 應用程式。 四元數最容易理解為點 [x,y,z] 繞任意軸的旋轉 (與旋轉矩陣相反,旋轉矩陣表示繞三個軸的旋轉)。 四元數背後的數學相當異國情調,因為它涉及複數的幾何屬性和虛數的數學屬性,但使用它們很簡單,DirectX 之類的架構支持它們。 複雜的 3D 應用程式可以使用 Orientation 感應器來調整使用者的視角。 此感應器結合了加速計、陀螺儀和指南針的輸入。

SimpleOrientation API 可用來判斷目前裝置方向的定義,例如直向向上、直向向下、橫向向左和向右橫向。 它也可以偵測裝置是否正視或向下。 此感應器不會傳回如「直向向上」或「橫向向左」等屬性,而是傳迴旋轉值:「未旋轉」、「Rotated90DegreesCounterclockwise」等等。 下表會將通用方向屬性對應至對應的感應器讀數。

方向 對應的感應器讀取
直向向上 NotRotated
橫向 (左) Rotated90DegreesCounterclockwise
直向向下 Rotated180DegreesCounterclockwise
橫向 (右) Rotated270DegreesCounterclockwise

注意

更完整的實作,請查閱:

指示

  • 建立一個新項目,從 Visual C# 項目範本中選擇一個空白應用程式 (通用 Windows)

  • 開啟專案的 MainPage.xaml.cs 檔案,並以下列程式碼取代現有的程式碼。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;

    using Windows.UI.Core;
    using Windows.Devices.Sensors;

    // The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?linkid=234238

    namespace App1
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            private OrientationSensor _sensor;

            private async void ReadingChanged(object sender, OrientationSensorReadingChangedEventArgs e)
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    OrientationSensorReading reading = e.Reading;

                    // Quaternion values
                    txtQuaternionX.Text = String.Format("{0,8:0.00000}", reading.Quaternion.X);
                    txtQuaternionY.Text = String.Format("{0,8:0.00000}", reading.Quaternion.Y);
                    txtQuaternionZ.Text = String.Format("{0,8:0.00000}", reading.Quaternion.Z);
                    txtQuaternionW.Text = String.Format("{0,8:0.00000}", reading.Quaternion.W);

                    // Rotation Matrix values
                    txtM11.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M11);
                    txtM12.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M12);
                    txtM13.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M13);
                    txtM21.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M21);
                    txtM22.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M22);
                    txtM23.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M23);
                    txtM31.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M31);
                    txtM32.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M32);
                    txtM33.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M33);
                });
            }

            public MainPage()
            {
                this.InitializeComponent();
                _sensor = OrientationSensor.GetDefault();

                // Establish the report interval for all scenarios
                uint minReportInterval = _sensor.MinimumReportInterval;
                uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
                _sensor.ReportInterval = reportInterval;

                // Establish event handler
                _sensor.ReadingChanged += new TypedEventHandler<OrientationSensor, OrientationSensorReadingChangedEventArgs>(ReadingChanged);
            }
        }
    }

您必須使用您提供項目的名稱,重新命名上一個代碼段中的命名空間。 例如,如果您已建立名為 AccelerometerCS 的專案,則會將 namespace App1 取代為 namespace OrientationSensorCS

  • 開啟檔案 MainPage.xaml 並將原始內容替換為以下 XML。
        <Page
        x:Class="App1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">

        <Grid x:Name="LayoutRoot" Background="Black">
            <TextBlock HorizontalAlignment="Left" Height="28" Margin="4,4,0,0" TextWrapping="Wrap" Text="M11:" VerticalAlignment="Top" Width="46"/>
            <TextBlock HorizontalAlignment="Left" Height="23" Margin="4,36,0,0" TextWrapping="Wrap" Text="M12:" VerticalAlignment="Top" Width="39"/>
            <TextBlock HorizontalAlignment="Left" Height="24" Margin="4,72,0,0" TextWrapping="Wrap" Text="M13:" VerticalAlignment="Top" Width="39"/>
            <TextBlock HorizontalAlignment="Left" Height="31" Margin="4,118,0,0" TextWrapping="Wrap" Text="M21:" VerticalAlignment="Top" Width="39"/>
            <TextBlock HorizontalAlignment="Left" Height="24" Margin="4,160,0,0" TextWrapping="Wrap" Text="M22:" VerticalAlignment="Top" Width="39"/>
            <TextBlock HorizontalAlignment="Left" Height="24" Margin="8,201,0,0" TextWrapping="Wrap" Text="M23:" VerticalAlignment="Top" Width="35"/>
            <TextBlock HorizontalAlignment="Left" Height="23" Margin="4,234,0,0" TextWrapping="Wrap" Text="M31:" VerticalAlignment="Top" Width="39"/>
            <TextBlock HorizontalAlignment="Left" Height="28" Margin="4,274,0,0" TextWrapping="Wrap" Text="M32:" VerticalAlignment="Top" Width="46"/>
            <TextBlock HorizontalAlignment="Left" Height="21" Margin="4,322,0,0" TextWrapping="Wrap" Text="M33:" VerticalAlignment="Top" Width="39"/>
            <TextBlock x:Name="txtM11" HorizontalAlignment="Left" Height="19" Margin="43,4,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM12" HorizontalAlignment="Left" Height="23" Margin="43,36,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM13" HorizontalAlignment="Left" Height="15" Margin="43,72,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM21" HorizontalAlignment="Left" Height="20" Margin="43,114,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM22" HorizontalAlignment="Left" Height="19" Margin="43,156,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM23" HorizontalAlignment="Left" Height="16" Margin="43,197,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM31" HorizontalAlignment="Left" Height="17" Margin="43,230,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM32" HorizontalAlignment="Left" Height="19" Margin="43,270,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock x:Name="txtM33" HorizontalAlignment="Left" Height="21" Margin="43,322,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
            <TextBlock HorizontalAlignment="Left" Height="15" Margin="194,8,0,0" TextWrapping="Wrap" Text="Quaternion X:" VerticalAlignment="Top" Width="81"/>
            <TextBlock HorizontalAlignment="Left" Height="23" Margin="194,36,0,0" TextWrapping="Wrap" Text="Quaternion Y:" VerticalAlignment="Top" Width="81"/>
            <TextBlock HorizontalAlignment="Left" Height="15" Margin="194,72,0,0" TextWrapping="Wrap" Text="Quaternion Z:" VerticalAlignment="Top" Width="81"/>
            <TextBlock x:Name="txtQuaternionX" HorizontalAlignment="Left" Height="15" Margin="279,8,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="104"/>
            <TextBlock x:Name="txtQuaternionY" HorizontalAlignment="Left" Height="12" Margin="275,36,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="108"/>
            <TextBlock x:Name="txtQuaternionZ" HorizontalAlignment="Left" Height="19" Margin="275,68,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="89"/>
            <TextBlock HorizontalAlignment="Left" Height="21" Margin="194,96,0,0" TextWrapping="Wrap" Text="Quaternion W:" VerticalAlignment="Top" Width="81"/>
            <TextBlock x:Name="txtQuaternionW" HorizontalAlignment="Left" Height="12" Margin="279,96,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="72"/>

        </Grid>
    </Page>

您必須將上一個代碼段中類別名稱的第一個部分取代為應用程式的命名空間。 例如,如果您已建立名為 AccelerometerCS 的專案,則會將 x:Class="App1.MainPage" 取代為 x:Class="OrientationSensorCS.MainPage"。 您也應該將取代 xmlns:local="using:App1"xmlns:local="using:OrientationSensorCS"

  • 按 F5 或選擇偵錯>或開始偵錯來建置、部署和執行應用程式。

應用程式執行後,您可以透過行動裝置或使用模擬器工具來更改方向。

  • 返回 Visual Studio 並按 Shift+F5,或選取偵錯>停止偵錯以停止應用程式,以停止應用程式。

說明

前面的範例演示了您只需編寫很少的程式碼即可將方向感應器輸入整合到您的應用程式中。

應用程式在 MainPage 方法中與預設方向感應器建立連接。

_sensor = OrientationSensor.GetDefault();

應用程式會在 MainPage 方法內建立報表間隔。 此程式碼會擷取裝置支援的最小間隔,並將它與要求間隔 16 毫秒 (大約 60-Hz 重新整理速率) 進行比較。 如果支援的最小間隔大於要求的間隔,程式碼會將值設定為最小值。 否則,它會將值設定為要求的間隔。

uint minReportInterval = _sensor.MinimumReportInterval;
uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
_sensor.ReportInterval = reportInterval;

新的感應器資料會在 ReadingChanged 方法中擷取。 每次感應器驅動程式收到來自感應器的新資料時,都會使用此事件處理常式將值傳遞給您的應用程式。 應用程式會在下一行註冊此事件處理常式。

_sensor.ReadingChanged += new TypedEventHandler<OrientationSensor,
OrientationSensorReadingChangedEventArgs>(ReadingChanged);

這些新值會寫入專案 XAML 中找到的 TextBlock。

建立 SimpleOrientation 應用程式

本節分為兩個小節。 第一個子區段會引導您完成從頭開始建立簡單方向應用程式所需的步驟。 下列小節說明您剛建立的應用程式。

指示

  • 建立一個新項目,從 Visual C# 項目範本中選擇一個空白應用程式 (通用 Windows)

  • 開啟專案的 MainPage.xaml.cs 檔案,並以下列程式碼取代現有的程式碼。

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;

    using Windows.UI.Core;
    using Windows.Devices.Sensors;
    // The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?linkid=234238

    namespace App1
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            // Sensor and dispatcher variables
            private SimpleOrientationSensor _simpleorientation;

            // This event handler writes the current sensor reading to
            // a text block on the app' s main page.

            private async void OrientationChanged(object sender, SimpleOrientationSensorOrientationChangedEventArgs e)
            {
                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    SimpleOrientation orientation = e.Orientation;
                    switch (orientation)
                    {
                        case SimpleOrientation.NotRotated:
                            txtOrientation.Text = "Not Rotated";
                            break;
                        case SimpleOrientation.Rotated90DegreesCounterclockwise:
                            txtOrientation.Text = "Rotated 90 Degrees Counterclockwise";
                            break;
                        case SimpleOrientation.Rotated180DegreesCounterclockwise:
                            txtOrientation.Text = "Rotated 180 Degrees Counterclockwise";
                            break;
                        case SimpleOrientation.Rotated270DegreesCounterclockwise:
                            txtOrientation.Text = "Rotated 270 Degrees Counterclockwise";
                            break;
                        case SimpleOrientation.Faceup:
                            txtOrientation.Text = "Faceup";
                            break;
                        case SimpleOrientation.Facedown:
                            txtOrientation.Text = "Facedown";
                            break;
                        default:
                            txtOrientation.Text = "Unknown orientation";
                            break;
                    }
                });
            }

            public MainPage()
            {
                this.InitializeComponent();
                _simpleorientation = SimpleOrientationSensor.GetDefault();

                // Assign an event handler for the sensor orientation-changed event
                if (_simpleorientation != null)
                {
                    _simpleorientation.OrientationChanged += new TypedEventHandler<SimpleOrientationSensor, SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged);
                }
            }
        }
    }

您必須使用您提供項目的名稱,重新命名上一個代碼段中的命名空間。 例如,如果您已建立名為 AccelerometerCS 的專案,則會將 namespace App1 取代為 namespace SimpleOrientationCS

  • 開啟檔案 MainPage.xaml 並將原始內容替換為以下 XML。
    <Page
        x:Class="App1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">

        <Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
            <TextBlock HorizontalAlignment="Left" Height="24" Margin="8,8,0,0" TextWrapping="Wrap" Text="Current Orientation:" VerticalAlignment="Top" Width="101" Foreground="#FFF8F7F7"/>
            <TextBlock x:Name="txtOrientation" HorizontalAlignment="Left" Height="24" Margin="118,8,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="175" Foreground="#FFFEFAFA"/>

        </Grid>
    </Page>

您必須將上一個代碼段中類別名稱的第一個部分取代為應用程式的命名空間。 例如,如果您已建立名為 AccelerometerCS 的專案,則會將 x:Class="App1.MainPage" 取代為 x:Class="SimpleOrientationCS.MainPage"。 您也應該將取代 xmlns:local="using:App1"xmlns:local="using:SimpleOrientationCS"

  • 按 F5 或選擇偵錯>或開始偵錯來建置、部署和執行應用程式。

應用程式執行後,您可以透過行動裝置或使用模擬器工具來更改方向。

  • 返回 Visual Studio 並按 Shift+F5,或選取偵錯>停止偵錯以停止應用程式,以停止應用程式。

說明

前面的範例演示了您只需編寫很少的程式碼即可將簡單方向感應器輸入整合到您的應用程式中。

應用程式會使用 MainPage 方法中的預設感應器建立連線。

_simpleorientation = SimpleOrientationSensor.GetDefault();

新的感應器資料會在 OrientationChanged 方法中擷取。 每次感應器驅動程式收到來自感應器的新資料時,都會使用此事件處理常式將值傳遞給您的應用程式。 應用程式會在下一行註冊此事件處理常式。

_simpleorientation.OrientationChanged += new TypedEventHandler<SimpleOrientationSensor,
SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged);

這些新值會寫入專案 XAML 中找到的 TextBlock。

<TextBlock HorizontalAlignment="Left" Height="24" Margin="8,8,0,0" TextWrapping="Wrap" Text="Current Orientation:" VerticalAlignment="Top" Width="101" Foreground="#FFF8F7F7"/>
 <TextBlock x:Name="txtOrientation" HorizontalAlignment="Left" Height="24" Margin="118,8,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="175" Foreground="#FFFEFAFA"/>