Materi berikut ditujukan untuk developer aplikasi.
Agar aplikasi mendukung rotary, Anda HARUS:
- Tempatkan
FocusParkingViewdi tata letak aktivitas masing-masing. - Pastikan tampilan yang dapat (atau tidak dapat) difokuskan.
- Gunakan
FocusAreauntuk menggabungkan semua tampilan yang dapat difokuskan, kecualiFocusParkingView.
Setiap tugas ini dijelaskan di bawah, setelah Anda menyiapkan lingkungan untuk mengembangkan aplikasi yang mendukung rotary.
Menyiapkan pengontrol rotasi
Sebelum dapat mulai mengembangkan aplikasi yang mendukung rotary, Anda memerlukan pengontrol rotary atau pengganti. 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 pengontrol putar yang diemulasi:
- Ketuk tiga titik di bagian bawah toolbar:
Gambar 1. Mengakses pengontrol rotasi yang diemulasi - Pilih Car rotary di jendela extended controls:
Gambar 2. Pilih Putar mobil
Keyboard USB
- Colokkan keyboard USB ke perangkat Anda yang menjalankan Android Automotive OS (AAOS). Dalam beberapa kasus, hal ini mencegah keyboard virtual muncul.
- Gunakan build
userdebugataueng. - Mengaktifkan 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 Tindakan dari tombol putar T Putar berlawanan arah jarum jam E Putar searah jarum jam A Geser ke Kiri D Geser ke Kanan W 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 rotasi. 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 |
Memutar 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 hardware pengontrol rotari Anda sudah aktif dan berjalan, ini adalah opsi yang paling realistis. Hal ini sangat berguna untuk menguji rotasi cepat.
FocusParkingView
FocusParkingView adalah tampilan transparan di
Library UI Mobil (car-ui-library).
RotaryService menggunakannya untuk mendukung navigasi pengontrol rotasi.
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 sudah menggunakan tata letak dasar car-ui-library,
yang berisi FocusParkingView, Anda tidak perlu menambahkan
FocusParkingView lain. Berikut adalah contoh FocusParkingView di
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:
- Android tidak menghapus fokus secara otomatis saat fokus ditetapkan di jendela lain. Jika Anda
mencoba menghapus fokus di jendela sebelumnya, Android akan memfokuskan ulang tampilan di jendela tersebut, yang
mengakibatkan dua jendela difokuskan secara bersamaan. Menambahkan
FocusParkingViewke setiap jendela dapat memperbaiki masalah ini. Tampilan ini bersifat transparan dan sorotan fokus defaultnya dinonaktifkan, sehingga tidak terlihat oleh pengguna, terlepas dari apakah difokuskan atau tidak. Tindakan ini dapat mengambil fokus sehinggaRotaryServicedapat memarkir fokus di dalamnya untuk menghapus sorotan fokus. - Jika hanya ada satu
FocusAreadi jendela saat ini, memutar pengontrol diFocusAreaakan menyebabkanRotaryServicememindahkan fokus dari tampilan di sebelah kanan ke tampilan di sebelah kiri (dan sebaliknya). Menambahkan tampilan ini ke setiap jendela dapat memperbaiki masalah. SaatRotaryServicemenentukan target fokus adalahFocusParkingView,RotaryServicedapat menentukan bahwa penggabungan akan terjadi, dan pada titik tersebut,RotaryServiceakan menghindari penggabungan dengan tidak memindahkan fokus. - Saat kontrol putar meluncurkan aplikasi, Android akan memfokuskan tampilan pertama yang dapat difokuskan,
yang selalu berupa
FocusParkingView.FocusParkingViewmenentukan tampilan optimal yang akan difokuskan, lalu menerapkan fokus.
Tampilan yang dapat difokuskan
RotaryService dibuat berdasarkan konsep fokus tampilan
yang ada
pada framework Android, yang berasal dari saat ponsel memiliki keyboard fisik dan D-pad.
Atribut android:nextFocusForward yang ada digunakan kembali untuk perangkat putar
(lihat Penyesuaian FocusArea), tetapi
android:nextFocusLeft, android:nextFocusRight,
android:nextFocusUp, dan android:nextFocusDown tidak.
RotaryService hanya berfokus pada tampilan yang dapat difokuskan. Beberapa tampilan,
seperti Button,
biasanya dapat difokuskan. Yang lainnya, seperti TextView dan ViewGroup,
biasanya tidak. Tampilan yang dapat diklik secara otomatis dapat difokuskan dan tampilan secara otomatis
dapat diklik jika memiliki pemroses klik. Jika logika otomatis ini menghasilkan fokus
yang diinginkan, Anda tidak perlu menetapkan fokus tampilan secara eksplisit. Jika logika otomatis tidak
menghasilkan kemampuan fokus yang diinginkan, tetapkan atribut android:focusable ke
true atau false, atau tetapkan kemampuan fokus tampilan secara terprogram dengan
View.setFocusable(boolean). Agar RotaryService berfokus pada tampilan, tampilan HARUS
memenuhi persyaratan berikut:
- Dapat difokuskan
- Aktif
- Terlihat
- Memiliki nilai non-nol untuk lebar dan tinggi
Jika tampilan tidak memenuhi semua persyaratan ini, misalnya tombol yang dapat difokuskan tetapi dinonaktifkan,
pengguna tidak dapat menggunakan kontrol putar untuk berfokus pada tombol tersebut. Jika Anda ingin berfokus pada tampilan yang dinonaktifkan,
pertimbangkan untuk menggunakan status kustom, bukan android:state_enabled, untuk mengontrol cara
tampilan muncul tanpa menunjukkan bahwa Android harus menganggapnya dinonaktifkan. Aplikasi Anda dapat memberi tahu
pengguna alasan tampilan dinonaktifkan saat diketuk. Bagian berikutnya menjelaskan cara melakukannya.
Status kustom
Untuk menambahkan status kustom:
- Untuk menambahkan atribut kustom
ke tampilan Anda. Misalnya, untuk menambahkan status kustom
state_rotary_enabledke class tampilanCustomView, gunakan:<declare-styleable name="CustomView"> <attr name="state_rotary_enabled" format="boolean" /> </declare-styleable> - Untuk melacak status ini, tambahkan variabel instance ke tampilan Anda beserta metode pengakses:
private boolean mRotaryEnabled; public boolean getRotaryEnabled() { return mRotaryEnabled; } public void setRotaryEnabled(boolean rotaryEnabled) { mRotaryEnabled = rotaryEnabled; } - Untuk membaca nilai atribut saat tampilan dibuat:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView); mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
- Di class tampilan, ganti metode
onCreateDrawableState(), lalu tambahkan 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; } - Buat pengendali klik tampilan Anda berperforma berbeda-beda, bergantung pada statusnya. Misalnya, pengendali klik mungkin tidak melakukan apa pun atau mungkin memunculkan toast saat
mRotaryEnabledadalahfalse. - Agar tombol tampak dinonaktifkan, di drawable latar belakang tampilan, gunakan
app:state_rotary_enabled, bukanandroid:state_enabled. Jika belum memilikinya, Anda harus menambahkan:xmlns:app="http://schemas.android.com/apk/res-auto"
- Jika tampilan Anda dinonaktifkan di tata letak apa pun, ganti
android:enabled="false"denganapp:state_rotary_enabled="false", lalu tambahkan namespaceapp, seperti di atas. - Jika tampilan Anda dinonaktifkan secara terprogram, ganti panggilan ke
setEnabled()dengan panggilan kesetRotaryEnabled().
FocusArea
Gunakan FocusAreas untuk mempartisi tampilan yang dapat difokuskan menjadi beberapa blok untuk mempermudah
navigasi dan agar konsisten dengan aplikasi lain. Misalnya, jika aplikasi Anda memiliki toolbar, toolbar
harus berada di FocusArea terpisah dari aplikasi lainnya. Panel tab dan
elemen navigasi lainnya juga harus dipisahkan dari aplikasi lainnya. Daftar besar
umumnya harus memiliki FocusArea-nya sendiri. Jika tidak, pengguna harus memutar
seluruh daftar untuk mengakses beberapa tampilan.
FocusArea adalah subclass dari LinearLayout di library car-ui.
Jika fitur ini diaktifkan, FocusArea akan menggambar sorotan saat salah satu
turunan difokuskan. Untuk mempelajari lebih lanjut, lihat
Penyesuaian sorotan fokus.
Saat membuat blok navigasi dalam file tata letak, jika Anda ingin menggunakan
LinearLayout sebagai penampung untuk blok tersebut, gunakan FocusArea.
Jika tidak, gabungkan blok dalam FocusArea.
JANGAN bertingkat FocusArea di FocusArea lain.
Tindakan ini akan menyebabkan perilaku navigasi yang tidak ditentukan. Pastikan semua tampilan yang dapat difokuskan
bertingkat 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:
- Saat menangani tindakan putar dan dorong,
RotaryServiceakan mencari instanceFocusAreadalam hierarki tampilan. - Saat menerima peristiwa rotasi,
RotaryServiceakan memindahkan fokus ke View lain yang dapat mengambil fokus diFocusAreayang sama. - Saat menerima peristiwa dorongan,
RotaryServiceakan memindahkan fokus ke tampilan lain yang dapat mengambil fokus diFocusArealain (biasanya berdekatan).
Jika Anda tidak menyertakan FocusAreas dalam tata letak, tampilan root akan diperlakukan
sebagai area fokus implisit. Pengguna tidak dapat mendorong untuk menavigasi di aplikasi. Sebagai gantinya, mereka akan
memutar semua tampilan yang dapat difokuskan, yang mungkin memadai untuk dialog.
Penyesuaian FocusArea
Dua atribut View standar dapat digunakan untuk menyesuaikan navigasi putar:
android:nextFocusForwardmemungkinkan developer aplikasi menentukan urutan rotasi di area fokus. Ini adalah atribut yang sama dengan yang digunakan untuk mengontrol urutan Tab untuk navigasi keyboard. JANGAN gunakan atribut ini untuk membuat loop. Sebagai gantinya, gunakanapp:wrapAround(lihat di bawah) untuk membuat loop.android:focusedByDefaultmemungkinkan developer aplikasi menentukan tampilan fokus default di jendela. JANGAN gunakan atribut ini danapp:defaultFocus(lihat di bawah) dalamFocusAreayang sama.
FocusArea juga menentukan beberapa atribut untuk menyesuaikan navigasi putar.
Area fokus implisit tidak dapat disesuaikan dengan atribut ini.
- (Android 11 QPR3, Android 11 Car,
Android 12)
app:defaultFocusdapat digunakan untuk menentukan ID tampilan turunan yang dapat difokuskan, yang harus difokuskan saat pengguna mendorong keFocusAreaini. - (Android 11 QPR3, Android 11 Car,
Android 12)
app:defaultFocusOverridesHistorydapat disetel ketrueuntuk membuat tampilan yang ditentukan di atas mengambil fokus meskipun dengan histori untuk menunjukkan tampilan lain diFocusAreaini telah difokuskan. - (Android 12)
Gunakanapp:nudgeLeftShortcut,app:nudgeRightShortcut,app:nudgeUpShortcut, danapp:nudgeDownShortcutuntuk menentukan ID tampilan turunan yang dapat difokuskan, yang harus difokuskan saat pengguna mendorong ke arah tertentu. Untuk mempelajari lebih lanjut, lihat konten untuk pintasan dorong di bawah.(Android 11 QPR3, Android 11 Car, tidak digunakan lagi di Android 12)
app:nudgeShortcutdanapp:nudgeShortcutDirectionhanya mendukung satu pintasan dorong. - (Android 11 QPR3, Android 11 Car,
Android 12)
Untuk mengaktifkan rotasi agar dibungkus diFocusAreaini,app:wrapArounddapat disetel ketrue. Ini biasanya digunakan saat tampilan disusun dalam lingkaran atau oval. - (Android 11 QPR3, Android 11 Car,
Android 12)
Untuk menyesuaikan padding sorotan diFocusAreaini, gunakanapp:highlightPaddingStart,app:highlightPaddingEnd,app:highlightPaddingTop,app:highlightPaddingBottom,app:highlightPaddingHorizontal, danapp:highlightPaddingVertical. - (Android 11 QPR3, Android 11 Car,
Android 12)
Untuk menyesuaikan batas yang dirasakan dariFocusAreaini untuk menemukan target dorongan, gunakanapp:startBoundOffset,app:endBoundOffset,app:topBoundOffset,app:bottomBoundOffset,app:horizontalBoundOffset, danapp:verticalBoundOffset. - (Android 11 QPR3, Android 11 Car,
Android 12)
Untuk menentukan IDFocusArea(atau area) yang berdekatan secara eksplisit dalam rute yang diberikan, gunakanapp:nudgeLeft,app:nudgeRight,app:nudgeUp, danapp:nudgeDown. Gunakan ini jika penelusuran geometris yang digunakan secara default tidak menemukan target yang diinginkan.
Dorongan biasanya menavigasi di antara FocusAreas. Namun, dengan pintasan dorongan,
dorongan terkadang pertama-tama menavigasi dalam FocusArea sehingga pengguna mungkin perlu
mendorong dua kali untuk menavigasi ke FocusArea berikutnya. Pintasan nudge berguna
saat FocusArea berisi daftar panjang yang diikuti dengan
Floating Action Button,
seperti pada contoh di bawah:
Tanpa pintasan dorong, pengguna harus memutar seluruh daftar untuk mencapai FAB.
Penyesuaian sorotan fokus
Seperti yang disebutkan di atas, RotaryService dibuat berdasarkan konsep fokus tampilan
yang ada di framework Android. Saat pengguna memutar dan mendorong, RotaryService akan memindahkan fokus,
memfokuskan satu tampilan dan membatalkan fokus tampilan lainnya. Di Android, saat tampilan difokuskan, jika tampilan:
- Telah menentukan sorotan fokusnya sendiri, Android menggambar sorotan fokus tampilan.
- Tidak menentukan sorotan fokus, dan sorotan fokus default tidak dinonaktifkan, Android akan menggambar sorotan fokus default untuk tampilan.
Aplikasi yang dirancang untuk sentuh biasanya tidak menentukan sorotan fokus yang sesuai.
Sorotan fokus default disediakan oleh framework Android dan dapat diganti
oleh OEM. Developer aplikasi menerimanya saat tema yang mereka gunakan berasal dari
Theme.DeviceDefault.
Untuk pengalaman pengguna yang konsisten, gunakan sorotan fokus default jika memungkinkan.
Jika Anda memerlukan sorotan fokus berbentuk kustom (misalnya, bulat atau berbentuk pil), atau jika Anda
menggunakan tema yang tidak berasal dari Theme.DeviceDefault, gunakan resource car-ui-library
untuk menentukan sorotan fokus Anda sendiri untuk setiap tampilan.
Untuk menentukan sorotan fokus kustom untuk tampilan, ubah drawable latar belakang atau latar depan tampilan menjadi drawable yang berbeda saat tampilan difokuskan. Biasanya, Anda akan mengubah latar belakang. Drawable berikut, jika digunakan sebagai latar belakang untuk tampilan persegi, akan 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 Car, Android 12) Referensi resource Tebal dalam contoh di atas mengidentifikasi resource yang ditentukan oleh car-ui-library. OEM menggantinya agar konsisten dengan sorotan fokus default yang ditentukan. Hal ini memastikan bahwa warna sorotan fokus, lebar goresan, dan sebagainya tidak berubah saat pengguna beralih antara tampilan dengan sorotan fokus kustom dan tampilan dengan sorotan fokus default. Item terakhir adalah ripple yang digunakan untuk sentuhan. Nilai default yang digunakan untuk resource tebal akan muncul sebagai berikut:
Selain itu, sorotan fokus kustom dipanggil saat tombol diberi warna latar solid untuk menarik perhatian pengguna, seperti pada contoh di bawah. Hal ini dapat membuat sorotan fokus sulit dilihat. Dalam situasi ini, tentukan sorotan fokus kustom menggunakan warna sekunder:
![]() |
- (Android 11 QPR3, Android 11 Car,
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:
![]() |
![]() |
|
| Difokuskan, tidak ditekan | Fokus, ditekan |
Scroll putar
Jika aplikasi Anda menggunakan RecyclerView, Anda HARUS menggunakan
CarUiRecyclerView sebagai gantinya. Hal ini memastikan bahwa UI Anda konsisten dengan
UI lainnya karena penyesuaian OEM berlaku untuk semua CarUiRecyclerView.
Jika semua elemen dalam daftar dapat difokuskan, Anda tidak perlu melakukan apa pun. Navigasi rotasi memindahkan fokus melalui elemen dalam daftar dan daftar akan di-scroll agar elemen yang baru difokuskan terlihat.
(Android 11 QPR3, Android 11 Car,
Android 12)
Jika ada campuran elemen yang dapat difokuskan dan tidak dapat difokuskan, atau jika semua elemen tidak dapat difokuskan, Anda dapat mengaktifkan scroll putar, yang memungkinkan
pengguna menggunakan pengontrol putar untuk men-scroll daftar secara bertahap tanpa melewati
item yang tidak dapat difokuskan. Untuk mengaktifkan scroll putar, tetapkan atribut
app:rotaryScrollEnabled ke true.
(Android 11 QPR3, Android 11 Car,
Android 12)
Anda dapat mengaktifkan scroll putar di
tampilan yang dapat di-scroll, termasuk avCarUiRecyclerView, dengan
metode setRotaryScrollEnabled() di CarUiUtils. Jika melakukannya,
Anda harus:
- Buat tampilan yang dapat di-scroll dapat difokuskan sehingga dapat difokuskan saat tidak ada tampilan turunan yang dapat difokuskan yang terlihat,
- Nonaktifkan sorotan fokus default pada tampilan yang dapat di-scroll dengan memanggil
setDefaultFocusHighlightEnabled(false)sehingga tampilan yang dapat di-scroll tidak tampak difokuskan, - Pastikan tampilan yang dapat di-scroll difokuskan sebelum turunannya dengan memanggil
setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS). - Proses MotionEvents dengan
SOURCE_ROTARY_ENCODERdanAXIS_VSCROLLatauAXIS_HSCROLLuntuk menunjukkan jarak yang akan di-scroll dan arah (melalui tanda).
Saat scroll putar diaktifkan di CarUiRecyclerView dan pengguna memutar
ke area yang tidak memiliki tampilan yang dapat difokuskan, scrollbar akan berubah dari abu-abu menjadi biru, seolah-olah
menunjukkan bahwa scrollbar difokuskan. Anda dapat menerapkan efek serupa jika mau.
MotionEvents sama dengan yang dihasilkan oleh roda scroll pada mouse, kecuali sumbernya.
Mode manipulasi langsung
Biasanya, dorongan dan rotasi menavigasi antarmuka pengguna, sedangkan penekanan tombol Tengah akan melakukan tindakan, meskipun tidak selalu demikian. Misalnya, jika pengguna ingin menyesuaikan volume alarm, mereka dapat menggunakan pengontrol putar untuk membuka penggeser volume, menekan tombol Tengah, memutar pengontrol untuk menyesuaikan volume alarm, lalu menekan tombol Kembali untuk kembali ke navigasi. Hal ini disebut sebagai mode manipulasi langsung (DM). Dalam mode ini, pengontrol rotasi digunakan untuk berinteraksi dengan tampilan secara langsung, bukan untuk menavigasi.
Terapkan DM dengan salah satu dari dua cara. Jika Anda hanya perlu menangani rotasi dan tampilan yang ingin
dimanipulasi merespons ACTION_SCROLL_FORWARD dan
ACTION_SCROLL_BACKWARD AccessibilityEvent dengan tepat, gunakan
mekanisme sederhana. Jika tidak, gunakan mekanisme lanjutan.
Mekanisme sederhana adalah satu-satunya opsi di jendela sistem; aplikasi dapat menggunakan salah satu mekanisme.
Mekanisme sederhana
(Android 11 QPR3, Android 11 Car,
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 akan menjalankan
ACTION_SCROLL_FORWARD atau ACTION_SCROLL_BACKWARD dan keluar dari mode DM
saat pengguna menekan tombol Kembali. Mekanisme sederhana ini mengalihkan status tampilan
yang dipilih saat memasuki dan keluar dari mode DM.
Untuk memberikan isyarat visual bahwa pengguna berada dalam mode DM, buat tampilan Anda terlihat berbeda
saat dipilih. Misalnya, ubah latar belakang saat
android:state_selected adalah true.
Mekanisme lanjutan
Aplikasi menentukan kapan RotaryService memasuki dan keluar dari mode DM. Untuk pengalaman pengguna
yang konsisten, menekan tombol Tengah dengan tampilan DM yang difokuskan akan memasuki mode DM
dan tombol Kembali akan keluar dari mode DM. Jika tidak digunakan, tombol Tengah dan/atau dorongan dapat menjadi cara alternatif untuk keluar dari mode DM. Untuk aplikasi seperti Maps, tombol untuk mewakili DM dapat digunakan untuk memasuki mode DM.
Untuk mendukung mode DM lanjutan, tampilan:
- (Android 11 QPR3, Android 11 Car,
Android 12) HARUS memproses peristiwa
KEYCODE_DPAD_CENTERuntuk memasuki mode DM dan memproses peristiwaKEYCODE_BACKuntuk keluar dari mode DM, memanggilDirectManipulationHelper.enableDirectManipulationMode()dalam setiap kasus. Untuk memproses peristiwa ini, lakukan salah satu tindakan berikut:- Daftarkan
OnKeyListener.
atau,
- Luaskan tampilan, lalu ganti metode
dispatchKeyEvent()-nya.
- Daftarkan
- HARUS memproses peristiwa nudge (
KEYCODE_DPAD_UP,KEYCODE_DPAD_DOWN,KEYCODE_DPAD_LEFT, atauKEYCODE_DPAD_RIGHT) jika tampilan harus menangani nudge. - HARUS memproses
MotionEventdan mendapatkan jumlah rotasi diAXIS_SCROLLjika tampilan ingin menangani rotasi. Ada beberapa cara untuk melakukannya:- Daftarkan
OnGenericMotionListener. - Luaskan tampilan dan ganti metode
dispatchTouchEvent()-nya.
- Daftarkan
- Untuk menghindari terjebak dalam mode DM, HARUS keluar dari mode DM saat Fragmen atau Aktivitas yang menjadi milik tampilan tidak interaktif.
- HARUS memberikan isyarat visual untuk menunjukkan bahwa tampilan berada dalam mode DM.
Contoh tampilan kustom yang menggunakan mode DM untuk menggeser dan memperbesar peta diberikan di bawah ini:
/** 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.
ActivityView
Saat menggunakan ActivityView:
ActivityViewtidak boleh difokuskan.- (Android 11 QPR3, Android 11 Car,
tidak digunakan lagi di Android 11)
KontenActivityViewHARUS berisiFocusParkingViewsebagai tampilan pertama yang dapat difokuskan, dan atributapp:shouldRestoreFocusHARUS berupafalse. - Konten
ActivityViewtidak boleh memiliki tampilanandroid:focusByDefault.
Bagi pengguna, ActivityViews seharusnya tidak memengaruhi navigasi, kecuali area fokus
tidak dapat menjangkau ActivityViews. Dengan kata lain, Anda tidak dapat memiliki satu area fokus yang
memiliki konten di dalam dan di luar ActivityView. Jika Anda tidak menambahkan
FocusAreas ke ActivityView, root hierarki tampilan di
ActivityView dianggap sebagai area fokus implisit.
Tombol yang beroperasi saat ditahan
Sebagian besar tombol menyebabkan beberapa tindakan saat diklik. Beberapa tombol beroperasi saat ditekan.
Misalnya, tombol Maju Cepat dan Putar Balik biasanya beroperasi saat ditekan. Agar tombol
tersebut mendukung tombol 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;
});
Di mana mRunnable mengambil tindakan (seperti memundurkan) dan menjadwalkan dirinya sendiri untuk
berjalan setelah penundaan.
Mode sentuh
Pengguna dapat menggunakan pengontrol putar untuk berinteraksi dengan head unit di mobil dengan dua cara, baik menggunakan pengontrol putar maupun dengan menyentuh layar. Saat menggunakan pengontrol putar, salah satu tampilan yang dapat difokuskan akan ditandai. Saat menyentuh layar, tidak ada sorotan fokus yang muncul. Pengguna dapat beralih di antara mode input ini kapan saja:
- Putar → sentuh. Saat pengguna menyentuh layar, sorotan fokus akan menghilang.
- Sentuh → putar. Saat pengguna mendorong, memutar, atau menekan tombol Tengah, sorotan fokus akan muncul.
Tombol Kembali dan Layar Utama tidak memengaruhi mode input.
Rotary piggybacks pada konsep
mode sentuh yang ada di Android.
Anda dapat menggunakan
View.isInTouchMode()
untuk menentukan mode input yang digunakan pengguna. Anda dapat menggunakan
OnTouchModeChangeListener
untuk memproses perubahan. Meskipun dapat digunakan untuk menyesuaikan antarmuka pengguna untuk mode input
saat ini, hindari perubahan besar karena dapat mengganggu.
Pemecahan masalah
Dalam aplikasi yang dirancang untuk sentuhan, tampilan bertingkat yang dapat difokuskan biasanya digunakan.
Misalnya, mungkin ada FrameLayout di sekitar ImageButton,
yang keduanya dapat difokuskan. Hal ini tidak berbahaya untuk sentuh, tetapi dapat mengakibatkan pengalaman pengguna yang buruk
untuk tombol putar karena pengguna harus memutar pengontrol dua kali untuk berpindah ke
tampilan interaktif berikutnya. Untuk pengalaman pengguna yang baik, Google merekomendasikan agar Anda membuat
tampilan luar atau tampilan dalam dapat difokuskan, tetapi tidak keduanya.
Jika tombol atau tombol beralih kehilangan fokus saat ditekan melalui pengontrol putar, salah satu kondisi berikut mungkin berlaku:
- Tombol atau tombol akses dinonaktifkan (secara singkat atau tanpa batas waktu) karena
tombol ditekan. Dalam kedua kasus tersebut, ada dua cara untuk mengatasinya:
- Biarkan status
android:enabledsebagaitruedan gunakan status kustom untuk membuat tombol atau tombol beralih berwarna abu-abu seperti yang dijelaskan dalam Status Kustom. - Gunakan penampung untuk mengelilingi tombol atau tombol akses dan membuat penampung dapat difokuskan, bukan tombol atau tombol akses. (Pemroses klik harus berada di penampung.)
- Biarkan status
- Tombol atau tombol akses sedang diganti. Misalnya, tindakan yang dilakukan saat tombol
ditekan atau tombol diaktifkan dapat memicu pembaruan tindakan yang tersedia
sehingga tombol baru akan menggantikan tombol yang ada. Ada dua cara untuk mengatasinya:
- Daripada membuat tombol atau tombol akses baru, tetapkan ikon dan/atau teks tombol atau tombol akses yang ada.
- Seperti di atas, tambahkan penampung yang dapat difokuskan di sekitar tombol atau tombol akses.
RotaryPlayground
RotaryPlayground adalah aplikasi referensi untuk alat rotasi. Gunakan untuk mempelajari cara mengintegrasikan
fitur rotasi ke dalam aplikasi Anda. RotaryPlayground disertakan dalam build emulator dan dalam
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, lewati elemen yang tidak dapat difokuskan dan input teks.
- Manipulasi Langsung. Uji widget yang mendukung mode manipulasi langsung sederhana dan lanjutan. Tab ini khusus untuk manipulasi langsung dalam jendela aplikasi.
- Manipulasi UI Sys. Uji widget yang mendukung manipulasi langsung di jendela sistem yang hanya mendukung mode manipulasi langsung sederhana.
- Petak. Menguji navigasi dari alat rotasi pola z dengan scroll.
- Notifikasi. Menguji notifikasi pendahuluan yang masuk dan keluar.
- Scroll. Uji scroll melalui campuran konten yang dapat difokuskan dan tidak dapat difokuskan.
- WebView. Uji navigasi melalui link di
WebView. FocusAreakustom. Uji penyesuaianFocusArea:- Wrap-around.
android:focusedByDefaultdanapp:defaultFocus.
- Target dorongan eksplisit.
- Pintasan dorong.
FocusAreatanpa tampilan yang dapat difokuskan.


