觸控式裝置

Android 支援各種觸控螢幕和觸控板,包括基於手寫筆的數位化平板電腦。

觸控螢幕是與顯示器相關聯的觸控設備,使得使用者有直接操縱螢幕上的項目的印象。

觸控板是與顯示器無關的觸控設備,例如數位平板電腦。觸控板通常用於指向或絕對間接定位或使用者介面的基於手勢的控制。

觸控設備可以具有功能類似於滑鼠按鈕的按鈕。

有時可以使用各種不同的工具(例如手指或手寫筆)來操縱觸控設備,這取決於底層觸控感應器技術。

觸控設備有時用於實現虛擬按鍵。例如,在某些 Android 裝置上,觸控螢幕感應器區域延伸到顯示器邊緣之外,並作為觸控鍵盤的一部分發揮雙重作用。

由於觸控設備種類繁多,Android 依賴大量配置屬性來描述每個設備的特性和所需行為。

觸摸設備分類

如果同時滿足以下兩個條件,則輸入裝置被歸類為多點觸控設備:

  • 輸入裝置報告ABS_MT_POSITION_XABS_MT_POSITION_Y絕對軸的存在。
  • 輸入設備沒有任何遊戲手把按鈕。此情況解決了某些遊戲手把的歧義,這些遊戲手把報告的軸的代碼與 MT 軸的代碼重疊。

如果滿足以下兩個條件,則輸入裝置被歸類為單點觸控裝置:

  • 輸入設備不屬於多點觸控設備。輸入設備要么被分類為單點觸控設備,要么被分類為多點觸控設備,而不會同時被分類為兩者。
  • 輸入設備報告ABS_XABS_Y絕對軸的存在以及BTN_TOUCH鍵代碼的存在。

當輸入裝置被分類為觸控裝置時,透過嘗試載入裝置的虛擬鍵對應檔案來確定虛擬鍵的存在。如果虛擬按鍵對應可用,則也會載入裝置的按鍵佈局檔案。有關這些檔案的位置和格式的信息,請參閱[虛擬鍵映射檔案](#virtual-key-map-files)。

接下來,系統會載入觸控設備的輸入設備設定檔。

所有內建觸控設備都應該有輸入設備設定檔。如果不存在輸入裝置設定文件,系統會選擇適用於通用觸控週邊(例如外部 USB 或藍牙 HID 觸控螢幕或觸控板)的預設配置。這些預設值不是為內建觸控螢幕設計的,可能會導致不正確的行為。

載入輸入裝置配置後,系統將輸入裝置分類為觸控螢幕觸控板指針裝置。

  • 觸控螢幕設備用於直接操縱螢幕上的物件。使用者直接觸摸螢幕,因此系統不需要任何額外的功能來指示正在操作的物件。
  • 觸控板設備用於向應用程式提供有關給定感測器區域上的觸控的絕對定位資訊。它對於數位化平板電腦很有用。
  • 指針設備用於使用遊標間接操縱螢幕上的物件。手指被解釋為多點觸摸指針手勢。其他工具(例如手寫筆)是使用絕對位置來解釋的。有關詳細信息,請參閱間接多點觸摸指針手勢

以下規則用於將輸入裝置分類為觸控螢幕、觸控板或指針裝置。

  • 如果設定了touch.deviceType屬性,則裝置類型將依指示設定。
  • 如果輸入設備報告存在INPUT_PROP_DIRECT輸入屬性(透過EVIOCGPROP ioctl),則設備類型設定為touch screen 。此條件假設直接輸入觸控裝置連接到也已連接的顯示器。
  • 如果輸入設備報告存在INPUT_PROP_POINTER輸入屬性(透過EVIOCGPROP ioctl),則設備類型設定為指標
  • 如果輸入設備報告存在REL_XREL_Y相對軸,則設備類型設定為touch pad 。此條件解決了由滑鼠和觸控板組成的輸入裝置的歧義。在這種情況下,觸控板不用於控制指針,因為滑鼠已經控制了它。
  • 否則,設備類型設定為指針。此預設設定可確保未指定任何其他特殊用途的觸控板控制指標。

羈扣

按鈕是應用程式可用於執行附加功能的可選控制項。觸控裝置上的按鈕的行為與滑鼠按鈕類似,主要與指標式觸控裝置或手寫筆一起使用。

支援以下按鈕:

  • BTN_LEFT :映射到MotionEvent.BUTTON_PRIMARY
  • BTN_RIGHT :映射到MotionEvent.BUTTON_SECONDARY
  • BTN_MIDDLE :對應到MotionEvent.BUTTON_MIDDLE
  • BTN_BACKBTN_SIDE :對應到MotionEvent.BUTTON_BACK 。按下此按鈕也會合成一個帶有鍵碼KeyEvent.KEYCODE_BACK的按鍵。
  • BTN_FORWARDBTN_EXTRA :映射到MotionEvent.BUTTON_FORWARD 。按下此按鈕也會使用鍵碼KeyEvent.KEYCODE_FORWARD合成按鍵。
  • BTN_STYLUS :映射到MotionEvent.BUTTON_SECONDARY
  • BTN_STYLUS2 :映射到MotionEvent.BUTTON_TERTIARY

工具和工具類型

工具是手指、觸筆或用於與觸控裝置互動的其他裝置。一些觸摸設備可以區分不同類型的工具。

在 Android 的其他地方,例如在MotionEvent API 中,工具通常稱為指標

支援以下工具類型:

  • BTN_TOOL_FINGERMT_TOOL_FINGER :映射到MotionEvent.TOOL_TYPE_FINGER
  • BTN_TOOL_PENMT_TOOL_PEN :映射到MotionEvent.TOOL_TYPE_STYLUS
  • BTN_TOOL_RUBBER :對應到MotionEvent.TOOL_TYPE_ERASER
  • BTN_TOOL_BRUSH :對應到MotionEvent.TOOL_TYPE_STYLUS
  • BTN_TOOL_PENCIL :映射到MotionEvent.TOOL_TYPE_STYLUS
  • BTN_TOOL_AIRBRUSH :對應到MotionEvent.TOOL_TYPE_STYLUS
  • BTN_TOOL_MOUSE :對應到MotionEvent.TOOL_TYPE_MOUSE
  • BTN_TOOL_LENS :對應到MotionEvent.TOOL_TYPE_MOUSE
  • BTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAPBTN_TOOL_QUADTAP :對應到MotionEvent.TOOL_TYPE_FINGER

懸停工具與觸控工具

工具可以與觸控設備接觸,也可以在其範圍內並懸停在其上方。並非所有觸控設備都能感知懸停在觸控設備上方的工具的存在。那些能夠做到這一點的工具,例如基於射頻的手寫筆數位化儀,通常可以檢測工具何時位於數位化儀的有限範圍內。

InputReader元件區分觸控工具和懸停工具。同樣,觸控工具和懸停工具以不同的方式報告給應用程式。

使用MotionEvent.ACTION_DOWNMotionEvent.ACTION_MOVEMotionEvent.ACTION_DOWNMotionEvent.ACTION_POINTER_DOWNMotionEvent.ACTION_POINTER_UP將觸控工具作為觸摸事件報告給應用程式。

使用MotionEvent.ACTION_HOVER_ENTERMotionEvent.ACTION_HOVER_MOVEMotionEvent.ACTION_HOVER_EXIT將懸停工具作為通用運動事件報告給應用程式。

觸摸裝置驅動程式要求

  • 觸摸設備驅動程式應僅註冊它們支援的軸和軸和按鈕的鍵代碼。註冊不受支援的軸或鍵代碼可能會混淆設備分類演算法或導致系統錯誤地檢測設備的功能。例如,如果設備報告BTN_TOUCH按鍵代碼,系統假定BTN_TOUCH始終用於指示工具是否正在觸摸螢幕。因此, BTN_TOUCH不應用於指示該工具僅在範圍內並懸停。
  • 單點觸控設備使用以下 Linux 輸入事件:
    • ABS_X :(必要)報告工具的 X 座標。
    • ABS_Y :(必要)報告工具的 Y 座標。
    • ABS_PRESSURE :(可選)報告施加在工具尖端的物理壓力或觸摸接觸的訊號強度。
    • ABS_TOOL_WIDTH :(可選)報告觸控觸點或工具本身的橫截面積或寬度。
    • ABS_DISTANCE :(選用)報告工具距觸控設備表面的距離。
    • ABS_TILT_X :(選用)報告工具沿著 X 軸相對於觸控裝置表面的傾斜度。
    • ABS_TILT_Y :(選用)報告工具沿著 Y 軸相對於觸控設備表面的傾斜度。
    • BTN_TOUCH :(必需)指示工具是否正在接觸設備。
    • BTN_LEFTBTN_RIGHTBTN_MIDDLEBTN_BACKBTN_SIDEBTN_FORWARDBTN_EXTRABTN_STYLUSBTN_STYLUS2 :(選用)報告按鈕狀態。
    • BTN_TOOL_FINGERBTN_TOOL_PENBTN_TOOL_RUBBERBTN_TOOL_BRUSHBTN_TOOL_PENCILBTN_TOOL_AIRBRUSHBTN_TOOL_MOUSE 、 BTN_TOOL_PENCIL 、 BTN_TOOL_LENSBTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAP BTN_TOOL_QUADTAP :(可選)報告工具類型
  • 多點觸控設備使用以下 Linux 輸入事件:
    • ABS_MT_POSITION_X :(必要)報告工具的 X 座標。
    • ABS_MT_POSITION_Y :(必要)報告工具的 Y 座標。
    • ABS_MT_PRESSURE :(可選)報告施加在工具尖端的物理壓力或觸摸接觸的訊號強度。
    • ABS_MT_TOUCH_MAJOR :(可選)報告觸控接點的橫截面積,或觸控接點較長尺寸的長度。
    • ABS_MT_TOUCH_MINOR :(可選)報告觸摸接觸的較短尺寸的長度。如果ABS_MT_TOUCH_MAJOR正在報告面積測量,則不應使用此軸。
    • ABS_MT_WIDTH_MAJOR :(可選)報告工具本身的橫截面積,或工具本身較長尺寸的長度。除非您知道工具本身的尺寸,否則請勿使用此軸。
    • ABS_MT_WIDTH_MINOR :(可選)報告工具本身較短尺寸的長度。如果ABS_MT_WIDTH_MAJOR報告面積測量或工具本身的尺寸未知,則不應使用此軸。
    • ABS_MT_ORIENTATION :(可選)報告工具的方向。
    • ABS_MT_DISTANCE :(可選)報告工具與觸控設備表面的距離。
    • ABS_MT_TOOL_TYPE :(可選)工具類型報告為MT_TOOL_FINGERMT_TOOL_PEN
    • ABS_MT_TRACKING_ID :(可選)報告工具的追蹤 ID。追蹤 ID 是任意非負整數,用於在多個工具處於活動狀態時獨立識別和追蹤每個工具。例如,當多個手指觸摸裝置時,每個手指都應該分配一個不同的追蹤 ID,只要手指保持接觸,就可以使用該追蹤 ID。當相關工具移出範圍時,追蹤 ID 可以重複使用。
    • ABS_MT_SLOT :(選用)使用 Linux 多點觸控協定「B」時報告工具的插槽 ID。有關更多詳細信息,請參閱 Linux 多點觸控協議文件。
    • BTN_TOUCH :(必需)指示工具是否正在接觸設備。
    • BTN_LEFTBTN_RIGHTBTN_MIDDLEBTN_BACKBTN_SIDEBTN_FORWARDBTN_EXTRABTN_STYLUSBTN_STYLUS2 :(選用)報告按鈕狀態。
    • BTN_TOOL_FINGERBTN_TOOL_PENBTN_TOOL_RUBBERBTN_TOOL_BRUSHBTN_TOOL_PENCILBTN_TOOL_AIRBRUSHBTN_TOOL_MOUSE 、 BTN_TOOL_PENCIL 、 BTN_TOOL_LENSBTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAP BTN_TOOL_QUADTAP :(可選)報告工具類型
  • 如果同時定義了單點觸控和多點觸控協定的軸,則僅使用多點觸控軸,而忽略單點觸控軸。
  • ABS_XABS_YABS_MT_POSITION_XABS_MT_POSITION_Y軸的最小值和最大值以裝置特定的表面單位定義裝置活動區域的邊界。對於觸控螢幕,活動區域描述了觸控裝置中實際覆蓋顯示器的部分。

    對於觸控屏,系統會根據以下計算自動對報告的觸控位置(以表面單位為單位)進行插值,以獲得以顯示像素為單位的觸控位置:

        displayX = (x - minX) * displayWidth / (maxX - minX + 1)
        displayY = (y - minY) * displayHeight / (maxY - minY + 1)
        

    觸控螢幕可能會報告所報告的活動區域之外的觸控。

    在活動區域外發起的觸控不會傳遞到應用程序,但可用於虛擬按鍵。

    在活動區域內發起的觸摸,或進入和退出顯示區域的觸控都會傳遞給應用程式。因此,如果觸控在應用程式的範圍內開始,然後移動到活動區域之外,則應用程式可能會收到顯示座標為負或超出顯示範圍的觸控事件。這是預期的行為。

    觸控設備不應該將觸控座標限制在活動區域的邊界內。如果觸摸退出活動區域,則應將其報告為在活動區域之外,或者根本不應該報告。

    例如,如果使用者的手指觸摸觸控螢幕的左上角附近,則可能會報告座標(minX,minY)。如果手指繼續進一步移出活動區域,觸控螢幕應開始報告小於 minX 和 minY 的座標,例如 (minX - 2, minY - 3),或完全停止報告觸控。換句話說,當使用者的手指確實觸摸到活動區域之外時,觸控螢幕應該報告(minX,minY)。

    將觸控座標固定到顯示邊緣會在螢幕邊緣周圍建立一個人造硬邊界,阻止系統平滑地追蹤進入或退出顯示區域邊界的運動。

  • ABS_PRESSUREABS_MT_PRESSURE報告的值(如果有報告)在工具接觸設備時必須為非零,否則為零以指示工具正在懸停。

    報告壓力資訊是可選的,但強烈建議這樣做。應用程式可以使用壓力資訊來實現壓力敏感繪圖和其他效果。

  • 當工具接觸設備時, ABS_TOOL_WIDTHABS_MT_TOUCH_MAJORABS_MT_TOUCH_MINORABS_MT_WIDTH_MAJORABS_MT_WIDTH_MINOR報告的值應為零,但這不是必要的。例如,觸控裝置可能能夠測量手指觸摸觸點的尺寸,但不能測量手寫筆觸控觸點的尺寸。

    報告尺寸資訊是可選的,但強烈建議這樣做。應用程式可以使用壓力資訊來實現大小敏感的繪圖和其他效果。

  • 當工具接觸設備時, ABS_DISTANCEABS_MT_DISTANCE報告的值應接近零。即使工具直接接觸,該距離也可以保持非零。報告的確切值取決於硬體測量距離的方式。

    報告距離資訊是可選的,但建議用於手寫筆設備。

  • 當工具垂直於設備時, ABS_TILT_XABS_TILT_Y報告的值應為零。非零傾斜表示工具保持傾斜。

    假設沿 X 軸和 Y 軸的傾斜角度以與垂直方向的度數為單位指定。每個軸的中心點(完全垂直)由(max + min) / 2給出。小於中心點的值表示向上或向左傾斜,大於中心點的值表示向下或向右傾斜。

    InputReader將 X 和 Y 傾斜分量轉換為範圍從 0 到PI / 2弧度的垂直傾斜角和範圍從-PIPI弧度的平面方向角。這種表示導致對方向的描述與用於描述手指觸摸的方向相容。

    報告傾斜資訊是可選的,但建議用於手寫筆設備。

  • 如果工具類型由ABS_MT_TOOL_TYPE報告,它將取代BTN_TOOL_*報告的任何工具類型資訊。如果根本沒有可用的工具類型訊息,則工具類型預設為MotionEvent.TOOL_TYPE_FINGER

  • 根據以下條件決定工具處於活動狀態:

    • 使用單點觸控協定時,如果BTN_TOUCHBTN_TOOL_*為 1,則該工具處於活動狀態。

      此條件意味著InputReader需要至少有一些有關工具性質的信息,無論是觸摸,還是至少其工具類型。如果沒有可用信息,則假定該工具處於非活動狀態(超出範圍)。

    • 使用多點觸控協定「A」時,只要工具出現在最新的同步報告中,該工具就會處於活動狀態。當該工具停止出現在同步報告中時,它就不再存在。
    • 使用多點觸控協定「B」時,只要工具具有活動插槽,該工具就處於作用中狀態。當槽位被清除後,該工具就不存在了。
  • 根據以下條件決定工具處於懸停狀態:
    • 如果工具是BTN_TOOL_MOUSEBTN_TOOL_LENS ,則即使滿足下列任一條件,該工具也不會懸停。
    • 如果該工具處於活動狀態並且駕駛員報告壓力訊息,並且報告的壓力為零,則該工具正在懸停。
    • 如果該工具處於活動狀態且驅動程式支援BTN_TOUCH鍵代碼且BTN_TOUCH的值為零,則該工具處於懸停狀態。
  • InputReader支援多點觸控協定「A」和「B」。新驅動程式應使用“B”協議,但兩者都可以。
  • 從 Android 4.0 開始,觸控螢幕驅動程式可能需要變更以符合 Linux 輸入協定規格。

    可能需要進行以下更改:

    • 當工具變成非活動狀態(手指「向上」移動)時,它應該會停止出現在後續多點觸控同步報告中。當所有工具變成非活動狀態(所有手指都「向上」)時,驅動程式應發送空的同步報告資料包,例如SYN_MT_REPORT後跟SYN_REPORT

      先前版本的 Android 期望透過發送壓力值 0 來報告「向上」事件。舊的行為與 Linux 輸入協定規範不相容,不再受支援。

    • 應使用ABS_MT_PRESSURE報告物理壓力或訊號強度資訊。

      先前版本的 Android 從ABS_MT_TOUCH_MAJOR檢索壓力資訊。舊行為與 Linux 輸入協定規範不相容,不再支援。

    • 應使用ABS_MT_TOUCH_MAJOR報告觸控尺寸資訊。

      先前版本的 Android 從ABS_MT_TOOL_MAJOR檢索尺寸資訊。舊行為與 Linux 輸入協定規範不相容,不再支援。

    觸控裝置驅動程式不再需要 Android 特定的自訂。透過依靠標準的Linux輸入協議,Android可以使用未經修改的驅動程式支援更廣泛的觸控外設,例如外部HID多點觸控螢幕。

觸摸設備操作

下面簡單總結Android上的觸控設備操作。

  1. EventHubevdev驅動程式讀取原始事件。
  2. InputReader使用原始事件並更新有關每個工具的位置和其他特徵的內部狀態。它還追蹤按鈕狀態。
  3. 如果按下或釋放BACKFORWARDInputReader會通知InputDispatcher有關按鍵事件的資訊。
  4. InputReader決定是否發生虛擬按鍵按下。如果是這樣,它會通知InputDispatcher有關按鍵事件的資訊。
  5. InputReader決定觸摸是否在顯示範圍內啟動。如果是這樣,它會通知InputDispatcher有關觸摸事件的資訊。
  6. 如果沒有觸摸工具,但至少有一個懸停工具, InputReader會通知InputDispatcher有關懸停事件的資訊。
  7. 如果觸摸裝置類型為指針InputReader執行指針手勢偵測,相應地移動指針並進行定位,並通知InputDispatcher有關指針事件的資訊。
  8. InputDispatcher使用WindowManagerPolicy來決定是否要調度事件以及是否應喚醒裝置。然後, InputDispatcher將事件傳遞到適當的應用程式。

觸摸設備配置

觸控設備行為由設備的軸、按鈕、輸入屬性、輸入設備配置、虛擬鍵映射和鍵佈局決定。

有關參與鍵盤配置的文件的更多詳細信息,請參閱以下部分:

特性

系統依賴許多輸入設備配置屬性來配置和校準觸控設備行為。

原因之一是觸摸設備的設備驅動程式通常使用設備特定的單位來報告觸摸的特徵。

例如,許多觸控設備使用內部設備特定的尺度來測量觸摸接觸面積,例如由觸摸觸發的感測器節點的總數。此原始尺寸值對應用程式沒有意義,因為它們需要了解觸控設備感測器節點的物理尺寸和其他特性。

該系統使用輸入設備設定檔中編碼的校準參數來解碼、轉換觸控設備報告的值並將其標準化為應用程式可以理解的更簡單的標準表示形式。

文件約定

出於記錄目的,我們使用以下約定來描述系統在校準過程中使用的值。

原始軸值

以下表達式表示觸控裝置驅動程式作為EV_ABS事件報告的原始值。

raw.x
ABS_XABS_MT_POSITION_X軸的值。
raw.y
ABS_YABS_MT_POSITION_Y軸的值。
raw.pressure
ABS_PRESSUREABS_MT_PRESSURE軸的值,若無法使用則為 0。
raw.touchMajor
ABS_MT_TOUCH_MAJOR軸的值,若無法使用則為 0。
raw.touchMinor
ABS_MT_TOUCH_MINOR軸的值,或raw.touchMajor (如果不可用)。
raw.toolMajor
ABS_TOOL_WIDTHABS_MT_WIDTH_MAJOR軸的值,若無法使用則為 0。
raw.toolMinor
ABS_MT_WIDTH_MINOR軸的值,或raw.toolMajor (如果不可用)。
raw.orientation
ABS_MT_ORIENTATION軸的值,若不可用則為 0。
raw.distance
ABS_DISTANCEABS_MT_DISTANCE軸的值,若無法使用則為 0。
raw.tiltX
ABS_TILT_X軸的值,如果不可用則為 0。
raw.tiltY
ABS_TILT_Y軸的值,如果不可用則為 0。

原始軸範圍

以下表達式表示原始值的範圍。它們是透過為每個軸調用EVIOCGABS ioctl 而獲得的。

raw.*.min
原始軸的包含最小值。
raw.*.max
原始軸的包含最大值。
raw.*.range
相當於raw.*.max - raw.*.min
raw.*.fuzz
原始軸的精度。例如。 fuzz = 1 表示數值精確到 +/- 1 個單位。
raw.width
觸摸區域的包含寬度,相當於raw.x.range + 1
raw.height
觸摸區域的包含高度,相當於raw.y.range + 1

輸出範圍

以下表達式表示輸出座標系的特性。該系統使用線性插值將觸控位置資訊從觸控裝置使用的表面單位轉換為報告給應用程式的輸出單位,例如顯示像素。

output.width
輸出寬度。對於觸控螢幕(與顯示器相關),這是以像素為單位的顯示寬度。對於觸控板(不與顯示器關聯),輸出寬度等於raw.width ,表示不執行內插。
output.height
輸出高度。對於觸控螢幕(與顯示器相關),這是以像素為單位的顯示器高度。對於觸控板(不與顯示器關聯),輸出高度等於raw.height ,表示不執行內插。
output.diag
輸出座標系的對角線長度,相當於sqrt(output.width ^2 + output.height ^2)

基本配置

觸控輸入映射器使用輸入裝置設定檔中的許多配置屬性來指定校準值。下表描述了一些通用配置屬性。所有其他屬性及其用於校準的欄位將在以下部分中進行說明。

touch.deviceType

定義: touch.deviceType = touchScreen | touchPad | pointer | default

指定觸摸設備類型。

  • 如果值為touchScreen ,則觸控裝置是與顯示器關聯的觸控螢幕。

  • 如果值為touchPad ,則觸控裝置是與顯示器無關的觸控板。

  • 如果值為pointer ,則觸控裝置是與顯示器無關的觸控板,且其動作用於間接多點觸控指標手勢

  • 如果值為default ,系統會根據分類演算法自動偵測設備類型。

有關設備類型如何影響觸摸設備行為的更多詳細信息,請參閱分類部分。

在 Android 3 及更低版本中,所有觸控裝置都被假定為觸控螢幕。

touch.orientationAware

定義: touch.orientationAware = 0 | 1

指定觸摸設備是否應對顯示方向變化做出反應。

  • 如果值為1 ,則只要顯示方向發生變化,觸摸裝置報告的觸控位置就會旋轉。

  • 如果值為0 ,則觸摸裝置報告的觸控位置不受顯示方向變化的影響。

如果設備是觸控屏,則預設值為1 ,否則為0

此系統區分內部和外部觸控螢幕和顯示器。方向感知內部觸控螢幕根據內部顯示器的方向旋轉。方向感知外部觸控螢幕根據外部顯示器的方向旋轉。

方向感知用於支援 Nexus One 等裝置上觸控螢幕的旋轉。例如,當裝置從其自然方向順時針旋轉 90 度時,觸控的絕對位置將被重新映射,以便將觸控螢幕絕對座標系左上角的觸控報告為左上角的觸控顯示器旋轉座標系的一角。這樣做是為了使用應用程式用來繪製其視覺元素的相同座標系來報告觸控。

在 Honeycomb 出現之前,所有觸控裝置都被假定為具有方向感知能力。

觸摸手勢模式

定義: touch.gestureMode = pointer | spots | default

指定指針手勢的呈現模式。僅當觸控設備的類型為指標時,此配置屬性才相關。

  • 如果值為pointer ,則觸控板手勢將透過類似滑鼠指標的遊標呈現。

  • 如果值為spots ,則觸控板手勢由表示手勢質心的錨點和表示各個手指位置的一組圓形點來呈現。

當設定INPUT_PROP_SEMI_MT輸入屬性時,預設值為pointer ,否則為spots

X 和 Y 字段

X 和 Y 欄位提供接觸區域中心的位置資訊。

計算

計算很簡單:來自觸控驅動器的位置資訊被線性插值到輸出座標系。

xScale = output.width / raw.width
yScale = output.height / raw.height

If not orientation aware or screen rotation is 0 degrees:
output.x = (raw.x - raw.x.min) * xScale
output.y = (raw.y - raw.y.min) * yScale
Else If rotation is 90 degrees:
    output.x = (raw.y - raw.y.min) * yScale
    output.y = (raw.x.max - raw.x) * xScale
Else If rotation is 180 degrees:
    output.x = (raw.x.max - raw.x) * xScale
    output.y = (raw.y.max - raw.y) * yScale
Else If rotation is 270 degrees:
    output.x = (raw.y.max - raw.y) * yScale
    output.y = (raw.x - raw.x.min) * xScale
End If

touchMajor、touchMinor、toolMajor、toolMinor、尺寸字段

touchMajortouchMinor字段以輸出單位(像素)描述接觸區域的大致尺寸。

toolMajortoolMinor欄位以輸出單位(像素)描述工具本身的大致尺寸。

size欄位描述相對於觸控裝置可以感測到的最大可能觸控的觸控的歸一化尺寸。最小可能的標準化尺寸為 0.0(無接觸,或無法測量),最大可能的標準化尺寸為 1.0(感測器區域飽和)。

當近似長度和寬度都可以測量時,則touchMajor字段指定接觸區域的較長尺寸,而touchMinor字段指定接觸區域的較短尺寸。當只能測量接觸區域的近似直徑時, touchMajortouchMinor字段相等。

同樣, toolMajor欄位指定工具橫斷面區域的較長尺寸, toolMinor欄位指定工具橫斷面區域的較短尺寸。

如果觸摸尺寸不可用但工具尺寸可用,則工具尺寸將設定為等於觸摸尺寸。相反,如果工具尺寸不可用但觸摸尺寸可用,則觸摸尺寸設定為等於工具尺寸。

觸摸設備以多種方式測量或報告觸摸尺寸和工具尺寸。目前的實現支援三種不同類型的測量:直徑、面積和表面單位的幾何邊界框。

定義: touch.size.calibration = none | geometric | diameter | area | default

指定觸摸驅動程式用於報告觸摸尺寸和工具尺寸的測量類型。

  • 如果值為none ,則大小設定為零。

  • 如果該值為geometric值,則假定大小以與位置相同的表面單位指定,因此以相同的方式縮放。

  • 如果值為diameter ,則假定大小與觸摸或工具的直徑(寬度)成正比。

  • 如果值為area ,則假定大小與觸摸或工具的面積成正比。

  • 如果值為default ,如果raw.touchMajorraw.toolMajor軸可用,系統將使用geometric校準,否則將使用none校準。

觸控尺寸比例

定義: touch.size.scale = <非負浮點數>

指定校準中使用的恆定比例因子。

預設值為1.0

觸控尺寸偏差

定義: touch.size.bias = <非負浮點數>

指定校準中使用的恆定偏壓值。

預設值為0.0

touch.size.isSummed

定義: touch.size.isSummed = 0 | 1

指定是將大小報告為所有活動聯絡人的大小總和,還是單獨報告每個聯絡人的大小。

  • 如果值為1 ,則在使用之前將報告的大小除以觸點數量。

  • 如果值為0 ,則按原樣使用報告的大小。

預設值為0

一些觸控設備,特別是「半MT」設備無法區分多個觸點的各個尺寸,因此它們報告代表其總面積或寬度的尺寸測量值。對於此類設備,此屬性只能設定為1 。如果有疑問,請將此值設為0

計算

touchMajortouchMinortoolMajortoolMinorsize欄位的計算取決於指定的校準參數。

If raw.touchMajor and raw.toolMajor are available:
    touchMajor = raw.touchMajor
    touchMinor = raw.touchMinor
    toolMajor = raw.toolMajor
    toolMinor = raw.toolMinor
Else If raw.touchMajor is available:
    toolMajor = touchMajor = raw.touchMajor
    toolMinor = touchMinor = raw.touchMinor
Else If raw.toolMajor is available:
    touchMajor = toolMajor = raw.toolMajor
    touchMinor = toolMinor = raw.toolMinor
Else
    touchMajor = toolMajor = 0
    touchMinor = toolMinor = 0
    size = 0
End If

size = avg(touchMajor, touchMinor)

If touch.size.isSummed == 1:
    touchMajor = touchMajor / numberOfActiveContacts
    touchMinor = touchMinor / numberOfActiveContacts
    toolMajor = toolMajor / numberOfActiveContacts
    toolMinor = toolMinor / numberOfActiveContacts
    size = size / numberOfActiveContacts
End If

If touch.size.calibration == "none":
    touchMajor = toolMajor = 0
    touchMinor = toolMinor = 0
    size = 0
Else If touch.size.calibration == "geometric":
    outputScale = average(output.width / raw.width, output.height / raw.height)
    touchMajor = touchMajor * outputScale
    touchMinor = touchMinor * outputScale
    toolMajor = toolMajor * outputScale
    toolMinor = toolMinor * outputScale
Else If touch.size.calibration == "area":
    touchMajor = sqrt(touchMajor)
    touchMinor = touchMajor
    toolMajor = sqrt(toolMajor)
    toolMinor = toolMajor
Else If touch.size.calibration == "diameter":
    touchMinor = touchMajor
    toolMinor = toolMajor
End If

If touchMajor != 0:
    output.touchMajor = touchMajor * touch.size.scale + touch.size.bias
Else
    output.touchMajor = 0
End If

If touchMinor != 0:
    output.touchMinor = touchMinor * touch.size.scale + touch.size.bias
Else
    output.touchMinor = 0
End If

If toolMajor != 0:
    output.toolMajor = toolMajor * touch.size.scale + touch.size.bias
Else
    output.toolMajor = 0
End If

If toolMinor != 0:
    output.toolMinor = toolMinor * touch.size.scale + touch.size.bias
Else
    output.toolMinor = 0
End If

output.size = size

壓力場

pressure場將施加到觸摸設備的近似物理壓力描述為 0.0(無觸摸)和 1.0(全力)之間的標準化值。

零壓力表示工具正在懸停。

觸摸壓力校準

定義: touch.pressure.calibration = none | physical | amplitude | default

指定觸摸驅動程式用於報告壓力的測量類型。

  • 如果值為none ,則壓力未知,因此觸摸時設定為 1.0,懸停時設定為 0.0。

  • 如果該值是physical ,則假定壓力軸測量施加到觸控板的壓力的實際物理強度。

  • 如果值為amplitude ,則假定壓力軸測量訊號幅度,這與接觸的大小和施加的壓力有關。

  • 如果該值為default ,則如果壓力軸可用,系統將使用physical校準,否則將none使用物理校準。

觸摸壓力刻度

定義: touch.pressure.scale = <非負浮點數>

指定校準中使用的恆定比例因子。

預設值為1.0 / raw.pressure.max

計算

pressure場的計算取決於指定的校準參數。

If touch.pressure.calibration == "physical" or "amplitude":
    output.pressure = raw.pressure * touch.pressure.scale
Else
    If hovering:
        output.pressure = 0
    Else
        output.pressure = 1
    End If
End If

方向和傾斜字段

orientation場將觸摸和工具的方向描述為角度測量。 0的方向表示主要軸是垂直定向的, -PI/2表示主要軸定向向左, PI/2表示主要軸將主要軸定向向右側。當有手寫筆工具時,可以在-PIPI的整個圓範圍內描述方向範圍。

tilt場將工具的傾斜度描述為角度測量。 0的傾斜表示該工具垂直於表面。 PI/2的傾斜表示該工具在表面上是平坦的。

觸摸。定位

定義: touch.orientation.calibration = none | interpolated | vector | default

指定觸摸驅動程式用於報告方向的測量方法。

  • 如果該值none ,則方向未知,因此將其設為0。
  • 如果該值被interpolated ,則將方向線性內插,以使raw.orientation.min對應到-PI/2的原始值,以及raw.orientation.max對應到PI/2的原始值。 (raw.orientation.min + raw.orientation.max) / 2映射為0的中心值。
  • 如果值是vector ,則將方向解釋為兩個簽名的4位元欄位的包裝向量共識。此表示形式用於基於ATMEL物件的協定零件。解碼時,向量會產生方向角度和置信度。置信度的幅度用於擴展大小信息,除非它是幾何信息。
  • 如果值default值,則系統如果可用的方向軸使用interpolated校準,否則none使用。

計算

orientationtilt欄位的計算取決於指定的校準參數和可用輸入。

If touch.tiltX and touch.tiltY are available:
    tiltXCenter = average(raw.tiltX.min, raw.tiltX.max)
    tiltYCenter = average(raw.tiltY.min, raw.tiltY.max)
    tiltXAngle = (raw.tiltX - tiltXCenter) * PI / 180
    tiltYAngle = (raw.tiltY - tiltYCenter) * PI / 180
    output.orientation = atan2(-sin(tiltXAngle), sinf(tiltYAngle))
    output.tilt = acos(cos(tiltXAngle) * cos(tiltYAngle))
Else If touch.orientation.calibration == "interpolated":
    center = average(raw.orientation.min, raw.orientation.max)
    output.orientation = PI / (raw.orientation.max - raw.orientation.min)
    output.tilt = 0
Else If touch.orientation.calibration == "vector":
    c1 = (raw.orientation & 0xF0) >> 4
    c2 = raw.orientation & 0x0F

    If c1 != 0 or c2 != 0:
        If c1 >= 8 Then c1 = c1 - 16
        If c2 >= 8 Then c2 = c2 - 16
        angle = atan2(c1, c2) / 2
        confidence = sqrt(c1*c1 + c2*c2)

        output.orientation = angle

        If touch.size.calibration == "diameter" or "area":
            scale = 1.0 + confidence / 16
            output.touchMajor *= scale
            output.touchMinor /= scale
            output.toolMajor *= scale
            output.toolMinor /= scale
        End If
    Else
        output.orientation = 0
    End If
    output.tilt = 0
Else
    output.orientation = 0
    output.tilt = 0
End If

If orientation aware:
    If screen rotation is 90 degrees:
        output.orientation = output.orientation - PI / 2
    Else If screen rotation is 270 degrees:
        output.orientation = output.orientation + PI / 2
    End If
End If

距離場

distance場描述了工具和觸控設備表面之間的距離。 0.0的值表示直接接觸,較大的值表示與表面的距離增加。

touch.distance。映射

定義: touch.distance.calibration = none | scaled | default

指定觸摸驅動程式報告距離的測量方法。

  • 如果該值none ,則距離是未知的,因此將其設為0。

  • 如果scaled值,則報告的距離乘以恆定尺度因子。

  • 如果值default值,則系統如果可用的距離軸,則使用scaled校準,否則none使用。

touch.distance.scale

定義: touch.distance.scale = <A非負浮點編號>

指定校準中使用的恆定比例因子。

預設值為1.0

計算

distance場的計算取決於指定的校準參數。

If touch.distance.calibration == "scaled":
    output.distance = raw.distance * touch.distance.scale
Else
    output.distance = 0
End If

例子

# Input device configuration file for a touch screen that supports pressure,
# size and orientation. The pressure and size scale factors were obtained
# by measuring the characteristics of the device itself and deriving
# useful approximations based on the resolution of the touch sensor and the
# display.
#
# Note that these parameters are specific to a particular device model.
# Different parameters need to be used for other devices.

# Basic Parameters
touch.deviceType = touchScreen
touch.orientationAware = 1

# Size
# Based on empirical measurements, we estimate the size of the contact
# using size = sqrt(area) * 28 + 0.
touch.size.calibration = area
touch.size.scale = 28
touch.size.bias = 0
touch.size.isSummed = 0

# Pressure
# Driver reports signal strength as pressure.
#
# A normal index finger touch typically registers about 80 signal strength
# units although we don't expect these values to be accurate.
touch.pressure.calibration = amplitude
touch.pressure.scale = 0.0125

# Orientation
touch.orientation.calibration = vector

相容性說明

觸摸設備的配置屬性在Android冰淇淋三明治4.0中發生了顯著變化。必須更新用於觸摸設備的所有輸入設備配置文件,以使用新的配置屬性。

較舊的觸控裝置驅動程式也可能需要更新。

虛擬密鑰映射文件

觸控設備通常用於實現虛擬鍵。

根據觸控控制器的功能,有幾種方法可以做到這一點。可以將一些觸控控制器直接配置為透過設定韌體暫存器來實現軟鍵。其他時候,希望執行從觸控座標到軟體中的鍵代碼的對應。

當軟體中實作虛擬鍵時,核心必須匯出一個稱為virtualkeys.<devicename>作為董事會屬性。例如,如果觸控螢幕裝置驅動程式將其名稱報告為“ touchyfeely”,則虛擬金鑰映射檔案必須具有path /sys/board_properties/virtualkeys.touchyfeely /virtualkeys.touchyfeely。

虛擬密鑰映射檔案描述了觸控螢幕上虛擬鍵的座標和Linux鍵代碼。

除了虛擬密鑰映射文件外,還必須有一個相應的密鑰佈局文件和鍵字符地圖文件,以將Linux鍵代碼映射到Android鍵代碼並指定鍵盤設備的類型(通常是SPECIAL_FUNCTION )。

句法

虛擬密鑰映射文件是一個純文字文件,該文件由一系列由新線或結腸隔開的虛擬鑰匙佈局來描述序列。

評論行以“#”開頭,然後繼續到線路結束。

每個虛擬密鑰都由6個結腸劃分的組件描述:

  • 0x01 :版本代碼。必須始終為0x01
  • <Linux鍵碼>:虛擬鍵的Linux金鑰代碼。
  • <centerx>:虛擬鑰匙中心的X像素座標。
  • <centery>:虛擬鑰匙中心的Y像素座標。
  • <width>:像素中虛擬鍵的寬度。
  • <height>:像素中虛擬鍵的高度。

所有座標和尺寸均根據顯示座標係指定。

這是一個虛擬密鑰映射檔全部寫在一行上。

# All on one line
0x01:158:55:835:90:55:0x01:139:172:835:125:55:0x01:102:298:835:115:55:0x01:217:412:835:95:55

相同的虛擬金鑰映射檔案也可以寫在多行上。

# One key per line
0x01:158:55:835:90:55
0x01:139:172:835:125:55
0x01:102:298:835:115:55
0x01:217:412:835:95:55

在上面的範例中,觸控螢幕的解析度為480x800。因此,所有虛擬鍵的<centery>座標為835,它比觸控螢幕可見區域低一點。

第一個鍵的Linux掃描代碼為158KEY_BACK ),中心X為55 ,百分比為835 ,寬度為90 ,高度為55

例子

虛擬鑰匙地圖檔案: /sys/board_properties/virtualkeys.touchyfeely

0x01:158:55:835:90:55
0x01:139:172:835:125:55
0x01:102:298:835:115:55
0x01:217:412:835:95:55

鑰匙佈局檔: /system/usr/keylayout/touchyfeely.kl

key 158 BACK
key 139 MENU
key 172 HOME
key 217 SEARCH

關鍵字元映射檔: /system/usr/keychars/touchyfeely.kcm

type SPECIAL_FUNCTION

間接多點觸摸指針手勢

在指針模式下,系統解釋以下手勢:

  • 單手指點擊:單擊。
  • 單指運動:移動指針。
  • 單指運動加按鈕按下:拖曳指針。
  • 兩個手指運動朝著相同的方向移動:將區域拖到指針下方。指針本身不會移動。
  • 兩個手指的手指彼此相互移動或朝不同方向移動:鍋子/比例/旋轉指針周圍的區域。指針本身不會移動。
  • 多手指運動:自由形式的手勢。

棕櫚拒絕

從Android 13開始,啟用內建框架時,系統可以自動拒絕手掌的輸入。內部,仍然支援定制的解決方案,儘管在檢測到手掌時可能需要修改它們以返回TOOL_TYPE_PALM標誌。內建框架也與自訂解決方案一起使用。

實際模型查看手勢資料的前90毫秒,當前指針以及周圍的指針,然後考慮觸摸觸摸的邊緣的距離。然後,它以每分的方式決定哪個指針是手掌。如touchMajortouchMinor所報告,它也考慮了每個觸點的大小。然後,Android框架刪除了從觸控流標記為手掌的指針。

如果已經將指標發送到應用程序,則該系統要么:

  • (如果還有其他活動指標)用ACTION_POINTER_UPFLAG_CANCELED set取消指標。
  • (如果這是唯一的指標)用ACTION_CANCEL取消指標。

公共API, MotionEvent.FLAG_CANCELED ,表示當前事件不應觸發使用者操作。此標誌是為ACTION_CANCELACTION_POINTER_UP設定的。

如果棕櫚指針未發送到應用程序,則系統只需刪除指針即可。

啟用棕櫚拒絕

  1. 在您的觸控驅動程式中,使用input_abs_set_res巨集來設定以下欄位的解析度(單位為像素 /毫米):
    • ABS_MT_POSITION_X
    • ABS_MT_POSITION_Y
    • ABS_MT_TOUCH_MAJOR
    • ABS_MT_TOUCH_MINOR

    支援ABS_MT_TOUCH_MINOR是可選的。但是,如果您的設備確實支援它,請確保正確設定了解析度。

  2. 若要確認正確設定
        $ adb shell getevent -li
    
  3. 若要在執行時啟用此功能,請執行:
        $ adb shell device_config put input_native_boot palm_rejection_enabled 1
    
  4. 重新啟動system_server過程。
         $ adb shell stop && adb shell start
        
  5. 確認adb shell dumpsys input表明,不需要UnwantedInteractionBlocker內部有棕櫚拒絕器。如果沒有,請檢查與輸入相關的日誌,以查找可能錯誤配置的線索。

    請參閱以下範例以取得參考:

    UnwantedInteractionBlocker:
      mEnablePalmRejection: true
      isPalmRejectionEnabled (flag value): true
      mPalmRejectors:
        deviceId = 3:
          mDeviceInfo:
            max_x = 
            max_y = 
            x_res = 11.00
            y_res = 11.00
            major_radius_res = 1.00
            minor_radius_res = 1.00
            minor_radius_supported = true
            touch_major_res = 1
            touch_minor_res = 1
          mSlotState:
            mSlotsByPointerId:
    
            mPointerIdsBySlot:
    
          mSuppressedPointerIds: {}
    
  6. 若要永久啟用功能,請在您的init**rc檔案中新增對應的SYSPROP命令:

    setprop persist.device_config.input_native_boot.palm_rejection_enabled 1
    

進一步閱讀