開發應用程序

以下材料適用於應用程序開發人員。

要使您的應用支持輪播,您必須:

  1. 放置FocusParkingView在各自的活動佈局。
  2. 確保可(或不可)聚焦的視圖。
  3. 使用FocusArea s到環繞你的所有可獲得焦點的看法,除了FocusParkingView

在您設置環境以開發支持旋轉的應用程序後,下面詳細介紹了這些任務中的每一個。

設置旋轉控制器

在開始開發支持旋轉的應用程序之前,您需要一個旋轉控制器或一個替身。您有以下描述的選項。

模擬器

source build/envsetup.sh && lunch car_x86_64-userdebug
m -j
emulator -wipe-data -no-snapshot -writable-system

您還可以使用aosp_car_x86_64-userdebug

要訪問模擬旋轉控制器:

  1. 點擊工具欄底部的三個點:

    訪問模擬旋轉控制器
    圖1.訪問仿真旋轉控制器
  2. 汽車在擴展控件窗口旋轉

    選擇汽車旋轉
    圖2.選擇租車旋轉

USB鍵盤

  • 將 USB 鍵盤插入 Seahawk(在某些情況下,這可能會阻止屏幕鍵盤出現)。
  • 使用userdebugeng建設。
  • 啟用關鍵事件過濾:
    adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
    
  • 請參閱下表以查找每個操作的相應鍵:
    鑰匙旋轉動作
    逆時針旋轉
    順時針旋轉
    一種向左輕推
    D向右輕推
    輕推
    輕推
    F 或逗號中心按鈕
    R 或 Esc返回鍵

亞行命令

您可以使用car_service命令注入旋轉輸入事件。這些命令可以在 Seahawk 或模擬器上運行。

car_service 命令旋轉輸入
adb shell cmd car_service inject-rotary逆時針旋轉
adb shell cmd car_service inject-rotary -c true順時針旋轉
adb shell cmd car_service inject-rotary -dt 100 50逆時針旋轉多次(100 毫秒前和 50 毫秒前)
adb shell cmd car_service inject-key 282向左輕推
adb shell cmd car_service inject-key 283向右輕推
adb shell cmd car_service inject-key 280輕推
adb shell cmd car_service inject-key 281輕推
adb shell cmd car_service inject-key 23單擊中心按鈕
adb shell input keyevent inject-key 4點擊返回按鈕

OEM 旋轉控制器

當您的旋轉控制器硬件啟動並運行時,這是最現實的選擇。它對於測試快速旋轉特別有用。

焦點停車視圖

FocusParkingView是在一個透明的視圖汽車UI庫(車的UI庫)RotaryService用它來支持旋轉控制器導航。 FocusParkingView必須在佈局中的第一個可聚焦的觀點。必須放在外面的所有FocusArea秒。每個窗口都必須有一個FocusParkingView 。如果你已經在使用汽車的UI庫基地佈局,其中包含一個FocusParkingView ,你不需要添加另一個FocusParkingView 。下面顯示的是一個示例FocusParkingViewRotaryPlayground

<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <com.android.car.ui.FocusParkingView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
   <FrameLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
</FrameLayout>

下面是你需要一個理由FocusParkingView

  1. 當焦點設置在另一個窗口中時,Android 不會自動清除焦點。如果您嘗試清除前一個窗口中的焦點,Android 會重新聚焦該窗口中的視圖,這會導致兩個窗口同時聚焦。添加FocusParkingView到每個窗口可以解決這個問題。這個視圖是透明的,並且它的默認焦點突出顯示是禁用的,因此無論是否聚焦,它對用戶都是不可見的。它可以工作重點, RotaryService為重點,以去除重點亮點。
  2. 如果只有一個FocusArea在當前窗口中,旋轉在控制器FocusArea使RotaryService將焦點從視圖中移動右側到左側(反之亦然)的圖。將此視圖添加到每個窗口可以解決問題。當RotaryService判斷調焦目標是FocusParkingView ,它能確定一個迴繞即將發生,在該點它避免了由不運動焦點纏繞。
  3. 當旋轉控制發射一個應用程序,機器人把第一可聚焦的視圖,它始終是FocusParkingView 。所述FocusParkingView確定最佳視圖專注於,然後應用焦點。

可聚焦視圖

RotaryService建立在Android框架的現有觀點的重點概念,可以追溯到當手機有物理鍵盤和d-墊。現有的android:nextFocusForward屬性重新用於旋轉(參見FocusArea定制),但android:nextFocusLeftandroid:nextFocusRightandroid:nextFocusUp ,和android:nextFocusDown不是。

RotaryService只關注看法是可獲得焦點。一些觀點,比如Button S,通常可獲得焦點。其它如TextView S和ViewGroup S,通常都沒有。可點擊的視圖是自動聚焦的,當它們有一個點擊監聽器時,視圖會自動點擊。如果此自動邏輯導致所需的可聚焦性,則無需顯式設置視圖的可聚焦性。如果自動邏輯不以期望的可聚焦導致,設置android:focusable屬性為truefalse用,或以編程方式設置視圖的可聚焦View.setFocusable(boolean) 。對於RotaryService把重點放在它的視圖,必須滿足以下要求:

  • 可對焦
  • 啟用
  • 可見的
  • 具有非零值的寬度和高度

如果一個視圖不滿足所有這些要求,例如一個可聚焦但被禁用的 Button,用戶將無法使用旋轉控件來聚焦它。如果你想專注於殘疾人的意見,可以考慮使用自定義的狀態,而不是android:state_enabled來控制如何看法似乎沒有表明Android的應該考慮禁用它。您的應用程序可以通知用戶為什麼在點擊時禁用視圖。下一節將說明如何執行此操作。

自定義狀態

添加自定義狀態:

  1. 要在添加自定義屬性到您的視圖。例如,為了添加一個state_rotary_enabled定制狀態向CustomView視圖類,使用:
    <declare-styleable name="CustomView">
        <attr name="state_rotary_enabled" format="boolean" />
    </declare-styleable>
    
  2. 要跟踪此狀態下,實例變量添加到您的視圖與存取方法一起:
    private boolean mRotaryEnabled;
    public boolean getRotaryEnabled() { return mRotaryEnabled; }
    public void setRotaryEnabled(boolean rotaryEnabled) {
        mRotaryEnabled = rotaryEnabled;
    }
    
  3. 讀你的屬性值視圖創建時:
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
    mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
    
  4. 在您的視圖類,覆蓋onCreateDrawableState()方法,然後添加自定義的狀態,在適當的時候。例如:
    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mRotaryEnabled) extraSpace++;
        int[] drawableState = super.onCreateDrawableState(extraSpace);
        if (mRotaryEnabled) {
            mergeDrawableStates(drawableState, { R.attr.state_rotary_enabled });
        }
        return drawableState;
    }
    
  5. 使視圖的單擊處理程序根據其狀態執行不同的操作。例如,點擊處理程序可能什麼也不做,或者它可能會彈出一個敬酒時mRotaryEnabledfalse
  6. 為了使按鈕顯示為禁用,在您看來的背景繪製,使用app:state_rotary_enabled而不是android:state_enabled 。如果你不已經擁有了它,你就需要添加:
    xmlns:app="http://schemas.android.com/apk/res-auto"
    
  7. 如果您認為在任何佈局禁用,則更換android:enabled="false"app:state_rotary_enabled="false" ,然後添加app的命名空間,如上面。
  8. 如果你的觀點是編程禁用,取而代之以電話setEnabled()與調用setRotaryEnabled()

重點地區

使用FocusAreas的可聚焦的觀點劃分成塊,使導航更容易,要與其他應用程序一致。例如,如果你的應用程序有一個工具欄,工具欄應該是在一個單獨的FocusArea從您的應用程序的其餘部分。標籤欄和其他導航元素也應該與應用程序的其餘部分分開。大名單一般應該有自己的FocusArea 。如果沒有,用戶必須輪換整個列表才能訪問某些視圖。

FocusArea是的子類LinearLayout在車上的UI庫。如果啟用此功能,一個FocusArea時,其後代的一個重點是將繪製的一大亮點。要了解更多信息,請參閱聚焦亮點定制

當創建佈局文件導航塊,如果你打算使用LinearLayout作為該區塊的容器,使用FocusArea代替。否則,包裹在塊FocusArea

嵌套FocusArea在另一個FocusArea 。這樣做會導致未定義的導航行為。確保所有可獲得焦點的視圖嵌套在中FocusArea

一的一個例子FocusAreaRotaryPlayground如下所示:

<com.android.car.ui.FocusArea
       android:layout_margin="16dp"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">
       <EditText
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:singleLine="true">
       </EditText>
   </com.android.car.ui.FocusArea>

FocusArea的工作原理如下:

  1. 在處理旋轉和微調動作, RotaryService查找的情況下FocusArea視圖層次結構。
  2. 當接收到一個旋轉事件, RotaryService將焦點移動到另一個視圖,可以採取焦點在同一個FocusArea
  3. 當接收到微移事件, RotaryService移動焦點,可以採取焦點在另一個(通常是相鄰的)另一視圖FocusArea

如果不包含任何FocusAreas在你的佈局,根視圖被視為隱含的重點領域。用戶無法輕推在應用程序中導航。相反,它們將在所有可聚焦的視圖中旋轉,這對於對話框來說可能已經足夠了。

焦點區域定制

兩個標準視圖屬性可用於自定義旋轉導航:

  • android:nextFocusForward允許應用程序開發人員指定在重點領域的旋轉順序。這與用於控制鍵盤導航的 Tab 順序的屬性相同。使用此屬性來創建一個循環。相反,使用app:wrapAround (見下文),以創建一個循環。
  • android:focusedByDefault允許應用程序開發人員指定的窗口中默認焦點視圖。使用此屬性和app:defaultFocus (見下文)在同一FocusArea

FocusArea還定義了一些屬性自定義旋轉導航。無法使用這些屬性自定義隱式焦點區域。

  1. (11的Android QPR3,機器人11汽車,機器人12)
    app:defaultFocus可用於指定可聚焦後裔視圖的ID,該ID應集中在當用戶輕推到這個FocusArea
  2. (11的Android QPR3,機器人11汽車,機器人12)
    app:defaultFocusOverridesHistory可以設置為true ,以使上述採取集中指定的視圖,即使與歷史表明在這另一種觀點認為FocusArea一直專注於。
  3. 機器人12)
    使用app:nudgeLeftShortcutapp:nudgeRightShortcutapp:nudgeUpShortcut ,和app:nudgeDownShortcut指定可聚焦的後代視圖的ID,該ID應集中在當在給定方向上的用戶輕推。要了解更多信息,請參閱內容微調快捷鍵的下方。

    (11的Android QPR3,機器人11汽車,Android中12棄用app:nudgeShortcutapp:nudgeShortcutDirection僅支持一個微移的快捷方式。

  4. (11的Android QPR3,機器人11汽車,機器人12)
    為了使旋轉包裹在這周圍FocusAreaapp:wrapAround可以設置為true 。這在視圖排列成圓形或橢圓形時最常用。
  5. (11的Android QPR3,機器人11汽車,機器人12)
    要調整亮點填充在這個FocusArea ,使用app:highlightPaddingStartapp:highlightPaddingEndapp:highlightPaddingTopapp:highlightPaddingBottomapp:highlightPaddingHorizontalapp:highlightPaddingVertical
  6. (11的Android QPR3,機器人11汽車,機器人12)
    要調整此的感知範圍FocusArea找到一個輕推目標,使用app:startBoundOffsetapp:endBoundOffsetapp:topBoundOffsetapp:bottomBoundOffsetapp:horizontalBoundOffsetapp:verticalBoundOffset
  7. (11的Android QPR3,機器人11汽車,機器人12)
    明確指定的相鄰的ID FocusArea在給定方向上,使用(或區域) app:nudgeLeftapp:nudgeRightapp:nudgeUp ,和app:nudgeDown 。當默認使用的幾何搜索未找到所需目標時,請使用此選項。

微調通常在 FocusAreas 之間導航。但隨著輕推的快捷鍵,一內輕推,有時首先導航FocusArea使用戶可能需要兩次輕推導航到下一個FocusArea 。微調快捷方式時很有FocusArea包含一個長長的名單,然後一個浮動操作按鈕,如下面的例子:

輕推快捷方式
圖3.微調快捷方式

如果沒有輕推快捷方式,用戶將不得不在整個列表中旋轉才能到達 FAB。

焦點高亮定制

如上所述, RotaryService建立在Android框架的現有視圖焦點的概念。當用戶轉動和輕推, RotaryService移動聚焦各處,聚焦一個視圖和unfocusing另一個。在 Android 中,當一個視圖被聚焦時,如果視圖:

  • 指定了自己的焦點高亮,Android 繪製視圖的焦點高亮。
  • 不指定焦點高亮,並且默認焦點高亮未禁用,Android 為視圖繪製默認焦點高亮。

專為觸控設計的應用程序通常不會指定適當的焦點突出顯示。

默認焦點突出顯示由 Android 框架提供,並且可由 OEM 覆蓋。應用程序開發人員接受,當他們正在使用的主題源自Theme.DeviceDefault

為了獲得一致的用戶體驗,請盡可能使用默認的焦點突出顯示。如果您需要自定義形狀(例如,圓形或丸狀)聚焦的亮點,或者如果你使用的不是來源於一個主題Theme.DeviceDefault ,使用汽車的UI庫資源來指定自己的重點突顯每個視圖。

要為視圖指定自定義焦點突出顯示,請將視圖的背景或前景可繪製對象更改為在視圖聚焦時不同的可繪製對象。通常,您會更改背景。以下可繪製對象,如果用作方形視圖的背景,會產生圓形焦點突出顯示:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_focused="true" android:state_pressed="true">
      <shape android:shape="oval">
         <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/>
         <stroke
            android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width"
            android:color="@color/car_ui_rotary_focus_pressed_stroke_color"/>
      </shape>
   </item>
   <item android:state_focused="true">
      <shape android:shape="oval">
         <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
         <stroke
            android:width="@dimen/car_ui_rotary_focus_stroke_width"
            android:color="@color/car_ui_rotary_focus_stroke_color"/>
      </shape>
   </item>
   <item>
      <ripple...>
         ...
      </ripple>
   </item>
</selector>

上述(11的Android QPR3,機器人11汽車,機器人12)將樣品以粗體資源引用識別由汽車-UI-庫中定義的資源。 OEM 覆蓋這些以與它們指定的默認焦點突出顯示一致。這確保當用戶在具有自定義焦點突出顯示的視圖和具有默認焦點突出顯示的視圖之間導航時,焦點突出顯示顏色、筆觸寬度等不會改變。最後一項是用於觸摸的波紋。用於粗體資源的默認值如下所示:

粗體資源的默認值
圖4.大膽資源的默認值

此外,當按鈕具有純色背景以引起用戶注意時,會調用自定義焦點突出顯示,如下例所示。這會使焦點高光難以看到。在這種情況下,使用二次色指定自定義焦點亮點:

純色背景
  • (11的Android QPR3,機器人11汽車,機器人12)
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • 機器人12)
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

例如:

專注,沒有壓力專注,按下
專注,沒有壓力專注,按下

旋轉滾動

如果應用程序使用RecyclerView S,你應該使用CarUiRecyclerView !而非。這可以確保你的用戶界面是與他人一致的,因為OEM的定制適用於所有CarUiRecyclerView秒。

如果列表中的元素都是可聚焦的,則無需執行任何其他操作。旋轉導航在列表中的元素之間移動焦點,並且列表滾動以使新聚焦的元素可見。

(11的Android QPR3,機器人11汽車,機器人12)
如果有可聚焦和不可聚焦元素的混合,或者如果所有元素都不可聚焦,您可以啟用旋轉滾動,這允許用戶使用旋轉控制器逐漸滾動列表,而不會跳過不可聚焦的項目。要啟用旋轉滾動,設置app:rotaryScrollEnabled屬性為true

(11的Android QPR3,機器人11汽車,機器人12)
可以在任何可滾動視圖使旋轉滾動,包括AV CarUiRecyclerView ,與setRotaryScrollEnabled()在方法CarUiUtils 。如果您這樣做,您需要:

  • 使可滾動視圖可聚焦,以便在其可聚焦的後代視圖都不可見時可以聚焦,
  • 通過調用禁用的滾動視圖中的默認焦點亮點setDefaultFocusHighlightEnabled(false) ,這樣的滾動視圖不會出現集中,
  • 確保滾動視圖通過調用其後代之前專注於setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS)
  • 聽與MotionEvents SOURCE_ROTARY_ENCODER並且或者AXIS_VSCROLLAXIS_HSCROLL來指示滾動的距離和方向(通過符號)。

當旋轉滾動上一個啟用CarUiRecyclerView並且用戶旋轉到其中沒有可聚焦的觀點存在的區域中,滾動條從灰色到藍色的變化,因為如果以指示滾動條被聚焦。如果您願意,您可以實現類似的效果。

除了源之外,MotionEvents 與鼠標滾輪產生的相同。

直接操作模式

通常,輕推和旋轉會在用戶界面中導航,而按下“中心”按鈕會執行操作,但情況並非總是如此。例如,如果用戶想要調整鬧鐘音量,他們可能會使用旋轉控制器導航到音量滑塊,按中心按鈕,旋轉控制器以調整鬧鐘音量,然後按返回按鈕返回導航.這被稱為直接操縱(DM)模式。在這種模式下,旋轉控制器用於直接與視圖交互而不是導航。

以兩種方式之一實施 DM。如果你只需要旋轉手柄,你想操縱響應視圖ACTION_SCROLL_FORWARDACTION_SCROLL_BACKWARD AccessibilityEvent適當S,使用簡單的機制。否則,使用先進的機制。

簡單機制是系統窗口中唯一的選擇;應用程序可以使用任一機制。

簡單的機制

(11的Android QPR3,機器人11汽車,機器人12)
您的應用程序應該調用DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable)RotaryService當用戶處於DM模式和當用戶在一個視圖被聚焦按壓中心按鈕進入DM模式可識別。當DM模式,旋轉執行ACTION_SCROLL_FORWARDACTION_SCROLL_BACKWARD並退出DM模式下,當用戶按下返回按鈕。進入和退出 DM 模式時,簡單的機制會切換視圖的選定狀態。

要提供用戶處於 DM 模式的視覺提示,請在選擇時使您的視圖看起來不同。例如,更改背景,當android:state_selectedtrue

先進的機制

該應用確定何時RotaryService進入和退出DM模式。為了獲得一致的用戶體驗,在 DM 視圖聚焦的情況下按下中心按鈕應進入 DM 模式,而後退按鈕應退出 DM 模式。如果不使用中心按鈕和/或輕推,它們可以作為退出 DM 模式的替代方法。對於地圖等應用,可以使用代表 DM 的按鈕進入 DM 模式。

為了支持高級DM模式,一個視圖:

  1. (11的Android QPR3,機器人11汽車,機器人12)必須偵聽KEYCODE_DPAD_CENTER事件進入DM模式和偵聽KEYCODE_BACK事件退出DM模式,調用DirectManipulationHelper.enableDirectManipulationMode()在每種情況下。要偵聽這些事件,請執行以下操作之一:
    • 註冊一個OnKeyListener
    • 或者,
    • 延伸的視圖,然後覆蓋其dispatchKeyEvent()方法。
  2. 應該監聽微調事件( KEYCODE_DPAD_UPKEYCODE_DPAD_DOWNKEYCODE_DPAD_LEFT ,或KEYCODE_DPAD_RIGHT )如果視圖應該處理的微移。
  3. 應該聽MotionEvent S和得到的旋轉數量在AXIS_SCROLL如果視圖要手柄轉動。做這件事有很多種方法:
    1. 註冊一個OnGenericMotionListener
    2. 延伸的視圖並覆蓋其dispatchTouchEvent()方法。
  4. 為了避免卡在 DM 模式,當視圖所屬的 Fragment 或 Activity 不是交互式時,必須退出 DM 模式。
  5. 應該提供一個視覺提示來指示視圖處於 DM 模式。

下面提供了使用 DM 模式平移和縮放地圖的自定義視圖示例:

/** Whether this view is in DM mode. */
private boolean mInDirectManipulationMode;

/** Initializes the view. Called by the constructors. */ private void init() { setOnKeyListener((view, keyCode, keyEvent) -> { boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP; switch (keyCode) { // Always consume KEYCODE_DPAD_CENTER and KEYCODE_BACK events. case KeyEvent.KEYCODE_DPAD_CENTER: if (!mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = true; DirectManipulationHelper.enableDirectManipulationMode(this, true); setSelected(true); // visually indicate DM mode } return true; case KeyEvent.KEYCODE_BACK: if (mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); setSelected(false); } return true; // Consume controller nudge events only when in DM mode. // When in DM mode, nudges pan the map. case KeyEvent.KEYCODE_DPAD_UP: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, -10f); return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, 10f); return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(-10f, 0f); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(10f, 0f); return true; // Don't consume other key events. default: return false; } });
// When in DM mode, rotation zooms the map. setOnGenericMotionListener(((view, motionEvent) -> { if (!mInDirectManipulationMode) return false; float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); zoom(10 * scroll); return true; })); }
@Override public void onPause() { if (mInDirectManipulationMode) { // To ensure that the user doesn't get stuck in DM mode, disable DM mode // when the fragment is not interactive (e.g., a dialog shows up). mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); } super.onPause(); }

更多的例子可以在找到RotaryPlayground項目。

活動視圖

使用 ActivityView 時:

  • ActivityView不應該成為焦點。
  • 安卓11 QPR3,Android的11車,棄用Android的11)
    所述的內容ActivityView必須包含一個FocusParkingView作為第一可聚焦視圖,其app:shouldRestoreFocus屬性必須是false
  • 在內容ActivityView應該沒有android:focusByDefault意見。

對於用戶來說,ActivityViews 應該對導航沒有影響,除了焦點區域不能跨越 ActivityViews。換句話說,你不能有一個具有內容內部外部的一個重點領域ActivityView 。如果你沒有任何FocusAreas添加到您的ActivityView ,在視圖層次的根ActivityView被認為是一個隱含的重點領域。

按住時操作的按鈕

大多數按鈕在點擊時會引起一些動作。某些按鈕在按住時起作用。例如,快進和快退按鈕通常在按住時操作。為了使這樣的按鍵支持旋轉,聽KEYCODE_DPAD_CENTER KeyEvents如下:

mButton.setOnKeyListener((v, keyCode, event) ->
{
    if (keyCode != KEYCODE_DPAD_CENTER) {
        return false;
    }
    if (event.getAction() == ACTION_DOWN) {
        mButton.setPressed(true);
        mHandler.post(mRunnable);
    } else {
        mButton.setPressed(false);
        mHandler.removeCallbacks(mRunnable);
    }
    return true;
});

其中mRunnable採取動作(例如,倒帶)和安排其自身的延遲之後運行。

觸控方式

用戶可以通過旋轉控制器或觸摸屏幕兩種方式使用旋轉控制器與汽車中的主機進行交互。使用旋轉控制器時,將突出顯示可聚焦視圖之一。觸摸屏幕時,不會出現焦點突出顯示。用戶可以隨時在這些輸入模式之間切換:

  • 旋轉→觸摸。當用戶觸摸屏幕時,焦點高亮消失。
  • 觸摸 → 旋轉。當用戶輕推、旋轉或按下“中心”按鈕時,會出現焦點突出顯示。

Back 和 Home 按鈕對輸入模式沒有影響。

Android上的現有觀念旋轉捎帶觸控模式。可以使用View.isInTouchMode()來確定用戶正在使用哪個輸入模式。您可以使用OnTouchModeChangeListener聽更改。雖然這可用於為當前輸入模式自定義用戶界面,但請避免任何重大更改,因為它們可能會令人不安。

故障排除

在專為觸控設計的應用程序中,嵌套可聚焦視圖並不少見。例如,可以有一個FrameLayout圍繞ImageButton ,這兩者都是可獲得焦點。這對觸摸無害,但會導致旋轉的用戶體驗不佳,因為用戶必須將控制器旋轉兩次才能移動到下一個交互式視圖。為了獲得良好的用戶體驗,Google 建議您將外部視圖或內部視圖設為可聚焦,但不能同時使兩者都聚焦。

如果通過旋轉控制器按下按鈕或開關時失去焦點,則可能適用以下情況之一:

  • 由於按鈕被按下,按鈕或開關被禁用(短暫或無限期)。無論哪種情況,都有兩種方法可以解決這個問題:
    • 離開android:enabled狀態為true ,並使用自定義的狀態變為灰色,按鈕或開關中的說明自定義狀態
    • 使用容器包圍按鈕或開關並使容器可聚焦,而不是按鈕或開關。 (點擊偵聽器必須在容器上。)
  • 正在更換按鈕或開關。例如,按下按鈕或切換開關時採取的動作可能會觸發可用動作的刷新,從而導致新按鈕替換現有按鈕。有兩種方法可以解決這個問題:
    • 不要創建新按鈕或開關,而是設置現有按鈕或開關的圖標和/或文本。
    • 如上所述,在按鈕或開關周圍添加一個可聚焦的容器。

旋轉遊樂場

RotaryPlayground為旋轉基準的應用程序。使用它來了解如何將各種旋轉功能集成到您的應用程序中。 RotaryPlayground包含在模擬器和海鷹建立。

  • RotaryPlayground庫: packages/apps/Car/tests/RotaryPlayground/
  • 版本:Android 11 QPR3、Android 11 Car 和 Android 12

RotaryPlayground應用在左側顯示以下標籤:

  • 牌。測試圍繞焦點區域導航,跳過不可聚焦的元素和文本輸入。
  • 直接操縱。測試支持簡單和高級直接操作模式的小部件。此選項卡專門用於在應用程序窗口內進行直接操作。
  • 系統用戶界面操作。在僅支持簡單直接操作模式的系統窗口中測試支持直接操作的小部件。
  • 網格。使用滾動測試 z 模式旋轉導航。
  • 通知。測試微調進入和退出提醒通知。
  • 滾動。測試滾動瀏覽可聚焦和不可聚焦的內容。
  • 網絡視圖​​。測試通過在鏈接導航WebView
  • FocusArea測試FocusArea定制:
    • 環繞。
    • android:focusedByDefaultapp:defaultFocus
    • .
    • 明確的輕推目標。
    • 輕推快捷方式。
    • FocusArea沒有可聚焦的看法。