觸控式裝置

Android 支援多種觸控螢幕和觸控板,包括手寫筆數位板。

觸控螢幕是與螢幕相關聯的觸控裝置,可讓使用者直接操作螢幕上的項目。

觸控板是與螢幕無關聯的觸控裝置,例如數位板。觸控板通常用於指向、絕對間接定位或手勢控制使用者介面。

觸控裝置可能會有功能類似滑鼠按鈕的按鈕。

視基礎觸控感應器技術而定,有時可以使用各種不同的工具 (例如手指或觸控筆) 操作觸控裝置。

觸控裝置有時會用來實作虛擬按鍵。舉例來說,在某些 Android 裝置上,觸控螢幕感應器區域會延伸到螢幕邊緣之外,並兼具觸控式鍵盤的功能。

由於觸控裝置種類繁多,Android 仰賴大量設定屬性,描述每部裝置的特性和預期行為。

觸控裝置分類

如果輸入裝置符合下列兩項條件,就會歸類為多點觸控裝置:

  • 輸入裝置會回報 ABS_MT_POSITION_X 和 ABS_MT_POSITION_Y 絕對軸的存在。
  • 輸入裝置沒有任何遊戲手把按鈕。這項條件可解決某些遊戲手把的模糊問題,這些遊戲手把會回報與 MT 軸重疊的軸。

如果輸入裝置符合下列兩項條件,就會歸類為「單點觸控」裝置:

  • 輸入裝置未歸類為多點觸控裝置。輸入裝置會歸類為單點觸控裝置或多點觸控裝置,不會同時屬於兩者。
  • 輸入裝置會回報 ABS_X 和 ABS_Y 絕對軸的存在,以及 BTN_TOUCH 鍵碼的存在。

如果輸入裝置歸類為觸控裝置,系統會嘗試載入裝置的虛擬按鍵對應檔,判斷是否有虛擬按鍵。如果虛擬按鍵對應可用,系統也會載入裝置的按鍵配置檔案。如要瞭解這些檔案的位置和格式,請參閱「[虛擬按鍵對應檔](#virtual-key-map-files)」。

接著,系統會載入觸控裝置的輸入裝置設定檔。

所有內建觸控裝置都應有輸入裝置設定檔。如果沒有輸入裝置設定檔,系統會選擇適合一般用途觸控周邊裝置 (例如外部 USB 或藍牙 HID 觸控螢幕或觸控板) 的預設設定。這些預設值並非針對內建觸控螢幕設計,可能會導致不正確的行為。

載入輸入裝置設定後,系統會將輸入裝置分類為「觸控螢幕」、「觸控板」或「指標」裝置。

  • 觸控螢幕裝置用於直接操控螢幕上的物件。使用者直接觸控螢幕,因此系統不需要任何額外的預設用途,即可指出要操控的物件。
  • 觸控板裝置用於向應用程式提供絕對定位資訊,說明在特定感應器區域上的觸控操作。這項功能適用於數位板。
  • 「指標」裝置用於透過游標間接操控畫面上的物件。手指會解讀為多點觸控指標手勢。其他工具 (例如觸控筆) 則會使用絕對位置進行解讀。詳情請參閱「間接多點觸控指標手勢」。

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

  • 如果設定 touch.deviceType 屬性,系統會按照指示設定裝置類型。
  • 如果輸入裝置回報存在 INPUT_PROP_DIRECT 輸入屬性 (透過 EVIOCGPROP ioctl),則裝置類型會設為「觸控螢幕」。這項條件假設直接輸入觸控裝置已連接到同樣已連接的螢幕。
  • 如果輸入裝置回報存在 INPUT_PROP_POINTER 輸入屬性 (透過 EVIOCGPROP ioctl),則裝置類型會設為「指標」。
  • 如果輸入裝置回報存在 REL_X 或 REL_Y 相對軸,則裝置類型會設為「觸控板」。這項條件可解決由滑鼠和觸控板組成的輸入裝置模稜兩可的問題。在這種情況下,觸控板不會用於控制指標,因為滑鼠已控制指標。
  • 否則,裝置類型會設為 pointer。這項預設設定可確保未指定任何其他特殊用途的觸控板可控制指標。

按鈕

按鈕是選用控制項,應用程式可用來執行其他功能。觸控裝置上的按鈕行為與滑鼠按鈕類似,主要用於指標類型觸控裝置或觸控筆。

支援的按鈕如下:

  • BTN_LEFT:對應至 MotionEvent.BUTTON_PRIMARY。
  • BTN_RIGHT:對應至 MotionEvent.BUTTON_SECONDARY。
  • BTN_MIDDLE:對應至 MotionEvent.BUTTON_MIDDLE。
  • BTN_BACK 和 BTN_SIDE:對應至 MotionEvent.BUTTON_BACK。 按下這個按鈕也會合成按鍵代碼為 KeyEvent.KEYCODE_BACK 的按鍵。
  • BTN_FORWARD 和 BTN_EXTRA:對應至 MotionEvent.BUTTON_FORWARD。按下這個按鈕也會合成按鍵碼為 KeyEvent.KEYCODE_FORWARD 的按鍵。
  • BTN_STYLUS:對應至 MotionEvent.BUTTON_SECONDARY。
  • BTN_STYLUS2:對應至 MotionEvent.BUTTON_TERTIARY。

工具和工具類型

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

在 Android 的其他部分 (例如 MotionEvent API),工具通常稱為「指標」。

支援的工具類型如下:

  • BTN_TOOL_FINGER 和 MT_TOOL_FINGER:對應至 MotionEvent.TOOL_TYPE_FINGER。
  • BTN_TOOL_PEN 和 MT_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_DOUBLETAP、BTN_TOOL_TRIPLETAP和 BTN_TOOL_QUADTAP:對應至 MotionEvent.TOOL_TYPE_FINGER。

懸停與觸控工具

工具可以與觸控裝置接觸,也可以在觸控裝置的範圍內懸停。並非所有觸控裝置都能感應到工具懸停在觸控裝置上方。而支援這項功能的工具 (例如 RF 觸控筆數位板),通常可以偵測工具是否在數位板的有限範圍內。

InputReader 元件會區分觸控工具和懸停工具。同樣地,觸控工具和懸停工具也會以不同方式向應用程式回報。

觸控工具會使用 MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_DOWN、MotionEvent.ACTION_POINTER_DOWN 和 MotionEvent.ACTION_POINTER_UP,向應用程式回報為觸控事件。

懸停工具會使用 MotionEvent.ACTION_HOVER_ENTER、MotionEvent.ACTION_HOVER_MOVE 和 MotionEvent.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_LEFT、BTN_RIGHT、BTN_MIDDLE、BTN_BACK、BTN_SIDE、BTN_FORWARD、BTN_EXTRA、BTN_STYLUS、BTN_STYLUS2:(選用) 回報按鈕狀態。
    • BTN_TOOL_FINGER、BTN_TOOL_PEN、BTN_TOOL_RUBBER、BTN_TOOL_BRUSH、BTN_TOOL_PENCIL、BTN_TOOL_AIRBRUSH、BTN_TOOL_MOUSE、BTN_TOOL_LENS、BTN_TOOL_DOUBLETAP、BTN_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_FINGER 或 MT_TOOL_PEN。
    • ABS_MT_TRACKING_ID:(選用) 回報工具的追蹤 ID。追蹤 ID 是任意非負整數,用於在多個工具啟用時,獨立識別及追蹤每個工具。舉例來說,當多根手指觸碰裝置時,每根手指都應獲派不同的追蹤 ID,只要手指仍與裝置接觸,就會使用該 ID。如果相關聯的工具移出範圍,追蹤 ID 就能重複使用。
    • ABS_MT_SLOT:(選用) 使用 Linux 多點觸控通訊協定「B」時,回報工具的槽 ID。詳情請參閱 Linux 多點觸控通訊協定說明文件。
    • BTN_TOUCH:(必要) 指出工具是否觸碰裝置。
    • BTN_LEFT、BTN_RIGHT、BTN_MIDDLE、BTN_BACK、BTN_SIDE、BTN_FORWARD、BTN_EXTRA、BTN_STYLUS、BTN_STYLUS2:(選用) 回報按鈕狀態。
    • BTN_TOOL_FINGER、BTN_TOOL_PEN、BTN_TOOL_RUBBER、BTN_TOOL_BRUSH、BTN_TOOL_PENCIL、BTN_TOOL_AIRBRUSH、BTN_TOOL_MOUSE、BTN_TOOL_LENS、BTN_TOOL_DOUBLETAP、BTN_TOOL_TRIPLETAP、BTN_TOOL_QUADTAP:(選用) 回報工具類型。
  • 如果同時定義單點觸控和多點觸控通訊協定的軸,系統只會使用多點觸控軸,並忽略單點觸控軸。
  • ABS_X、ABS_Y、ABS_MT_POSITION_X 和 ABS_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_PRESSURE 或 ABS_MT_PRESSURE 回報值,則工具觸碰裝置時的值必須為非零,否則為零,表示工具懸停。

    回報壓力資訊為選用,但強烈建議提供。 應用程式可以使用壓力資訊,實作感壓繪圖和其他效果。

  • 當工具觸碰裝置時,ABS_TOOL_WIDTH、ABS_MT_TOUCH_MAJOR、ABS_MT_TOUCH_MINOR、ABS_MT_WIDTH_MAJOR 或 ABS_MT_WIDTH_MINOR 回報的值應為非零值,否則應為零,但這並非必要。舉例來說,觸控裝置可能可以測量手指觸控接觸點的大小,但無法測量觸控筆觸控接觸點的大小。

    尺寸資訊為選填,但強烈建議提供。 應用程式可使用壓力資訊,實作與大小相關的繪圖和其他效果。

  • 當工具觸碰裝置時,ABS_DISTANCE 或 ABS_MT_DISTANCE 回報的值應接近零。即使工具直接接觸,距離仍可能不為零。回報的確切值取決於硬體測量距離的方式。

    回報距離資訊為選用,但建議用於觸控筆裝置。

  • 當工具與裝置垂直時,ABS_TILT_X 和 ABS_TILT_Y 回報的值應為零。非零傾斜度表示工具傾斜。

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

    InputReader 會將 X 和 Y 傾斜元件轉換為垂直傾斜角度 (範圍為 0 到 PI / 2 弧度) 和平面方向角度 (範圍為 -PI 到 PI 弧度)。這種表示法會產生與描述手指觸控時所用方向相容的方向描述。

    不一定要回報傾斜資訊,但建議觸控筆裝置回報。

  • 如果工具類型是由 ABS_MT_TOOL_TYPE 回報,則會取代 BTN_TOOL_* 回報的任何工具類型資訊。如果完全沒有工具類型資訊,工具類型會預設為 MotionEvent.TOOL_TYPE_FINGER。

  • 符合下列條件的工具會判定為有效:

    • 使用單點觸控通訊協定時,如果 BTN_TOUCH 或 BTN_TOOL_* 為 1,工具就會啟用。

      這項條件表示 InputReader 至少需要一些關於工具性質的資訊,無論是工具是否接觸,或至少是工具類型。如果沒有可用資訊,系統會假設工具處於非使用中狀態 (超出範圍)。

    • 使用多點觸控通訊協定「A」時,只要工具出現在最新的同步報表中,就表示工具處於啟用狀態。當工具不再出現在同步報表中,即表示該工具已不存在。
    • 使用多點觸控通訊協定「B」時,只要工具具有有效版位,就會處於有效狀態。清除該欄位後,工具就會消失。
  • 系統會根據下列條件判斷工具是否懸停:
    • 如果工具是 BTN_TOOL_MOUSE 或 BTN_TOOL_LENS,則即使符合下列任一條件,工具也不會懸停。
    • 如果工具處於有效狀態,且驅動程式回報壓力資訊,且回報的壓力為零,則工具會懸停。
    • 如果工具處於啟用狀態,且驅動程式支援 BTN_TOUCH 按鍵代碼,且 BTN_TOUCH 的值為零,則工具處於懸停狀態。
  • InputReader 支援多點觸控通訊協定「A」和「B」。新驅動程式應使用「B」通訊協定,但兩者皆可。
  • 自 Android 4.0 起,觸控螢幕驅動程式可能需要變更,才能符合 Linux 輸入通訊協定規格。

    可能需要進行下列變更:

    • 當工具變成非使用中狀態 (手指「向上」) 時,就不應再出現在後續的多點觸控同步報告中。當所有工具都處於非使用中狀態 (所有手指都「向上」) 時,驅動程式應傳送空白同步報表封包,例如 SYN_MT_REPORT 後面接著 SYN_REPORT。

      舊版 Android 預期會透過傳送 0 的壓力值來回報「up」事件。舊版行為與 Linux 輸入通訊協定規格不相容,因此不再支援。

    • 應使用 ABS_MT_PRESSURE 回報實際壓力或訊號強度資訊。

      舊版 Android 會從 ABS_MT_TOUCH_MAJOR 擷取壓力資訊。舊行為與 Linux 輸入通訊協定規格不相容,因此不再支援。

    • 觸控大小資訊應使用 ABS_MT_TOUCH_MAJOR 回報。

      舊版 Android 會從 ABS_MT_TOOL_MAJOR 擷取大小資訊。舊行為與 Linux 輸入通訊協定規格不相容,因此不再支援。

    觸控裝置驅動程式不再需要 Android 專屬自訂。 Android 採用標準 Linux 輸入通訊協定,因此可使用未經修改的驅動程式,支援更多元的觸控周邊裝置,例如外接 HID 多點觸控螢幕。

觸控式裝置操作

以下簡要說明 Android 上的觸控裝置操作。

  1. EventHub 會從 evdev 驅動程式讀取原始事件。
  2. InputReader 會使用原始事件,並更新各項工具位置和其他特性的內部狀態。同時也會追蹤按鈕狀態。
  3. 如果按下或放開 BACK 或 FORWARD,InputReader 會通知 InputDispatcher 關於按鍵事件。
  4. InputReader 會判斷是否發生虛擬按鍵動作。如果是,則會向 InputDispatcher 通知重要事件。
  5. InputReader 會判斷觸控是否在螢幕範圍內啟動。如果是,則會通知 InputDispatcher 觸控事件。
  6. 如果沒有觸控工具,但至少有一個懸停工具,InputReader 會向 InputDispatcher 通知懸停事件。
  7. 如果觸控裝置類型為指標,InputReader 會執行指標手勢偵測、移動指標和相應點,並通知 InputDispatcher 指標事件。
  8. InputDispatcher 會使用 WindowManagerPolicy 判斷是否應調度事件,以及是否應喚醒裝置。接著,InputDispatcher 會將事件傳送至適當的應用程式。

觸控裝置設定

觸控裝置的行為取決於裝置的軸、按鈕、輸入屬性、輸入裝置設定、虛擬按鍵對應和按鍵配置。

如要進一步瞭解參與鍵盤設定的檔案,請參閱下列各節:

屬性

系統會依據多項輸入裝置設定屬性,設定及校正觸控裝置行為。

其中一個原因是,觸控裝置的裝置驅動程式通常會使用裝置專屬單位回報觸控特性。

舉例來說,許多觸控裝置會使用裝置專屬的內部比例來測量觸控接觸區域,例如觸控觸發的感應器節點總數。這個原始大小值對應用程式沒有意義,因為應用程式需要知道觸控裝置感應器節點的實體大小和其他特性。

系統會使用輸入裝置設定檔中編碼的校正參數,將觸控裝置回報的值解碼、轉換及正規化,變成應用程式可理解的簡單標準表示法。

說明文件慣例

為方便說明,我們使用下列慣例來描述系統在校正過程中使用的值。

原始軸值

下列運算式代表觸控裝置驅動程式回報為 EV_ABS 事件的原始值。

raw.x
ABS_X 或 ABS_MT_POSITION_X 軸的值。
raw.y
ABS_Y 或 ABS_MT_POSITION_Y 軸的值。
raw.pressure
ABS_PRESSURE 或 ABS_MT_PRESSURE 軸的值,如果無法取得則為 0。
raw.touchMajor
ABS_MT_TOUCH_MAJOR 軸的值,如果無法取得則為 0。
raw.touchMinor
ABS_MT_TOUCH_MINOR 軸的值,如果無法使用,則為 raw.touchMajor。
raw.toolMajor
ABS_TOOL_WIDTH 或 ABS_MT_WIDTH_MAJOR 軸的值,如果無法取得,則為 0。
raw.toolMinor
ABS_MT_WIDTH_MINOR 軸的值,如果無法使用,則為 raw.toolMajor。
raw.orientation
ABS_MT_ORIENTATION 軸的值,如果無法取得則為 0。
raw.distance
ABS_DISTANCE 或 ABS_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
原始軸的準確度。例如,模糊 = 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

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

指定指標手勢的呈現模式。只有在觸控裝置類型為 pointer 時,這項設定屬性才相關。

  • 如果值為 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、size 欄位

touchMajor 和 touchMinor 欄位會以輸出單位 (像素) 描述接觸區域的大致尺寸。

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

size 欄位說明觸控裝置可感應到的最大可能觸控大小,相對於觸控大小的正規化大小。最小的標準化大小為 0.0 (未接觸或無法測量),最大的標準化大小為 1.0 (感應器區域已飽和)。

如果可以測量大致的長度和寬度,則 touchMajor 欄位會指定接觸區域的較長維度,而 touchMinor 欄位會指定較短維度。如果只能測量接觸區域的大致直徑,則 touchMajor 和 touchMinor 欄位的值會相同。

同樣地,toolMajor 欄位會指定工具橫截面積的長邊,toolMinor 欄位則會指定短邊。

如果無法取得觸控大小,但可以取得工具大小,則工具大小會設為等於觸控大小。相反地,如果工具大小無法使用,但觸控大小可用,則觸控大小會設為等於工具大小。

觸控裝置會以各種方式測量或回報觸控大小和工具大小。目前的實作支援三種不同的測量方式:直徑、面積和幾何定界框 (以表面單位表示)。

<touch.size.calibration< h4=""></touch.size.calibration<>

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

指定觸控驅動程式用於回報觸控大小和工具大小的測量類型。

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

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

  • 如果值為 diameter,系統會假設大小與觸控或工具的直徑 (寬度) 成正比。

  • 如果值為 area,系統會假設大小與觸控或工具的面積成正比。

  • 如果值為 default,系統會在 raw.touchMajor 或 raw.toolMajor 軸可用時使用 geometric 校正,否則會使用 none 校正。

touch.size.scale

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

指定校正時使用的常數縮放比例係數。

預設值為 1.0。

touch.size.bias

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

指定校正時使用的常數偏差值。

預設值為 0.0。

touch.size.isSummed

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

指定大小要回報為所有有效聯絡人的大小總和,還是個別回報每個聯絡人的大小。

  • 如果值為 1,系統會先將回報的大小除以聯絡人數量,再使用該值。

  • 如果值為 0,則會直接使用回報的大小。

預設值為 0。

部分觸控裝置 (尤其是「Semi-MT」裝置) 無法區分多個接觸點的個別尺寸,因此會回報代表總面積或寬度的尺寸測量值。這類裝置的這個屬性只能設為 1。如有疑慮,請將這個值設為 0。

計算方式

touchMajor、touchMinor、toolMajor、toolMinor 和 size 欄位的計算方式取決於指定的校正參數。

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

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

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

  • 如果值為 none,則壓力不明,因此在觸控時會設為 1.0,懸停時則設為 0.0。

  • 如果值為 physical,系統會假設壓力軸會測量施加在觸控板上的實際物理壓力強度。

  • 如果值為 amplitude,系統會假設壓力軸測量的是信號振幅,這與接觸面積和施加的壓力有關。

  • 如果值為 default,系統會在壓力軸可用時使用 physical 校正,否則使用 none。

touch.pressure.scale

&定義: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 表示主軸向右。如果使用觸控筆工具,方向範圍可以描述為 -PI 或 PI 的完整圓形範圍。

tilt 欄位會以角度測量值描述工具的傾斜度。傾斜度為 0 表示工具與表面垂直。傾斜度為 PI/2 表示工具平放在表面上。

touch.orientation.calibration

定義: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。

計算方式

orientation 和 tilt 欄位的計算方式取決於指定的校正參數和可用輸入內容。

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.calibration

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

指定觸控驅動程式用於回報距離的測量類型。

  • 如果值為 none,表示距離不明,因此設為 0。

  • 如果值為 scaled,系統會將回報的距離乘以常數縮放比例係數。

  • 如果值為 default,系統會在距離軸可用時使用 scaled 校正,否則會使用 none。

touch.distance.scale

&定義:touch.distance.scale = <非負浮點數>

指定校正時使用的常數縮放比例係數。

預設值為 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 Ice Cream Sandwich 4.0 中,觸控裝置的設定屬性有大幅變更。觸控裝置的所有輸入裝置設定檔都必須更新,才能使用新的設定屬性。

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

虛擬按鍵對應檔

觸控裝置可用於實作虛擬按鍵。

視觸控控制器的功能而定,有幾種方法可以做到這一點。部分觸控控制器可透過設定韌體暫存器,直接設定為實作軟鍵。有時,您可能需要在軟體中執行從觸控座標到按鍵代碼的對應。

在軟體中實作虛擬按鍵時,核心必須將名為 virtualkeys.<devicename> 的虛擬按鍵對應檔匯出為板屬性。舉例來說,如果觸控螢幕裝置驅動程式將其名稱回報為「touchyfeely」,則虛擬按鍵對應檔必須具有路徑 /sys/board_properties/virtualkeys.touchyfeely。

虛擬按鍵對應檔會說明觸控螢幕上虛擬按鍵的座標和 Linux 按鍵代碼。

除了虛擬按鍵對應檔外,還必須有對應的按鍵配置檔和按鍵字元對應檔,才能將 Linux 按鍵代碼對應至 Android 按鍵代碼,並指定鍵盤裝置的類型 (通常為 SPECIAL_FUNCTION)。

語法

虛擬按鍵對應檔是純文字檔案,由一連串虛擬按鍵配置說明組成,並以換行符號或冒號分隔。

註解行以「#」開頭,並持續到行尾。

每個虛擬金鑰都由 6 個以冒號分隔的元件描述:

  • 0x01:版本代碼。必須一律為 0x01。
  • <Linux key code>:虛擬按鍵的 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 掃描碼為 158 (KEY_BACK),centerX 為 55,centerY 為 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 毫秒、目前指標和周圍指標,然後考量觸控點與螢幕邊緣的距離。接著,系統會根據每個指標判斷哪些指標是手掌。此外,系統也會考量 touchMajor 和 touchMinor 回報的每個聯絡人大小。接著,Android 架構會從觸控串流中移除標示為手掌的指標。

如果指標已傳送至應用程式,系統會執行下列其中一項操作:

  • (如有其他使用中的指標) 取消設定 ACTION_POINTER_UP 和 FLAG_CANCELED 的指標。
  • (如果這是唯一的指標) 使用 ACTION_CANCEL 取消指標。

公開 API MotionEvent.FLAG_CANCELED 表示目前事件不應觸發使用者動作。這個旗標會同時為 ACTION_CANCEL 和 ACTION_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
    

其他資訊