Mengembangkan aplikasi

Materi berikut ditujukan untuk developer aplikasi.

Agar aplikasi Anda mendukung tombol putar, Anda HARUS:

  1. Tempatkan FocusParkingView di tata letak aktivitas masing-masing.
  2. Pastikan tampilan yang dapat (atau tidak) dapat difokuskan.
  3. Gunakan FocusArea untuk menggabungkan semua tampilan yang dapat difokuskan, kecuali FocusParkingView.

Setiap tugas ini dijelaskan di bawah ini, setelah Anda menyiapkan lingkungan untuk mengembangkan aplikasi yang mendukung putar.

Menyiapkan rotary controller

Sebelum dapat mulai mengembangkan aplikasi yang mendukung putar, Anda memerlukan rotary controller atau stand-in. Anda memiliki opsi yang dijelaskan di bawah.

Emulator

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

Anda juga dapat menggunakan aosp_car_x86_64-userdebug.

Untuk mengakses rotary controller yang diemulasikan:

  1. Ketuk tiga titik di bagian bawah toolbar:

    Mengakses rotary controller yang diemulasi
    Gambar 1. Mengakses rotary controller yang diemulasi
  2. Pilih Mobil rotary di jendela Extended controls:

    Pilih putar Mobil
    Gambar 2. Pilih Putar mobil

Keyboard USB

  • Colokkan keyboard USB ke perangkat yang menjalankan Android Automotive OS (AAOS). Dalam beberapa kasus, menyebabkan keyboard virtual tidak muncul.
  • Gunakan build userdebug atau eng.
  • Aktifkan pemfilteran peristiwa utama:
    adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
    
  • Lihat tabel di bawah untuk menemukan kunci yang sesuai untuk setiap tindakan:
    Kunci Aksi putar
    T Putar berlawanan arah jarum jam
    E Putar searah jarum jam
    A Geser ke Kiri
    D Geser ke Kanan
    R Geser ke Atas
    S Geser ke Bawah
    F atau Koma Tombol tengah
    R atau Esc Tombol kembali

Perintah ADB

Anda dapat menggunakan perintah car_service untuk memasukkan peristiwa input dari tombol putar. Perintah-perintah ini dapat dijalankan di perangkat yang menjalankan Android Automotive OS (AAOS) atau di emulator.

Perintah car_service Input dari alat rotasi
adb shell cmd car_service inject-rotary Putar berlawanan arah jarum jam
adb shell cmd car_service inject-rotary -c true Putar searah jarum jam
adb shell cmd car_service inject-rotary -dt 100 50 Putar berlawanan arah jarum jam beberapa kali (100 md yang lalu dan 50 md yang lalu)
adb shell cmd car_service inject-key 282 Geser ke Kiri
adb shell cmd car_service inject-key 283 Geser ke Kanan
adb shell cmd car_service inject-key 280 Geser ke Atas
adb shell cmd car_service inject-key 281 Geser ke Bawah
adb shell cmd car_service inject-key 23 Klik tombol tengah
adb shell input keyevent inject-key 4 Klik tombol kembali

rotary controller OEM

Saat perangkat keras {i>rotary controller<i} Anda aktif dan berjalan, ini adalah yang paling opsi yang realistis. Hal ini sangat berguna untuk menguji rotasi cepat.

TampilanParkir Fokus

FocusParkingView adalah tampilan transparan di Library UI Mobil (car-ui-library). RotaryService menggunakannya untuk mendukung navigasi rotary controller. FocusParkingView harus menjadi tampilan pertama yang dapat difokuskan dalam tata letak. Elemen ini harus ditempatkan di luar semua FocusArea. Setiap jendela harus memiliki satu FocusParkingView. Jika Anda sudah menggunakan tata letak dasar {i>car-ui-library<i}, yang berisi FocusParkingView, Anda tidak perlu menambahkan yang lain FocusParkingView. Di bawah ini adalah contoh FocusParkingView dalam RotaryPlayground.

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

Berikut adalah alasan Anda memerlukan FocusParkingView:

  1. Android tidak menghapus fokus secara otomatis saat fokus disetel di jendela lain. Jika Anda mencoba untuk membersihkan fokus di jendela sebelumnya, Android memfokuskan ulang tampilan di jendela tersebut, yang menghasilkan dua jendela yang difokuskan secara bersamaan. Menambahkan FocusParkingView ke setiap jendela dapat memperbaiki masalah ini. Tampilan ini transparan dan sorotan fokus default-nya dinonaktifkan, sehingga tidak terlihat oleh pengguna, terlepas dari apakah difokuskan atau tidak. Diperlukan fokus sehingga RotaryService dapat memarkir fokus padanya untuk menghapus sorotan fokus.
  2. Jika hanya ada satu FocusArea di jendela saat ini, akan memutar pengontrol di FocusArea menyebabkan RotaryService memindahkan fokus dari tampilan di sebelah kanan ke tampilan di sebelah kiri (dan sebaliknya). Menambahkan tampilan ini ke setiap jendela dapat memperbaiki masalah. Saat RotaryService menentukan fokus targetnya adalah FocusParkingView, alat ini dapat menentukan penyelesaiannya akan terjadi pada titik mana dapat menghindari penyelesaian dengan tidak memindahkan fokus.
  3. Saat kontrol putar meluncurkan aplikasi, Android memfokuskan tampilan pertama yang dapat difokuskan, yang selalu berupa FocusParkingView. FocusParkingView menentukan tampilan optimal yang akan difokuskan, lalu menerapkan fokus.

Tampilan yang dapat difokuskan

RotaryService dibuat berdasarkan API sudah ada konsep fokus tampilan, sejak ponsel memiliki {i>keyboard<i} dan D-pad fisik. Atribut android:nextFocusForward yang ada digunakan ulang untuk tombol putar (lihat Penyesuaian FocusArea), tetapi android:nextFocusLeft, android:nextFocusRight, android:nextFocusUp dan android:nextFocusDown tidak.

RotaryService hanya berfokus pada tampilan yang dapat difokuskan. Beberapa pemandangan seperti Button, biasanya dapat difokuskan. Lainnya, seperti TextView dan ViewGroup, biasanya tidak. Tampilan yang dapat diklik secara otomatis dapat difokuskan dan tampilan secara otomatis dapat diklik saat memiliki pemroses klik. Jika logika otomatis ini menghasilkan metode kemampuan fokus, Anda tidak perlu menetapkan kemampuan fokus tampilan secara eksplisit. Jika logika otomatis tidak menghasilkan kemampuan fokus yang diinginkan, setel atribut android:focusable ke true atau false, atau secara terprogram menetapkan kemampuan fokus tampilan dengan View.setFocusable(boolean). Agar RotaryService dapat difokuskan padanya, tampilan HARUS memenuhi persyaratan berikut:

  • Dapat difokuskan
  • Aktif
  • Terlihat
  • Memiliki nilai bukan nol untuk lebar dan tinggi

Jika tampilan tidak memenuhi semua persyaratan ini, misalnya tombol yang dapat difokuskan tetapi dinonaktifkan, pengguna tidak dapat menggunakan kontrol tombol putar untuk fokus padanya. Jika ingin berfokus pada tampilan yang dinonaktifkan, sebaiknya gunakan status kustom, bukan android:state_enabled, untuk mengontrol cara tampilan muncul tanpa menunjukkan bahwa Android harus menganggapnya dinonaktifkan. Aplikasi Anda dapat menginformasikan pengguna mengapa tampilan dinonaktifkan saat diketuk. Bagian selanjutnya menjelaskan cara melakukannya.

Status kustom

Untuk menambahkan status kustom:

  1. Untuk menambahkan atribut khusus pada tampilan Anda. Misalnya, untuk menambahkan status kustom state_rotary_enabled ke Class tampilan CustomView, gunakan:
    <declare-styleable name="CustomView">
        <attr name="state_rotary_enabled" format="boolean" />
    </declare-styleable>
    
  2. Untuk melacak status ini, tambahkan variabel instance ke tampilan Anda bersama dengan metode pengakses:
    private boolean mRotaryEnabled;
    public boolean getRotaryEnabled() { return mRotaryEnabled; }
    public void setRotaryEnabled(boolean rotaryEnabled) {
        mRotaryEnabled = rotaryEnabled;
    }
    
  3. Untuk membaca nilai atribut saat tampilan dibuat:
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
    mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
    
  4. Di class tampilan Anda, ganti metode onCreateDrawableState(), lalu menambahkan status kustom, jika sesuai. Contoh:
    @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. Membuat pengendali klik tampilan Anda berperforma berbeda, bergantung pada statusnya. Misalnya, klik mungkin tidak melakukan apa-apa atau mungkin memunculkan {i>toast<i} saat mRotaryEnabled adalah false.
  6. Agar tombol tampak nonaktif, pada drawable latar belakang tampilan, gunakan app:state_rotary_enabled, bukan android:state_enabled. Jika belum memilikinya, Anda harus menambahkan:
    xmlns:app="http://schemas.android.com/apk/res-auto"
    
  7. Jika tampilan Anda dinonaktifkan pada tata letak apa pun, ganti android:enabled="false" dengan app:state_rotary_enabled="false", lalu tambahkan namespace app, seperti di atas.
  8. Jika tampilan Anda dinonaktifkan secara terprogram, ganti panggilan ke setEnabled() dengan panggilan ke setRotaryEnabled().

Area Fokus

Gunakan FocusAreas untuk mempartisi tampilan yang dapat difokuskan ke dalam blok untuk melakukan navigasi lebih mudah dan konsisten dengan aplikasi lain. Misalnya, jika aplikasi Anda memiliki toolbar, {i>toolbar<i} harus berada di FocusArea yang terpisah dari aplikasi Anda lainnya. Bilah tab dan elemen navigasi lainnya juga harus dipisahkan dari bagian aplikasi lainnya. Daftar besar umumnya harus memiliki FocusArea-nya sendiri. Jika tidak, pengguna harus merotasi seluruh daftar untuk mengakses beberapa tampilan.

FocusArea adalah subclass LinearLayout di library car-ui-. Saat fitur ini aktif, FocusArea akan menggambar sorotan jika salah satu turunan tetap fokus. Untuk mempelajari lebih lanjut, lihat Penyesuaian sorotan fokus.

Saat membuat blok navigasi di file tata letak, jika Anda ingin menggunakan LinearLayout sebagai penampung untuk blok tersebut, gunakan FocusArea sebagai gantinya. Jika tidak, gabungkan blok dalam FocusArea.

JANGAN menyarangkan FocusArea di FocusArea lain. Hal tersebut menyebabkan perilaku navigasi yang tidak ditentukan. Pastikan semua tampilan yang dapat difokuskan disarangkan dalam FocusArea.

Contoh FocusArea di RotaryPlayground ditampilkan di bawah ini:

<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 berfungsi sebagai berikut:

  1. Saat menangani tindakan rotasi dan geser, RotaryService akan mencari instance dari FocusArea dalam hierarki tampilan.
  2. Saat menerima peristiwa rotasi, RotaryService akan memindahkan fokus ke yang lain Tampilan yang dapat mengambil fokus dalam FocusArea yang sama.
  3. Saat menerima peristiwa saran tindak lanjut, RotaryService memindahkan fokus ke tampilan lain yang dapat mengambil fokus di FocusArea lain (yang biasanya berdekatan).

Jika Anda tidak menyertakan FocusAreas di tata letak, tampilan root akan diperlakukan sebagai area fokus implisit. Pengguna tidak dapat mendorong untuk membuka aplikasi. Sebaliknya, mereka akan memutar di seluruh tampilan yang dapat difokuskan, yang mungkin cukup untuk dialog.

Penyesuaian FocusArea

Dua atribut View standar dapat digunakan untuk menyesuaikan navigasi dari alat rotasi:

  • android:nextFocusForward memungkinkan developer aplikasi menentukan rotasi di area fokus. Atribut ini sama dengan yang digunakan untuk mengontrol urutan Tab untuk navigasi {i>keyboard<i}. JANGAN gunakan atribut ini untuk membuat loop. Sebagai gantinya, gunakan app:wrapAround (lihat di bawah) untuk membuat loop.
  • android:focusedByDefault memungkinkan developer aplikasi menentukan tampilan fokus default di jendela. JANGAN gunakan atribut ini dan app:defaultFocus (lihat di bawah) dalam FocusArea yang sama.

FocusArea juga menentukan beberapa atribut untuk menyesuaikan navigasi dari alat rotasi. Area fokus implisit tidak dapat disesuaikan dengan atribut ini.

  1. (Android 11 QPR3, Android 11 Mobil, Android 12)
    app:defaultFocus dapat digunakan untuk menentukan ID tampilan turunan yang dapat difokuskan, yang harus difokuskan saat pengguna saran tindak lanjut ke FocusArea ini.
  2. (Android 11 QPR3, Android 11 Mobil, Android 12)
    app:defaultFocusOverridesHistory dapat disetel ke true agar tampilan yang ditentukan di atas mengambil fokus meskipun dengan yang menunjukkan tampilan lain di FocusArea ini telah difokuskan.
  3. (Android 12)
    Gunakan app:nudgeLeftShortcut, app:nudgeRightShortcut, app:nudgeUpShortcut, dan app:nudgeDownShortcut untuk menetapkan ID tampilan turunan yang dapat difokuskan, yang harus difokuskan saat pengguna mendorong ke arah tertentu. Untuk mempelajari lebih lanjut, lihat konten untuk munculkan pintasan di bawah.

    (Android 11 QPR3, Android 11 Mobil, tidak digunakan lagi di Android 12) app:nudgeShortcut dan app:nudgeShortcutDirection hanya mendukung satu pintasan saran tindak lanjut.

  4. (Android 11 QPR3, Android 11 Mobil, Android 12)
    Untuk mengaktifkan rotasi yang dapat digabungkan dalam FocusArea ini, app:wrapAround dapat ditetapkan ke true. Ini paling sering digunakan saat tampilan diatur dalam lingkaran atau oval.
  5. (Android 11 QPR3, Android 11 Mobil, Android 12)
    Untuk menyesuaikan padding sorotan di FocusArea ini, gunakan app:highlightPaddingStart, app:highlightPaddingEnd, app:highlightPaddingTop, app:highlightPaddingBottom, app:highlightPaddingHorizontal, dan app:highlightPaddingVertical.
  6. (Android 11 QPR3, Android 11 Mobil, Android 12)
    Untuk menyesuaikan batas yang dirasakan dari FocusArea ini guna menemukan target dorongan, menggunakan app:startBoundOffset, app:endBoundOffset, app:topBoundOffset, app:bottomBoundOffset, app:horizontalBoundOffset, dan app:verticalBoundOffset.
  7. (Android 11 QPR3, Android 11 Mobil, Android 12)
    Untuk menetapkan secara eksplisit ID suatu FocusArea (atau area) yang berdekatan pada arah yang ditentukan, gunakan app:nudgeLeft, app:nudgeRight, app:nudgeUp, dan app:nudgeDown. Gunakan ini saat penelusuran geometris digunakan secara default tidak menemukan target yang diinginkan.

Dorongan biasanya menavigasi di antara FocusAreas. Tetapi dengan {i>shortcut<i} (pintasan){i>,<i} mendorong terkadang melakukan navigasi dalam FocusArea terlebih dahulu, sehingga pengguna mungkin perlu untuk mendorong dua kali guna membuka FocusArea berikutnya. Pintasan geser berguna saat FocusArea berisi daftar panjang yang diikuti dengan Tombol Tindakan Mengambang, seperti dalam contoh di bawah ini:

Pintasan geser
Gambar 3. Pintasan geser

Tanpa pintasan saran tindak lanjut, pengguna harus memutar seluruh daftar untuk menjangkau FAB.

Penyesuaian sorotan fokus

Seperti disebutkan di atas, RotaryService dibuat berdasarkan konsep framework Android yang sudah ada, fokus tampilan. Saat pengguna memutar dan menggeser, RotaryService akan memindahkan fokus, memfokuskan satu tampilan dan tidak memfokuskan yang lain. Di Android, saat tampilan difokuskan, jika tampilan:

  • Telah menetapkan sorotan fokusnya sendiri, Android menggambar sorotan fokus tampilan.
  • Tidak menentukan sorotan fokus, dan sorotan fokus default tidak dinonaktifkan, Android menggambar sorotan fokus default untuk tampilan.

Aplikasi yang dirancang untuk sentuhan biasanya tidak menentukan sorotan fokus yang sesuai.

Sorotan fokus default disediakan oleh framework Android dan dapat diganti oleh OEM. Developer aplikasi menerimanya jika tema yang mereka gunakan berasal dari Theme.DeviceDefault.

Untuk pengalaman pengguna yang konsisten, andalkan sorotan fokus default jika memungkinkan. Jika Anda memerlukan sorotan fokus berbentuk khusus (misalnya, bulat atau berbentuk pil), atau jika Anda menggunakan tema yang tidak berasal dari Theme.DeviceDefault, gunakan library car-ui- untuk menentukan sorotan fokus Anda sendiri bagi setiap tampilan.

Guna menentukan sorotan fokus kustom untuk tampilan, ubah drawable latar belakang atau latar depan tampilan ke drawable yang berbeda saat tampilan difokuskan. Biasanya, Anda akan mengubah latar belakang. Drawable berikut, jika digunakan sebagai latar belakang untuk tampilan persegi, menghasilkan sorotan fokus bulat:

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

(Android 11 QPR3, Android 11 Mobil, Android 12) Referensi resource Tebal dalam contoh di atas mengidentifikasi resource yang ditentukan oleh library car-ui-library. OEM menggantinya agar konsisten dengan sorotan fokus {i>default<i} yang ditentukan. Hal ini memastikan bahwa warna sorotan fokus, lebar goresan, dan sebagainya tidak berubah saat pengguna menavigasi di antara tampilan dengan fokus khusus dan tampilan dengan sorotan fokus default. Item terakhir adalah riak yang digunakan untuk sentuhan. Nilai default yang digunakan untuk resource tebal muncul sebagai berikut:

Nilai default untuk resource tebal
Gambar 4. Nilai default untuk resource tebal

Selain itu, sorotan fokus khusus juga dipanggil ketika tombol diberi warna solid warna latar belakang agar pengguna memperhatikan, seperti dalam contoh di bawah ini. Hal ini dapat menjadikan sorotan fokus sulit dilihat. Dalam situasi ini, tentukan sorotan fokus khusus menggunakan sekunder:

Warna latar belakang solid
  • (Android 11 QPR3, Android 11 Mobil, Android 12)
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • (Android 12)
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

Contoh:

Fokus, tidak ditekan Fokus, ditekan
Fokus, tidak ditekan Fokus, ditekan

Scrolling dari alat rotasi

Jika aplikasi Anda menggunakan RecyclerView, Anda HARUS menggunakan CarUiRecyclerView saja. Hal ini memastikan bahwa UI Anda konsisten dengan lainnya karena penyesuaian OEM berlaku untuk semua CarUiRecyclerView.

Jika semua elemen dalam daftar dapat difokuskan, Anda tidak perlu melakukan apa pun. Navigasi putar memindahkan fokus melalui elemen dalam daftar dan daftar di-scroll untuk membuat elemen yang baru difokuskan terlihat.

(Android 11 QPR3, Android 11 Mobil, Android 12)
Jika terdapat perpaduan antara fokus yang dapat difokuskan dan tidak dapat difokuskan atau jika semua elemen tidak bisa difokuskan, Anda bisa mengaktifkan scroll putar, yang memungkinkan pengguna menggunakan rotary controller untuk men-scroll daftar secara bertahap tanpa melewati item yang tidak dapat difokuskan. Untuk mengaktifkan scroll dari alat rotasi, setel app:rotaryScrollEnabled ke true.

(Android 11 QPR3, Android 11 Mobil, Android 12)
Anda dapat mengaktifkan scroll putar dalam tampilan yang dapat di-scroll, termasuk avCarUiRecyclerView, dengan setRotaryScrollEnabled() di CarUiUtils. Jika Anda melakukannya, Anda harus:

  • Membuat tampilan yang dapat di-scroll agar dapat difokuskan sehingga dapat difokuskan saat tidak ada tampilan turunan yang dapat difokuskan terlihat,
  • Nonaktifkan sorotan fokus default pada tampilan yang dapat di-scroll dengan memanggil setDefaultFocusHighlightEnabled(false) sehingga tampilan yang dapat di-scroll tampaknya tidak fokus,
  • Pastikan tampilan yang dapat di-scroll difokuskan sebelum turunannya dengan memanggil setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS).
  • Memproses MotionEvent dengan SOURCE_ROTARY_ENCODER dan AXIS_VSCROLL atau AXIS_HSCROLL untuk menunjukkan jarak yang akan di-scroll dan arah (melalui tanda).

Saat scroll dari alat rotasi diaktifkan pada CarUiRecyclerView dan pengguna memutarnya ke area yang tidak memiliki tampilan yang dapat difokuskan, scrollbar akan berubah dari abu-abu menjadi biru, seolah-olah untuk menunjukkan bahwa scrollbar difokuskan. Anda dapat menerapkan efek serupa jika mau.

MotionEvents sama dengan yang dihasilkan oleh roda scroll pada mouse, kecuali sumber.

Mode manipulasi langsung

Biasanya, dorongan dan rotasi menavigasi antarmuka pengguna, sementara tombol Tengah menekan tombol mengambil tindakan, meskipun hal ini tidak selalu terjadi. Misalnya, jika pengguna ingin menyesuaikan volume alarm, mereka mungkin menggunakan rotary controller untuk menavigasi ke penggeser volume, tekan Tombol tengah, putar pengontrol untuk menyesuaikan volume alarm, lalu tekan tombol Kembali untuk kembali ke navigasi. Hal ini disebut sebagai mode manipulasi langsung (DM). Di sini rotary controller digunakan untuk berinteraksi dengan tampilan secara langsung, bukan untuk menavigasi.

Terapkan DM dengan salah satu dari dua cara berikut. Jika Anda hanya perlu menangani rotasi dan tampilan yang diinginkan untuk memanipulasi respons terhadap ACTION_SCROLL_FORWARD dan ACTION_SCROLL_BACKWARD AccessibilityEvent dengan tepat, gunakan sederhana. Jika tidak, gunakan mekanisme lanjutan.

Mekanisme sederhana adalah satu-satunya pilihan di jendela sistem; aplikasi dapat menggunakan salah satu mekanisme tersebut.

Mekanisme sederhana

(Android 11 QPR3, Android 11 Mobil, Android 12)
Aplikasi Anda harus memanggil DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable). RotaryService mengenali saat pengguna berada dalam mode DM dan memasuki mode DM saat pengguna menekan tombol Tengah saat tampilan difokuskan. Saat dalam mode DM, rotasi melakukan ACTION_SCROLL_FORWARD atau ACTION_SCROLL_BACKWARD dan keluar dari mode DM ketika pengguna menekan tombol Kembali. Mekanisme sederhana mengalihkan status yang dipilih dari tampilan saat masuk dan keluar dari mode DM.

Untuk memberikan isyarat visual bahwa pengguna sedang dalam mode DM, buat tampilan Anda tampak berbeda saat dipilih. Misalnya, ubah latar belakang saat android:state_selected adalah true.

Mekanisme lanjutan

Aplikasi menentukan kapan RotaryService masuk dan keluar dari mode DM. Untuk konsistensi pengalaman pengguna, menekan tombol Tengah dengan tampilan DM yang difokuskan akan memasuki mode DM dan tombol Kembali akan keluar dari mode DM. Jika tombol Tengah dan/atau dorongan tidak digunakan, bisa menjadi cara alternatif untuk keluar dari mode DM. Untuk aplikasi seperti Maps, tombol yang mewakili DM dapat digunakan untuk masuk ke mode DM.

Untuk mendukung mode DM lanjutan, tampilan:

  1. (Android 11 QPR3, Android 11 Mobil, Android 12) HARUS memproses KEYCODE_DPAD_CENTER peristiwa untuk masuk ke mode DM dan memproses peristiwa KEYCODE_BACK untuk keluar dari mode DM, memanggil DirectManipulationHelper.enableDirectManipulationMode() dalam setiap kasus. Untuk memproses peristiwa ini, lakukan salah satu hal berikut:
    • Daftarkan OnKeyListener.
    • atau,
    • Perluas tampilan lalu ganti metode dispatchKeyEvent()-nya.
  2. HARUS memproses peristiwa saran tindak lanjut (KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_LEFT, atau KEYCODE_DPAD_RIGHT) jika tampilan harus menangani dorongan.
  3. HARUS memproses MotionEvent dtk dan dapatkan jumlah rotasi dalam AXIS_SCROLL jika tampilan ingin menangani rotasi. Ada beberapa cara untuk melakukannya:
    1. Daftarkan OnGenericMotionListener.
    2. Perluas tampilan dan ganti metode dispatchTouchEvent()-nya.
  4. Untuk menghindari terjebak dalam mode DM, HARUS keluar dari mode DM saat Fragment atau Activity menampilkan tidak interaktif.
  5. HARUS memberikan isyarat visual untuk menunjukkan bahwa tampilan tersebut dalam mode DM.

Contoh tampilan kustom yang menggunakan mode DM untuk menggeser dan melakukan zoom pada peta disediakan di bawah:

/** 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(); }

Contoh lainnya dapat ditemukan di Project RotaryPlayground.

TampilanAktivitas

Saat menggunakan ActivityView:

  • ActivityView tidak boleh difokuskan.
  • (Android 11 QPR3, Android 11 Mobil, tidak digunakan lagi di Android 11)
    Konten ActivityView HARUS berisi FocusParkingView sebagai tampilan pertama yang dapat difokuskan, dan app:shouldRestoreFocus-nya HARUS false.
  • Konten ActivityView tidak boleh memiliki android:focusByDefault penayangan.

Bagi pengguna, ActivityView seharusnya tidak berpengaruh pada navigasi, kecuali fokus area tidak dapat mencakup ActivityView. Dengan kata lain, Anda tidak boleh memiliki satu area fokus yang memiliki konten di dalam dan di luar ActivityView. Jika Anda tidak menambahkan FocusAreas ke ActivityView, root hierarki tampilan di bagian ActivityView dianggap sebagai area fokus implisit.

Tombol yang beroperasi saat ditekan

Sebagian besar tombol menyebabkan beberapa tindakan saat diklik. Beberapa tombol beroperasi saat ditekan. Misalnya, tombol Maju Cepat dan Mundur biasanya beroperasi saat ditekan. Untuk membuat tombol mendukung putar, dengarkan KEYCODE_DPAD_CENTER KeyEvents sebagai berikut:

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;
});

Saat mRunnable mengambil tindakan (seperti memutar ulang) dan menjadwalkan dirinya untuk dijalankan setelah penundaan.

Mode sentuh

Pengguna dapat menggunakan rotary controller untuk berinteraksi dengan head unit di mobil dengan dua cara, menggunakan rotary controller atau dengan menyentuh layar. Saat menggunakan rotary controller, salah satu tampilan yang dapat difokuskan akan disorot. Saat menyentuh layar, tidak ada sorotan fokus muncul. Pengguna dapat beralih di antara mode input ini kapan saja:

  • Putar → sentuh. Saat pengguna menyentuh layar, sorotan fokus akan menghilang.
  • Sentuh → putar. Ketika pengguna menggeser, memutar, atau menekan tombol Tengah, sorotan fokus akan muncul.

Tombol Kembali dan Beranda tidak berpengaruh pada mode input.

tumpangan pada konsep Android yang ada tentang mode sentuh. Anda dapat menggunakan View.isInTouchMode() untuk menentukan mode input mana yang digunakan pengguna. Anda dapat menggunakan OnTouchModeChangeListener untuk memproses perubahan. Meskipun ini dapat digunakan untuk menyesuaikan antarmuka pengguna Anda dengan ke input mode input lainnya, hindari perubahan besar karena dapat membingungkan.

Pemecahan masalah

Dalam aplikasi yang dirancang untuk sentuhan, adalah hal yang umum untuk memiliki tampilan bertingkat yang dapat difokuskan. Misalnya, mungkin ada FrameLayout di sekitar ImageButton, keduanya dapat difokuskan. Hal ini tidak membahayakan sentuhan, tetapi dapat menghasilkan pengalaman pengguna untuk alat rotasi karena pengguna harus memutar pengontrol dua kali untuk berpindah ke ke tampilan interaktif berikutnya. Untuk pengalaman pengguna yang baik, Google merekomendasikan agar Anda melakukan tampilan luar atau tampilan dalam yang dapat difokuskan, tetapi tidak keduanya.

Jika tombol atau sakelar kehilangan fokus saat ditekan melalui rotary controller, salah satu ketentuan berikut mungkin berlaku:

  • Tombol atau sakelar sedang dinonaktifkan (secara singkat atau tanpa batas waktu) karena saat tombol ditekan. Dalam kedua kasus tersebut, ada dua cara untuk mengatasi hal ini:
    • Biarkan status android:enabled sebagai true dan gunakan status menjadi warna abu-abu pada tombol atau tombol seperti yang dijelaskan di Status Kustom.
    • Menggunakan penampung untuk mengelilingi tombol atau tombol akses dan membuat penampung dapat difokuskan alih-alih tombol atau {i>switch<i}. (Pemroses klik harus berada di penampung.)
  • Tombol atau tombol sedang diganti. Misalnya, tindakan yang diambil saat tombol ditekan atau tombol dialihkan dapat memicu muat ulang tindakan yang tersedia menyebabkan tombol baru menggantikan tombol yang ada. Ada dua cara untuk mengatasi hal ini:
    • Alih-alih membuat tombol atau {i>switch<i} baru, setel ikon dan/atau teks dari tombol atau {i>switch<i} yang sudah ada.
    • Seperti cara di atas, tambahkan penampung yang dapat difokuskan di sekitar tombol atau tombol.

Taman Putar

RotaryPlayground adalah aplikasi referensi untuk tombol putar. Gunakan untuk mempelajari cara mengintegrasikan fitur putar ke dalam aplikasi Anda. RotaryPlayground disertakan dalam build emulator dan di build untuk perangkat yang menjalankan Android Automotive OS (AAOS).

  • Repositori RotaryPlayground: packages/apps/Car/tests/RotaryPlayground/
  • Versi: Android 11 QPR3, Android 11 Car, dan Android 12

Aplikasi RotaryPlayground menampilkan tab berikut di sebelah kiri:

  • Kartu. Uji navigasi di sekitar area fokus, dengan melewatkan elemen yang tidak dapat difokuskan dan input teks.
  • Manipulasi Langsung. Uji widget yang mendukung sederhana dan lanjutan mode manipulasi langsung. Tab ini khusus untuk manipulasi langsung di dalam jendela aplikasi.
  • Manipulasi UI Sistem. Menguji widget yang mendukung manipulasi langsung di jendela sistem yang hanya mendukung mode manipulasi langsung yang sederhana.
  • Petak. Uji navigasi putar pola z dengan scrolling.
  • Notifikasi. Uji masuk dan keluar notifikasi peringatan dini.
  • Scroll. Uji scroll perpaduan antara kombinasi yang dapat difokuskan dan tidak dapat difokuskan saat ini.
  • WebView. Menguji navigasi melalui link di WebView.
  • FocusArea Kustom. Uji penyesuaian FocusArea:
    • Penutup.
    • android:focusedByDefault dan app:defaultFocus
    • .
    • Target saran tindak lanjut eksplisit.
    • Menggeser pintasan.
    • FocusArea tanpa tampilan yang dapat difokuskan.