觸控互動開發人員指南

設計您的應用程式時,期望觸控將成為使用者的主要輸入方法。 如果你使用 WinUI 控制項,觸控板、滑鼠和觸控筆的支援不需要額外程式,因為 WinUI 應用程式會免費提供這些功能。

但是,請記住,針對觸控進行最佳化的 UI 並不總是優於傳統 UI。 兩者都具有技術和應用所特有的優點和缺點。 在轉向觸控優先 UI 的過程中,了解觸控、觸控板、筆/手寫筆、滑鼠和鍵盤輸入之間的核心差異非常重要。

重要 APIMicrosoft。UI。Xaml.InputWindows.UI。核心Windows。Devices.Input

許多裝置都具有多點觸控螢幕,支援使用一根或多根手指 (或觸控觸點) 作為輸入。 觸控接觸及其移動被解釋為觸控手勢和操作以支援各種使用者互動。

Windows app 包含多種觸控輸入處理機制,讓你能打造沉浸式體驗,讓使用者能自信探索。 在這裡,我們會介紹在 Windows app 中使用觸控輸入的基本原理。

觸控互動需要三件事:

  • 觸控式顯示器。
  • 一根或多根手指在該顯示器上的直接接觸 (或接近,如果顯示器具有接近感測器並支援懸停檢測)。
  • 觸控接觸的移動(或其缺乏,根據時間閾值判定)。

觸控感應器提供的輸入資料可以是:

  • 解釋為直接操作一個或多個 UI 元素的實體手勢,例如平移、旋轉、調整大小或移動。 (相較之下,透過元素的 properties window、對話框或其他 UI 功能與元素互動則被視為間接操作。)
  • 被認可為替代的輸入方法,例如滑鼠或手寫筆。
  • 用於補充或修改其他輸入法的各個方面,例如模糊用鋼筆繪製的筆劃。

觸控輸入通常涉及對螢幕上的元素的直接操作。 此元素會立即回應其命中測試區域內的任何觸控接觸,並對觸控接觸的任何後續移動 (包括移除) 做出適當的反應。

應仔細設計自訂觸控手勢和互動。 它們應該是直覺式、回應性且可探索的,並且應該讓使用者充滿信心地探索您的應用程式。

確保應用程式功能在每種支援的輸入裝置類型上一致地公開。 如有必要,請使用某種形式的間接輸入模式,例如用於鍵盤互動的文字輸入,或用於滑鼠和筆的 UI 功能。

請記住,傳統輸入裝置(例如滑鼠和鍵盤)對很多使用者來說既熟悉又具有吸引力。 它們可以提供觸控無法提供的速度、準確性和觸覺回饋。

為所有輸入裝置提供獨特且獨特的互動體驗將支援最廣泛的功能和偏好,吸引最廣泛的受眾,並吸引更多客戶使用您的應用程式。

比較觸控互動要求

下表顯示了設計觸控最佳化 Windows 應用程式時應考慮的輸入裝置之間的一些差異。

因數 觸控互動 滑鼠、鍵盤、筆/手寫筆互動方式 觸控板
精確度 指尖的接觸面積大於單一 x-y 座標,這增加了意外命令啟動的機會。 滑鼠和筆/手寫筆提供精確的 x-y 座標。 與滑鼠相同。
接觸區域的形狀在整個運動過程中會改變。 滑鼠移動和筆/手寫筆筆畫提供精確的 x-y 座標。 鍵盤焦點明確。 與滑鼠相同。
沒有滑鼠游標來幫助定位。 滑鼠遊標、筆/手寫筆遊標和鍵盤焦點都有助於定位。 與滑鼠相同。
人體解剖學 指尖運動不精確,因為用一根或多根手指進行直線運動很困難。 這是由於手關節的曲率和參與運動的關節數量所致。 使用滑鼠或筆/手寫筆執行直線運動更容易,因為控制它們的手比螢幕上的遊標移動的物理距離更短。 與滑鼠相同。
顯示裝置觸控表面的某些區域因手指姿勢及使用者握持裝置的限制而難以觸及。 滑鼠和筆/手寫筆可以到達螢幕的任何部分,而任何控制項都應該可以透過鍵盤透過 Tab 鍵順序存取。 手指姿勢和握力可能是一個問題。
物件可能會被一個或多個指尖或使用者的手遮住。 這稱為遮擋。 間接輸入裝置不會造成遮蔽。 與滑鼠相同。
物件狀態 觸控採用雙狀態模型:顯示裝置的觸控表面要麼被觸碰(啟用),要麼未被觸碰(未啟用)。 沒有可以觸發額外視覺反饋的懸停狀態。 滑鼠、筆/手寫筆和鍵盤都展現出三種狀態模型:上 (釋放)、下 (按下) 和懸停 (聚焦)。
滑鼠懸停讓使用者可以透過與 UI 元素相關的工具提示來探索和學習。 懸停和焦點效果可以傳達哪些物件是互動的,也有助於定位。
與滑鼠相同。
豐富互動 支援多點觸控:觸控介面上有多個輸入點(指尖)。 支援單一輸入點。 與觸控相同。
支援透過手勢直接操作物件,例如點選、拖曳、滑動、捏合和旋轉。 不支援直接操作滑鼠、手寫筆和鍵盤是間接輸入裝置。 與滑鼠相同。

備註

間接投入得益於超過 25 年的改進。 懸停觸發的工具提示等功能旨在解決專門針對觸控板、滑鼠、筆/手寫筆和鍵盤輸入的 UI 探索。 此類 UI 功能已針對觸控輸入提供的豐富體驗進行了重新設計,而不會影響這些其他裝置的使用者體驗。

使用觸控反饋

與應用程式互動期間的適當視覺反饋可幫助使用者識別、學習和適應應用程式和 Windows 平台如何解釋他們的互動。 視覺反饋可以指示成功的互動,傳遞系統狀態,提高控制感,減少錯誤,幫助使用者了解系統和輸入裝置,鼓勵互動。

當使用者依賴觸控輸入進行需要準確定位的活動時,視覺反饋非常重要。 無論何時何地偵測到觸控輸入,都會顯示回饋,以幫助使用者了解您的應用程式及其控制項定義的任何自訂定位規則。

Targeting

鎖定是透過優化:

  • 觸控目標大小

    清晰的尺寸準則可確保應用程式提供舒適的 UI,其中包含易於安全定位的物件和控制項。

  • 接觸幾何

    手指的整個接觸區域會決定最有可能的目標物件。

  • 擦洗

    透過在組內的項目之間拖曳手指 (例如單選按鈕),可以輕鬆地重新定位組內的項目。 當觸控放開時,會啟動目前的項目。

  • 搖擺

    透過向下按手指並且在物品上來回搖晃手指 (無需滑動),可以輕鬆地重新定位密集的項目 (例如超連結)。 由於遮蔽,目前的項目是透過工具提示或狀態列來識別,並在觸控放開時啟動。

準確性

透過使用以下方法來設計草率的互動:

  • 對齊點可以讓使用者與內容互動時更輕鬆地在所需位置停止。
  • 定向「導軌」可以幫助垂直或水平平移,即使手以輕微的弧線移動也是如此。有關詳細資訊,請參閱平移指南

遮擋

可透過下列方式避免手指和手部遮蔽:

  • UI 的大小和位置

    使 UI 元素夠大,以便指尖接觸區域無法完全覆蓋它們。

    盡可能將功能表和彈出視窗放置在互動區域上方。

  • 工具提示

    當使用者在對象上維持手指接觸時顯示工具提示。 這適用於描述物件功能。 使用者可以將指尖從物件上拖曳,以避免叫用工具提示。

    對於小型物件,將工具提示偏移,以免被指尖的接觸區域覆蓋。 這對定位很有用。

  • 精確控制的手柄

    在需要精確度的情況下 (例如,文字選擇),請提供偏移的選擇手柄以提高準確性。 欲了解更多資訊,請參閱選擇文字與圖片指引(Windows 執行階段應用程式)

時機

避免時間模式變更,有利於直接操作。 直接操作會模擬物件的直接即時實體處理。 物件會隨著手指移動而回應。

另一方面,計時互動會在觸控互動之後發生。 計時互動通常取決於時間、距離或速度等不可見閾值,以判斷要執行的命令。 在系統執行動作之前,計時互動沒有視覺反饋。

直接操作比時間限制的互動提供更多優點:

  • 互動期間的即時視覺反饋可讓使用者感到更參與、更自信且能控制。
  • 直接操作使探索系統變得更安全,因為它們是可逆的。使用者能以邏輯和直觀的方式輕鬆地退回他們的操作。
  • 直接影響物件並模仿現實世界互動的互動更加直觀、可發現和難忘。 它們不依賴模糊或抽象的互動。
  • 定時互動可能很難執行,因為使用者必須達到任意且不可見的閾值。

此外,強烈建議以下事項:

  • 操作不應以使用的手指數目來區分。
  • 互動應該支持複合操作。 例如,同時捏合縮放和拖曳手指以平移。
  • 互動不應依時間區分。 無論執行所需的時間如何,相同的互動都應該產生相同的結果。 基於時間的啟動會為使用者帶來強制延遲,並降低直接操作的沉浸感和系統回應能力的感知。

    備註

    一個例外是,當您使用特定的計時互動來協助學習和探索時(例如長按)。

  • 適當的描述和視覺提示對高階互動的使用有很大的影響。

應用程式檢視

透過應用程式檢視的平移/捲動和縮放設定來調整使用者互動體驗。 應用程式檢視決定了使用者如何存取和操作您的應用程式及其內容。 檢視還提供慣性、內容邊界反彈和捕捉點等行為。

ScrollViewer 控制項的平移和捲動設定決定使用者在單一檢視內進行瀏覽的方式,當內容無法完全顯示於檢視區時。 例如,單一檢視可以是雜誌或書籍的一頁、電腦的資料夾結構、文件庫或相簿。

縮放設定適用於光學縮放 (受 ScrollViewer 控制項支援) 和語意縮放控制項。 語義縮放是一種觸控最佳化技術,用於在單一檢視中呈現和瀏覽大量相關資料或內容。 它透過使用兩種不同的分類模式或縮放等級來工作。 這類似於在單一檢視中移動和捲動。 平移和捲動可以與語義縮放結合使用。

使用應用程式檢視和事件來修改平移/捲動和縮放行為。 與處理指標和手勢事件相比,這可以提供更流暢的互動體驗。

如需應用程式檢視的詳細資訊,請參閱控制項、版面配置和文字

自訂觸控互動

如果您實現自己的互動支持,請記住,使用者期望獲得直覺的體驗,包括與應用程式中的 UI 元素直接互動。 我們建議您在平台控制庫上對自訂互動進行建模,以保持事物的一致性和可發現性。 這些資料庫中的控制項提供完整的使用者互動體驗,包括標準互動、動畫物理效果、視覺反饋和可存取性。 僅當存在明確、定義良好的要求並且基本互動不支援您的場景時才建立自訂互動。

這很重要

Windows 11及更新版

根據預設,某些三指和四指觸控互動將無法在 Windows 應用程式中運作。

根據預設,系統現在會針對切換或最小化視窗和變更虛擬桌面等作業使用三指和四指觸控互動。 由於這些互動現在會在系統層級處理,因此您的應用程式功能可能會受到這項變更的影響。

為了支援應用程式內的三指或四指互動,引進了新的使用者設定,指定系統是否處理這些互動:

藍牙 & 裝置 > 觸控 >「三指和四指觸控手勢」

當設定為 [開啟] 時,系統會處理所有三指和四指互動(應用程式將無法支持它們)。

當設定為 「關閉」時,應用程式可以支援三指和四指互動(系統不會處理它們)。

如果您的應用程式必須支援這些互動,建議您通知使用者此設定,並提供連結來啟動 Windows 設定至相關頁面 (ms-settings:devices-touch) 。 如需詳細資訊,請參閱 啟動 Windows 設定

若要提供自訂的觸控支援,您可以處理各種 UIElement 事件。 這些事件會分組為三個抽象層級。

  • 互動完成後觸發靜態手勢事件。 手勢事件包括 TappedDoubleTappedRightTappedHolding

    您可以將 IsTapEnabledIsDoubleTapEnabledIsRightTapEnabledIsHoldingEnabled 設為 false 來停用特定元素上的手勢事件。

  • PointerPressedPointerMoved 等指標事件會為每個觸控接觸提供詳細資料,包括指標動作,以及區分按下和釋放事件的能力。

    指標是具有統一事件機制的通用輸入類型。 它公開活動輸入來源 (可以是觸控、觸控板、滑鼠或筆) 的基本訊息,例如螢幕位置。

  • 操作手勢事件,例如 ManipulationStarted,表示進行中的互動。 它們在使用者觸控元素時開始觸發,一直持續到使用者抬起手指或操作被取消。

    操作事件包括多點觸控互動 (例如:縮放、平移或旋轉) 以及使用慣性和速度資料的互動 (例如:拖曳)。 操作事件提供的資訊並不標識所執行的互動的形式,而是包括位置、平移增量和速度等資料。 您可以使用此觸控資料來確定應執行的互動類型。

以下是 WinUI 支援的基本觸控手勢組合。

名稱 類型 Description
點選 靜態手勢 一根手指觸碰螢幕並抬起。
按住 靜態手勢 一根手指觸碰螢幕,並停留在原地。
幻燈片 操作手勢 一或多個手指觸碰螢幕,並以相同的方向移動。
滑動 操作手勢 一或多個手指觸碰螢幕,並以相同方向移動短距離。
轉動 操作手勢 兩個或更多手指觸碰螢幕並以順時針或逆時針弧線移動。
操作手勢 兩根或以上的手指觸碰螢幕,並向中間移動。
Stretch 操作手勢 兩個以上的手指觸碰螢幕,並移動得更遠。

手勢事件

如需個別控制項的詳細資訊,請參閱控制項清單

指標事件

指標事件是由各種不同的使用中輸入來源所引發,包括觸控、觸控板、手寫筆和滑鼠 (它們會取代傳統的滑鼠事件)。

指標事件是以單一輸入點 (手指、手寫筆尖、滑鼠游標) 為基礎,且不支援以速度為基礎的互動。

以下是指標事件及其相關事件引數的清單。

事件或類別 Description
指針按下 當單指觸控螢幕時發生。
指標已釋放 發生於解除相同的觸控接觸點時。
指標已移動 當指標在螢幕上拖曳時發生。
指針進入 當指標進入元素的命中測試區域時發生。
PointerExited 當指標退出元素的命中測試區域時發生。
Pointer已取消 當觸控接觸點異常失去時發生。
PointerCapture遺失 當指標捕捉被另一個元素接管時發生。
指針滾輪變更 發生於滑鼠滾輪的滾動增量變動和觸控板捏合時。
PointerRoutedEventArgs 提供所有指標事件的資料。

以下範例示範如何使用 PointerPressedPointerReleasedPointerExited 事件來處理 Rectangle 物件上的點擊互動。

首先,使用可擴充應用程式標記語言 (XAML) 建立一個名為

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Rectangle Name="touchRectangle"
           Height="100" Width="200" Fill="Blue" />
</Grid>

接下來,指定 PointerPressedPointerReleasedPointerExited 事件的接聽程式。

MainPage::MainPage()
{
    InitializeComponent();

    // Pointer event listeners.
    touchRectangle->PointerPressed += ref new PointerEventHandler(this, &MainPage::touchRectangle_PointerPressed);
    touchRectangle->PointerReleased += ref new PointerEventHandler(this, &MainPage::touchRectangle_PointerReleased);
    touchRectangle->PointerExited += ref new PointerEventHandler(this, &MainPage::touchRectangle_PointerExited);
}
public MainPage()
{
    this.InitializeComponent();

    // Pointer event listeners.
    touchRectangle.PointerPressed += touchRectangle_PointerPressed;
    touchRectangle.PointerReleased += touchRectangle_PointerReleased;
    touchRectangle.PointerExited += touchRectangle_PointerExited;
}
Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Pointer event listeners.
    AddHandler touchRectangle.PointerPressed, AddressOf touchRectangle_PointerPressed
    AddHandler touchRectangle.PointerReleased, AddressOf Me.touchRectangle_PointerReleased
    AddHandler touchRectangle.PointerExited, AddressOf touchRectangle_PointerExited

End Sub

最後,PointerPressed 事件處理程序增加 Rectangle高度寬度,而 PointerReleasedPointerExited 事件處理程序則會將高度寬度設定回其起始值。

// Handler for pointer exited event.
void MainPage::touchRectangle_PointerExited(Object^ sender, PointerRoutedEventArgs^ e)
{
    Rectangle^ rect = (Rectangle^)sender;

    // Pointer moved outside Rectangle hit test area.
    // Reset the dimensions of the Rectangle.
    if (nullptr != rect)
    {
        rect->Width = 200;
        rect->Height = 100;
    }
}

// Handler for pointer released event.
void MainPage::touchRectangle_PointerReleased(Object^ sender, PointerRoutedEventArgs^ e)
{
    Rectangle^ rect = (Rectangle^)sender;

    // Reset the dimensions of the Rectangle.
    if (nullptr != rect)
    {
        rect->Width = 200;
        rect->Height = 100;
    }
}

// Handler for pointer pressed event.
void MainPage::touchRectangle_PointerPressed(Object^ sender, PointerRoutedEventArgs^ e)
{
    Rectangle^ rect = (Rectangle^)sender;

    // Change the dimensions of the Rectangle.
    if (nullptr != rect)
    {
        rect->Width = 250;
        rect->Height = 150;
    }
}
// Handler for pointer exited event.
private void touchRectangle_PointerExited(object sender, PointerRoutedEventArgs e)
{
    Rectangle rect = sender as Rectangle;

    // Pointer moved outside Rectangle hit test area.
    // Reset the dimensions of the Rectangle.
    if (null != rect)
    {
        rect.Width = 200;
        rect.Height = 100;
    }
}
// Handler for pointer released event.
private void touchRectangle_PointerReleased(object sender, PointerRoutedEventArgs e)
{
    Rectangle rect = sender as Rectangle;

    // Reset the dimensions of the Rectangle.
    if (null != rect)
    {
        rect.Width = 200;
        rect.Height = 100;
    }
}

// Handler for pointer pressed event.
private void touchRectangle_PointerPressed(object sender, PointerRoutedEventArgs e)
{
    Rectangle rect = sender as Rectangle;

    // Change the dimensions of the Rectangle.
    if (null != rect)
    {
        rect.Width = 250;
        rect.Height = 150;
    }
}
' Handler for pointer exited event.
Private Sub touchRectangle_PointerExited(sender As Object, e As PointerRoutedEventArgs)
    Dim rect As Rectangle = CType(sender, Rectangle)

    ' Pointer moved outside Rectangle hit test area.
    ' Reset the dimensions of the Rectangle.
    If (rect IsNot Nothing) Then
        rect.Width = 200
        rect.Height = 100
    End If
End Sub

' Handler for pointer released event.
Private Sub touchRectangle_PointerReleased(sender As Object, e As PointerRoutedEventArgs)
    Dim rect As Rectangle = CType(sender, Rectangle)

    ' Reset the dimensions of the Rectangle.
    If (rect IsNot Nothing) Then
        rect.Width = 200
        rect.Height = 100
    End If
End Sub

' Handler for pointer pressed event.
Private Sub touchRectangle_PointerPressed(sender As Object, e As PointerRoutedEventArgs)
    Dim rect As Rectangle = CType(sender, Rectangle)

    ' Change the dimensions of the Rectangle.
    If (rect IsNot Nothing) Then
        rect.Width = 250
        rect.Height = 150
    End If
End Sub

操控事件

如果您需要支援多個手指互動或需要速度資料的互動,請在應用程式中使用操作事件。

您可以使用操作事件來偵測互動,例如拖曳、縮放和按住。

備註

觸控板不會引發操作事件。 相反地,觸控板輸入將引發指標事件。

以下是操作事件和相關事件參數的清單。

事件或類別 Description
ManipulationStarting 事件 第一次建立操作處理器時發生。
ManipulationStarted 事件 當輸入裝置開始操作 UIElement 時發生。
ManipulationDelta 事件 當輸入裝置在操作期間變更位置時發生。
ManipulationInertiaStarting 事件 當輸入裝置在操控UIElement物件時失去接觸,然後開始慣性時發生。
ManipulationCompleted 事件 發生於 UIElement 上的操作和慣性完成時。
操作開始路由事件參數 ManipulationStarting 事件提供資料。
ManipulationStartedRoutedEventArgs ManipulationStarted 事件提供資料。
ManipulationDeltaRoutedEventArgs 提供 ManipulationDelta 事件的資料。
ManipulationInertiaStartingRoutedEventArgs 提供 ManipulationInertiaStarting 事件的資料。
ManipulationVelocities 描述操作發生的速度。
操作完成路由事件引數 (ManipulationCompletedRoutedEventArgs) ManipulationCompleted+ 事件提供資料。

手勢是由一系列操作事件所組成。 每個手勢都會 以ManipulationStarted 事件開頭,例如當使用者觸碰螢幕時。

接下來,會引發一或多個 ManipulationDelta 事件。 例如,如果您觸碰螢幕,然後將手指拖曳到螢幕上。 最後,互動完成時會引發 ManipulationCompleted 事件。

備註

如果您沒有觸控螢幕顯示器,則可以使用滑鼠和滑鼠滾輪介面在模擬器中測試操作事件程式碼。

以下範例示範如何使用 ManipulationDelta 事件來處理 Rectangle 上的滑動互動並將其移至螢幕上。

首先,在 XAML 中建立一個名為Rectangle,其touchRectangle寬度均為 200。

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Rectangle Name="touchRectangle"
               Width="200" Height="200" Fill="Blue" 
               ManipulationMode="All"/>
</Grid>

接下來,為 Rectangle 建立一個名為 dragTranslation 的全域 TranslateTransform 用於轉換。 在 Rectangle 上指定 ManipulationDelta 事件偵聽器,並將 dragTranslation 新增至 RectangleRenderTransform 中。

// Global translation transform used for changing the position of 
// the Rectangle based on input data from the touch contact.
Windows::UI::Xaml::Media::TranslateTransform^ dragTranslation;
// Global translation transform used for changing the position of 
// the Rectangle based on input data from the touch contact.
private TranslateTransform dragTranslation;
' Global translation transform used for changing the position of 
' the Rectangle based on input data from the touch contact.
Private dragTranslation As TranslateTransform
MainPage::MainPage()
{
    InitializeComponent();

    // Listener for the ManipulationDelta event.
    touchRectangle->ManipulationDelta += 
        ref new ManipulationDeltaEventHandler(
            this, 
            &MainPage::touchRectangle_ManipulationDelta);
    // New translation transform populated in 
    // the ManipulationDelta handler.
    dragTranslation = ref new TranslateTransform();
    // Apply the translation to the Rectangle.
    touchRectangle->RenderTransform = dragTranslation;
}
public MainPage()
{
    this.InitializeComponent();

    // Listener for the ManipulationDelta event.
    touchRectangle.ManipulationDelta += touchRectangle_ManipulationDelta;
    // New translation transform populated in 
    // the ManipulationDelta handler.
    dragTranslation = new TranslateTransform();
    // Apply the translation to the Rectangle.
    touchRectangle.RenderTransform = this.dragTranslation;
}
Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Listener for the ManipulationDelta event.
    AddHandler touchRectangle.ManipulationDelta,
        AddressOf testRectangle_ManipulationDelta
    ' New translation transform populated in 
    ' the ManipulationDelta handler.
    dragTranslation = New TranslateTransform()
    ' Apply the translation to the Rectangle.
    touchRectangle.RenderTransform = dragTranslation

End Sub

最後,在 ManipulationDelta 事件處理程序中,透過使用 Delta 屬性上的 TranslateTransform 來更新 Rectangle 的位置。

// Handler for the ManipulationDelta event.
// ManipulationDelta data is loaded into the
// translation transform and applied to the Rectangle.
void MainPage::touchRectangle_ManipulationDelta(Object^ sender,
    ManipulationDeltaRoutedEventArgs^ e)
{
    // Move the rectangle.
    dragTranslation->X += e->Delta.Translation.X;
    dragTranslation->Y += e->Delta.Translation.Y;
    
}
// Handler for the ManipulationDelta event.
// ManipulationDelta data is loaded into the
// translation transform and applied to the Rectangle.
void touchRectangle_ManipulationDelta(object sender,
    ManipulationDeltaRoutedEventArgs e)
{
    // Move the rectangle.
    dragTranslation.X += e.Delta.Translation.X;
    dragTranslation.Y += e.Delta.Translation.Y;
}
' Handler for the ManipulationDelta event.
' ManipulationDelta data Is loaded into the
' translation transform And applied to the Rectangle.
Private Sub testRectangle_ManipulationDelta(
    sender As Object,
    e As ManipulationDeltaRoutedEventArgs)

    ' Move the rectangle.
    dragTranslation.X = (dragTranslation.X + e.Delta.Translation.X)
    dragTranslation.Y = (dragTranslation.Y + e.Delta.Translation.Y)

End Sub

路由事件

這裡提到的所有指標事件、手勢事件和操作事件都是作為路由事件實現的。 這代表該事件可能由最初引發該事件的物件以外的物件處理。 物件樹中的連續的父級(例如 UIElement 的父容器或應用程式的根 Page)可以選擇處理這些事件,而不需原始元素處理。 相反,任何處理該事件的物件都可以標記該事件已處理,以便它不再到達任何父元素。 有關路由事件概念及其如何影響路由事件的處理程序編寫方式的詳細資訊,請參閱事件和路由事件概述

這很重要

如果您需要在可捲動的檢視中處理 UIElement 的指標事件 (例如 ScrollViewer 或 ListView),則必須藉由呼叫 UIElement.CancelDirectmanipulation(),明確停用對於此檢視元素上操作事件的支援。 若要在檢視中重新啟用操作事件,請呼叫 UIElement.TryStartDirectManipulation()

可行與禁止事項

  • 將觸控互動設計為主要預期的輸入方法的應用程式。
  • 針對所有類型的互動提供視覺反饋 (觸控、手寫筆、手寫筆、滑鼠等)
  • 透過調整觸控目標尺寸、接觸幾何形狀、刮擦和搖擺來最佳化定位。
  • 透過使用貼齊點和方向導軌,將精確度最佳化。
  • 提供工具提示和控制點,以協助改善緊密排列 UI 項目的觸控精確度。
  • 盡量避免使用計時互動(適當使用範例:觸控並按住)。
  • 盡可能不要使用用於區分操作的手指數量。

Samples

封存範例