觸控式裝置

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) 的存在情形,則裝置類型會設為「觸控螢幕」。這個條件假設直接輸入觸控裝置已連接至同樣已連結的螢幕。
  • 如果輸入裝置回報 INPUT_PROP_POINTER 輸入屬性 (透過 EVIOCGPROP ioctl) 的存在,則裝置類型會設為「pointer」
  • 如果輸入裝置回報相對軸是否出現 REL_XREL_Y,則裝置類型會設為觸控板。這個條件可解決輸入裝置同時包含滑鼠和觸控板的模糊情況。在這種情況下,由於滑鼠已控制游標,因此觸控板不會用於控制游標。
  • 否則,裝置類型會設為「pointer」。這項預設值可確保未指定任何其他特殊用途的觸控板控制游標。

按鈕

按鈕是「選用」的控制項,應用程式可用於執行其他功能。觸控裝置上的按鈕與滑鼠按鈕的運作方式類似,主要用於搭配指標類型的觸控裝置或觸控筆使用。

系統支援下列按鈕:

  • 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

懸停與觸碰工具

工具可以與觸控裝置聯絡,也可以位於目標範圍內,並懸停在裝置上方。並非所有觸控裝置都能偵測到在觸控裝置上方懸停的工具。支援觸控筆數位板的工具 (例如 RF 數位板) 通常可以偵測到工具是否位於數位板的限制範圍內。

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_MOUSEBTN_TOOL_LENSBTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAPBTN_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_MOUSEBTN_TOOL_LENSBTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAPBTN_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. 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_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

定義: 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 欄位

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

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

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

預設值為 1.0

touch.size.bias

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

定義: 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 表示主要軸向右。當觸控筆工具存在時,可使用 -PIPI 的整個圓形範圍來說明螢幕方向範圍。

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

計算方式

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.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 鍵碼>:虛擬鍵的 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,width 為 90,height 為 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 的指標。
  • (如果這是唯一的指標) 使用 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
    

其他資訊