輸入相容性

在 ChromeOS 裝置上,許多使用者會使用鍵盤、滑鼠、觸控板、觸控筆或遊戲搖桿與應用程式互動。雖然這些輸入裝置也適用於 Android 手機,但並不常見,開發人員通常會忽略這些裝置。

如果開發人員想讓應用程式在 ChromeOS 和其他支援 Android 的大螢幕裝置上順利運作,請參考下列最佳化做法:

  • 新增及測試基本鍵盤支援,例如使用方向鍵和 Tab 鍵瀏覽鍵盤、按 Enter 鍵確認文字輸入,以及在媒體應用程式中按空格鍵播放及暫停。
  • 在適用的情況下新增標準鍵盤快速鍵,例如 ctrl+z 可復原,ctrl+s 可儲存。
  • 測試基本的滑鼠互動,方法包括以滑鼠右鍵按一下內容選單、滑鼠遊標懸停圖示變化,以及在自訂檢視畫面上以滑鼠滾輪/觸控板捲動事件。
  • 測試應用程式專屬的輸入裝置,例如繪圖應用程式用的觸控筆、遊戲控制器及音樂應用程式用的 MIDI 控制器。
  • 考慮進階的輸入支援,讓應用程式能在桌面環境中脫穎而出:觸控板可運用於 DJ 應用程式的交替轉換、遊戲的滑鼠擷取等功能,以及進階使用者專屬的擴展鍵盤快速鍵。

鍵盤

應用程式回應鍵盤輸入的方式,有助打造良好的電腦體驗。鍵盤輸入有三種,分別為導覽、按鍵及快速鍵。

鍵盤導覽功能極少用在以觸控為主的應用程式,但使用者如果在操作應用程式時使用鍵盤,會希望有鍵盤導覽的功能。如果使用者有手機和電腦裝置的無障礙需求,這點也非常重要。

許多應用程式都只需要使用方向鍵和分頁導覽功能,大部分可以透過 Android 架構自動處理。舉例來說,Button 的檢視畫面預設為可聚焦,而鍵盤導覽一般不需要任何多餘的程式碼即可運作。如要讓預設為無法聚焦的檢視畫面啟用鍵盤導覽,開發人員應將其標示為可聚焦。您可以透過程式輔助方式或 XML 執行這項操作,如下所示。詳情請參閱「焦點處理」說明文件。

yourView.isFocusable = true

或者,也可以在版面配置檔案中設定 focusable 屬性:

android:focusable="true"

啟用聚焦功能後,Android 架構就會根據位置,建立所有可聚焦檢視畫面的對應導覽。通常這些可正常運作,無須做進一步的處理。如果應用程式的預設對應不正確,可依照以下方式覆寫:

// Arrow keys
yourView.nextFocusLeftId = R.id.view_to_left
yourView.nextFocusRightId = R.id.view_to_right
yourView.nextFocusTopId = R.id.view_above
yourView.nextFocusBottomId = R.id.view_below

// Tab key
yourView.nextFocusForwardId = R.id.next_view

建議在每次發布版本前,嘗試只使用鍵盤存取應用程式的每一個功能。必須可以在不須使用滑鼠或觸控輸入的情況下,存取最常見的操作。

注意:提醒您,對於有無障礙需求的使用者來說,鍵盤支援十分重要。

按鍵輸入

使用螢幕虛擬鍵盤處理的文字輸入功能 (IME),例如 EditText,應用程式要能如預期地在 ChromeOS 上正常運作,且開發人員不需再另行處理。對於架構無法預測的按鍵動作,應用程式必須自行處理其行為。這對於含有自訂檢視畫面的應用程式而言尤其重要。

例如使用 Enter 鍵傳送訊息的即時通訊應用程式、使用空格鍵啟動/停止播放的媒體應用程式,以及透過 w、a、s 和 d 鍵控制移動的遊戲等。

多數應用程式會覆寫 onKeyUp 事件,並為各個收到的鍵盤程式碼新增預期行為,如下所示。

override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
    return when (keyCode) {
        KeyEvent.KEYCODE_ENTER -> {
            sendChatMessage()
            true
        }
        KeyEvent.KEYCODE_SPACE -> {
            playOrPauseMedia()
            true
        }
        else -> super.onKeyUp(keyCode, event)
    }
}

使用 onKeyUp 可避免按下按鍵或釋放緩慢時,應用程式收到多個事件。如果遊戲和應用程式預期使用者會按住鍵盤鍵,可以查詢 onKeyDown 事件。

視應用程式的需求而定,通常為整個 Activity 覆寫 onKeyUp 會提供必要的行為。如有需要,也可以改為將 onKeyListener 新增至特定檢視畫面。舉例來說,應用程式可以只監聽特定 EditText 中的 Enter 鍵,而不是 Activity,以便只有在使用者在聊天方塊輸入時才執行傳送功能。

新增鍵盤支援功能時,請參閱 Android 的鍵盤處理說明文件

捷徑

在電腦環境中,最常使用的是 ctrlaltshift 組成的快速鍵。如果應用程式不執行這些項目,使用者可能會感到困擾,甚至覺得應用程式無法正常運作。進階使用者也喜歡為常用的應用程式特定工作設定快速鍵。快速鍵能讓應用程式使用起來更方便,使其與沒有快捷鍵的應用程式有所區隔。

常見的快速鍵包括儲存 (ctrl+s)、復原 (ctrl+z) 和重做 (ctrl+shift+z)。如需更進階的快速鍵範例,請參閱 VLC Media Player 快速鍵清單。

您可以使用 dispatchKeyShortcutEvent 實作捷徑。這會攔截給定鍵碼的所有中繼資料鍵組合 (altctrlshift)。如要檢查特定的中繼資料鍵,請使用 KeyEvent.isCtrlPressed()KeyEvent.isShiftPressed()KeyEvent.isAltPressed()KeyEvent.hasModifiers()

將快速鍵代碼與其他按鍵動作處理功能 (例如 onKeyUponKeyDown) 分隔開來可以讓程式碼維護起來更加簡單,而且可以開啟預設接受中繼資料鍵的功能,而不需每次都手動實作中繼資料鍵的檢查。對於習慣不同鍵盤配置和作業系統的使用者,允許所有中繼資料鍵的組合使用起來會更加方便。

override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean {
  return when (event.keyCode) {
    KeyEvent.KEYCODE_O -> {
      openFile() // Ctrl+O, Shift+O, Alt+O
      true
    }
    KeyEvent.KEYCODE_Z-> {
      if (event.isCtrlPressed) {
        if (event.isShiftPressed) {
          redoLastAction() // Ctrl+Shift+Z pressed
          true
        } else {
          undoLastAction() // Ctrl+Z pressed
          true
        }
      }
    }
    else -> {
      return super.dispatchKeyShortcutEvent(event)
    }
  }
}

也可以在 onKeyUp 中實作快速鍵,方法是檢查 KeyEvent.isCtrlPressed()KeyEvent.isShiftPressed()KeyEvent.isAltPressed(),方法與上述相同。如果中繼行為對應用程式來說比較像是行為的修改,而不是快捷鍵,維護起來會較為簡單。舉例來說,w 代表「向前走」,而 shift+w 則代表「向前跑」。

override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
  return when(keyCode) {
    KeyEvent.KEYCODE_W-> {
      if (event.isShiftPressed) {
        if (event.isCtrlPressed) {
          flyForward() // Ctrl+Shift+W pressed
          true
        } else {
          runForward() // Shift+W pressed
          true
        }
      } else {
        walkForward() // W pressed
      }
    }
    else -> super.onKeyUp(keyCode, event)
  }
}

支援滑鼠和觸控板

ChromeOS 會自動處理大多數滑鼠和觸控板事件,讓這些事件在 Android 手機上運作時,就像觸控事件一樣。包括雙指觸控板/滑鼠滾輪捲動。大多數應用程式通常只需要處理三個以電腦為主的事件:按一下滑鼠右鍵懸停,以及拖曳

按一下滑鼠右鍵

任何會導致應用程式顯示內容選單的操作 (例如長按清單項目) 也應該回應按一下滑鼠右鍵的事件。如要處理按一下滑鼠右鍵的事件,應用程式應註冊 View.OnContextClickListener。如要進一步瞭解如何建立內容選單,請參閱 Android 內容選單說明文件

yourView.setOnContextClickListener { view ->
  showContextMenu()
  true
}

注意:任何使用 Activity.registerForContextMenu() 註冊內容選單的檢視畫面,都應可使用長按及按一下滑鼠右鍵,而無需註冊內容點擊事件的監聽器。

懸停

開發人員可以透過處理懸停事件,讓應用程式版面配置看起來更精美流暢。這對自訂檢視畫面來說尤其重要。兩個最常見的範例為:

  • 變更滑鼠游標圖示,告訴使用者某元素具有可互動行為 (例如可點擊或可編輯)
  • 當指標懸停在大型清單或格狀項目上時,對項目加上可見的回饋內容
// Change the icon to a "hand" pointer on hover,
// Highlight the view by changing the background.
yourView.setOnHoverListener { view, _ ->
  addVisualHighlighting(true)
  view.pointerIcon =
    PointerIcon.getSystemIcon(applicationContext,
    PointerIcon.TYPE_HAND)
  false // listener did not consume the event.
}

拖曳

在多視窗環境中,使用者會希望可以在不同應用程式之間拖曳項目。這種情況發生於 ChromeOS 裝置,以及處於分割畫面模式的平板電腦、手機和折疊式裝置。

開發人員應考慮使用者是否會將項目拖曳到應用程式中。常見的範例包括:相片編輯器應預期會接收到相片、音訊播放器應預期會接收到音訊檔案,而繪圖程式應預期會接收到相片。

如要新增拖曳支援功能,請參閱 Android 拖曳說明文件和這篇 ChromeOS 網誌文章

ChromeOS 的特殊注意事項

  • 如要處理 ChromeOS「檔案」應用程式中的檔案,請尋找 MIME 類型 application/x-arc-uri-list
  • 請務必使用 requestDragAndDropPermissions 要求權限,存取從應用程式外部拖曳進來的項目
  • 項目必須具有 View.DRAG_FLAG_GLOBAL 旗標,才能拖曳至其他應用程式

支援多選

如果應用程式含有清單或格線,請考慮是否支援多重選取功能,讓使用者受益。使用滑鼠和觸控板時,高品質的多選體驗通常會包含帶狀選取等功能。自行實作這項功能可能很困難,但您可以使用 RecyclerView Selection 程式庫

使用滑鼠和指標選取多個頻段的範例。

進階指標支援

應用程式對滑鼠和觸控板輸入進行進階的處理時,應遵守針對 View.onGenericMotionEvent() 的 Android 說明文件,並使用 MotionEvent.getSource() 來區分 SOURCE_MOUSESOURCE_TOUCHSCREEN

檢查 MotionEvent 以實作必要的行為:

  • 動作會產生 ACTION_HOVER_MOVE 事件
  • 按鈕會產生 ACTION_BUTTON_PRESSACTION_BUTTON_RELEASE 事件。您也可以使用 getButtonState() 查看目前所有滑鼠/觸控板按鈕的狀態。
  • 滑鼠滾輪的捲動會產生 ACTION_SCROLL 事件

觸控筆

許多 Chromebook 都配備觸控筆,Android 應用程式則將其視為觸控螢幕輸入。部分裝置也可能有 USB 或藍牙繪圖桌,例如 Wacom Intuos。Android 應用程式可以接收藍牙輸入,但不支援 USB 輸入。

觸控筆事件會使用 View.onTouchEvent()View.onGenericMotionEvent() 報告為觸控螢幕事件,並包含 SOURCE_STYLUS 類型的 MotionEvent.getSource()MotionEvent 也具有其他資料:

歷史點

Android 會批次處理輸入事件,並以每個頁框傳送一次。觸控筆報告事件的頻率會高於螢幕的頻率。建立繪圖應用程式時,請務必使用 getHistorical API 檢查近期過去的事件:

  • MotionEvent.getHistoricalX()
  • MotionEvent.getHistoricalY()
  • MotionEvent.getHistoricalPressure()
  • MotionEvent.getHistoricalAxisValue()

防止誤觸

ChromeOS 會嘗試辨別使用者的手掌是否停留在觸控螢幕上。然而,不一定都做得到。有時候,在作業系統辨識出手掌之前,系統可能已經向應用程式報告觸控事件。在這種情況下,系統會根據報告的 ACTION_CANCEL 事件取消觸控。

此事件會通知應用程式某些觸控動作無效,而且應該復原由這些觸控產生的所有互動。例如,繪圖應用程式可能會在收到觸控後臨時繪製一個新線條來達到最短的延遲,但只有在連續觸控無誤地完成後,才會將其永久發布至畫布上。如果在此期間取消觸控事件,可清除臨時線條。

注意:如要減少繪圖和撰寫應用程式發生不必要的手掌和手指事件,其中一種方式,就是提供使用者介面設定將觸控繪圖的功能停用,並且在此模式下只用觸控筆繪圖的事件。

筆記應用程式

ChromeOS 有一項特殊意圖,可向使用者顯示已註冊的筆記應用程式。如要將應用程式註冊為筆記應用程式,請在 Android 資訊清單中加入以下內容:

<intent-filter>
    <action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>

使用者完成註冊後,即可將該應用程式選定為預設的筆記應用程式。當系統要求新的筆記時,應用程式應建立一個空白筆記,供觸控筆輸入內容。使用者想要為圖片加上註解時 (例如螢幕截圖或下載圖片),應用程式會以 ClipData 啟動,其中包含一或多個具備 content:// URI 的項目。應用程式應建立一項附註,利用第一個附加的圖片做為背景圖片,並進入使用者透過觸控筆在螢幕上繪圖的模式。

測試不使用觸控筆情況下的筆記意圖

如要測試應用程式是否能正確回應不使用觸控筆情況下的筆記意圖,請使用下列方法顯示筆記選項:

  1. 切換至開發人員模式,將裝置設為寫入模式
  2. 按下 ctrl+alt+f2 開啟終端機
  3. 執行 sudo vi /etc/chrome_dev.conf 指令。
  4. 按下 i 編輯檔案,並在檔案尾端加入一行新的 --ash-enable-palette
  5. 按下 Esc 鍵儲存,然後輸入 :wq,並按下 Enter
  6. 按下 ctrl+alt+f1 鍵,返回一般 ChromeOS UI

檔案櫃現在應該會顯示觸控筆選單:

  • 輕觸檔案櫃中的觸控筆按鈕,然後選擇「New note」。一個空白的繪圖筆記應該會開啟。
  • 擷取螢幕截圖。從檔案櫃中依序選取「stylus button」>「Capture screen」,或是下載一張圖片。通知中應會出現「為圖片加上註解」的選項。這個選項會啟動應用程式,準備為該圖片加上註解。

遊戲控制器

Chromebook 最多可支援四個遊戲控制器。開發人員應使用標準 Android 遊戲控制器 API 來處理這些事件。

按鈕是對應至常用的值,同時使用常見的對應。但很遺憾地,並非所有遊戲控制器製造商都遵守相同的對應慣例。如果可以讓使用者選取不同的熱門控制器對應關係,即可提供更優質的體驗。

輸入平移模式

ChromeOS 預設會啟用輸入平移模式。在大多數的 Android 應用程式中,此模式可讓應用程式在電腦環境中正常運作。例如在觸控板上自動啟用雙指捲動功能、滑鼠滾輪捲動,以及將原始顯示座標對應至視窗座標。一般來說,應用程式開發人員不需自行實作上述任何行為。

如果應用程式執行了自訂的輸入行為 (例如定義自訂的雙指觸控板雙指撥動操作),或是這些輸入平移無法提供應用程式預期的輸入事件,您可以停用輸入平移模式,只要在 Android 資訊清單中加入下列標記即可:

<uses-feature android:name="android.hardware.type.pc"
              android:required="false" />