Materi berikut ditujukan untuk pengembang aplikasi.
Untuk membuat aplikasi Anda mendukung rotasi, Anda HARUS:
- Tempatkan
FocusParkingView
di tata letak aktivitas masing-masing. - Pastikan tampilan yang (atau tidak) dapat difokuskan.
- Gunakan
FocusArea
untuk merangkum semua tampilan fokus Anda, kecualiFocusParkingView
.
Masing-masing tugas ini dirinci di bawah, setelah Anda menyiapkan lingkungan untuk mengembangkan aplikasi yang mendukung rotasi.
Siapkan pengontrol putar
Sebelum Anda dapat mulai mengembangkan aplikasi yang mendukung rotasi, Anda memerlukan pengontrol putar atau pengganti. Anda memiliki opsi yang dijelaskan di bawah ini.
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 ditiru:
- Ketuk tiga titik di bagian bawah bilah alat:
- Pilih Putar mobil di jendela kontrol yang diperluas:
papan ketik USB
- Colokkan keyboard USB ke perangkat Anda yang menjalankan Android Automotive OS (AAOS). Dalam beberapa kasus, hal ini mencegah munculnya keyboard di layar.
- Gunakan
userdebug
ataueng
build. - 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 Q Putar berlawanan arah jarum jam E Putar searah jarum jam A Dorongan ke kiri D Dorongan ke kanan W Dorongan ke atas S Dorong ke bawah F atau Koma Tombol tengah R atau Esc Tombol kembali
perintah ADB
Anda dapat menggunakan perintah car_service
untuk memasukkan peristiwa masukan putar. Perintah ini dapat dijalankan di perangkat yang menjalankan Android Automotive OS (AAOS) atau di emulator.
perintah car_service | Masukan putar |
---|---|
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 mdtk lalu dan 50 mdtk lalu) |
adb shell cmd car_service inject-key 282 | Dorongan ke kiri |
adb shell cmd car_service inject-key 283 | Dorongan ke kanan |
adb shell cmd car_service inject-key 280 | Dorongan ke atas |
adb shell cmd car_service inject-key 281 | Dorong ke bawah |
adb shell cmd car_service inject-key 23 | Klik tombol tengah |
adb shell input keyevent inject-key 4 | Klik tombol kembali |
Pengontrol putar OEM
Saat perangkat keras pengontrol putar Anda aktif dan berjalan, ini adalah opsi paling realistis. Ini sangat berguna untuk menguji rotasi cepat.
Tampilan Parkir Fokus
FocusParkingView
adalah tampilan transparan di Perpustakaan UI Mobil (car-ui-library) . RotaryService
menggunakannya untuk mendukung navigasi pengontrol putar. FocusParkingView
harus menjadi tampilan pertama yang dapat difokuskan dalam tata letak. Itu harus ditempatkan di luar semua FocusArea
s. Setiap jendela harus memiliki satu FocusParkingView
. Jika Anda sudah menggunakan tata letak dasar car-ui-library, yang berisi FocusParkingView
, Anda tidak perlu menambahkan FocusParkingView
lainnya. Di bawah ini 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 ketika fokus diatur di jendela lain. Jika Anda mencoba menghapus fokus di jendela sebelumnya, Android akan memfokuskan kembali tampilan di jendela tersebut, sehingga menghasilkan dua jendela yang difokuskan secara bersamaan. Menambahkan
FocusParkingView
ke setiap jendela dapat memperbaiki masalah ini. Tampilan ini transparan dan sorotan fokus defaultnya dinonaktifkan, sehingga tidak terlihat oleh pengguna, baik terfokus atau tidak. Diperlukan fokus agarRotaryService
dapat memarkir fokus padanya untuk menghilangkan sorotan fokus. - Jika hanya ada satu
FocusArea
di jendela saat ini, memutar pengontrol diFocusArea
menyebabkanRotaryService
memindahkan fokus dari tampilan di sebelah kanan ke tampilan di sebelah kiri (dan sebaliknya). Menambahkan tampilan ini ke setiap jendela dapat memperbaiki masalah ini. KetikaRotaryService
menentukan target fokus adalahFocusParkingView
, RotaryService dapat menentukan penyelesaian akan segera terjadi dan pada titik mana ia menghindari penyelesaian dengan tidak memindahkan fokus. - Saat kontrol putar meluncurkan aplikasi, Android memfokuskan tampilan fokus pertama, yang selalu berupa
FocusParkingView
.FocusParkingView
menentukan tampilan optimal untuk difokuskan dan kemudian menerapkan fokus.
Pandangan yang dapat difokuskan
RotaryService
dibangun berdasarkan konsep fokus tampilan kerangka Android yang sudah ada , sejak ponsel memiliki keyboard fisik dan D-pad. Atribut android:nextFocusForward
yang ada digunakan ulang untuk rotasi (lihat penyesuaian FocusArea ), namun android:nextFocusLeft
, android:nextFocusRight
, android:nextFocusUp
, dan android:nextFocusDown
tidak.
RotaryService
hanya berfokus pada pandangan yang dapat difokuskan. Beberapa tampilan, misalnya Button
, biasanya dapat difokuskan. Lainnya, seperti TextView
s dan ViewGroup
s, biasanya tidak. Tampilan yang dapat diklik secara otomatis dapat difokus dan tampilan secara otomatis dapat diklik ketika memiliki pemroses klik. Jika logika otomatis ini menghasilkan fokus yang diinginkan, Anda tidak perlu mengatur fokus tampilan secara eksplisit. Jika logika otomatis tidak menghasilkan kemampuan fokus yang diinginkan, setel atribut android:focusable
ke true
atau false
, atau setel fokusabilitas tampilan secara terprogram dengan View.setFocusable(boolean)
. Agar RotaryService
dapat fokus pada hal tersebut, suatu tampilan HARUS memenuhi persyaratan berikut:
- Dapat difokuskan
- Diaktifkan
- Bisa dilihat
- Memiliki nilai bukan nol untuk lebar dan tinggi
Jika tampilan tidak memenuhi semua persyaratan ini, misalnya tombol dapat difokus namun dinonaktifkan, pengguna tidak dapat menggunakan kontrol putar untuk memfokuskannya. Jika Anda ingin fokus pada tampilan yang dinonaktifkan, pertimbangkan untuk menggunakan status khusus, bukan android:state_enabled
untuk mengontrol tampilan tampilan tanpa menunjukkan bahwa Android harus menganggapnya dinonaktifkan. Aplikasi Anda dapat memberi tahu pengguna mengapa tampilan dinonaktifkan saat diketuk. Bagian selanjutnya menjelaskan cara melakukan ini.
Negara bagian khusus
Untuk menambahkan status khusus:
- Untuk menambahkan atribut khusus ke tampilan Anda. Misalnya, untuk menambahkan status kustom
state_rotary_enabled
ke kelas tampilanCustomView
, gunakan:<declare-styleable name="CustomView"> <attr name="state_rotary_enabled" format="boolean" /> </declare-styleable>
- Untuk melacak keadaan ini, tambahkan variabel instan ke tampilan Anda bersama dengan metode pengakses:
private boolean mRotaryEnabled; public boolean getRotaryEnabled() { return mRotaryEnabled; } public void setRotaryEnabled(boolean rotaryEnabled) { mRotaryEnabled = rotaryEnabled; }
- Untuk membaca nilai atribut Anda saat tampilan Anda dibuat:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView); mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
- Di kelas tampilan Anda, ganti metode
onCreateDrawableState()
lalu tambahkan status kustom, jika diperlukan. Misalnya:@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; }
- Jadikan pengendali klik tampilan Anda bekerja secara berbeda bergantung pada statusnya. Misalnya, pengendali klik mungkin tidak melakukan apa pun atau mungkin muncul bersulang ketika
mRotaryEnabled
bernilaifalse
. - Untuk membuat tombol tampak dinonaktifkan, di latar belakang tampilan Anda yang dapat digambar, gunakan
app:state_rotary_enabled
alih-alihandroid:state_enabled
. Jika Anda belum memilikinya, Anda perlu 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()
.
Area fokus
Gunakan FocusAreas
untuk mempartisi tampilan yang dapat difokuskan menjadi beberapa blok agar navigasi lebih mudah dan konsisten dengan aplikasi lain. Misalnya, jika aplikasi Anda memiliki toolbar, toolbar tersebut harus berada di FocusArea
terpisah dari aplikasi Anda lainnya. Bilah tab dan elemen navigasi lainnya juga harus dipisahkan dari aplikasi lainnya. Daftar besar umumnya harus memiliki FocusArea
sendiri. Jika tidak, pengguna harus memutar seluruh daftar untuk mengakses beberapa tampilan.
FocusArea
adalah subkelas LinearLayout
di perpustakaan car-ui. Saat fitur ini diaktifkan, FocusArea
akan menyorot saat salah satu turunannya terfokus. Untuk mempelajari lebih lanjut, lihat Kustomisasi sorotan fokus .
Saat membuat blok navigasi di file tata letak, jika Anda ingin menggunakan LinearLayout
sebagai kontainer untuk blok tersebut, gunakan FocusArea
sebagai gantinya. Jika tidak, bungkus blok dalam FocusArea
.
JANGAN menumpuk FocusArea
di FocusArea
lain. Melakukan hal ini akan menyebabkan perilaku navigasi yang tidak terdefinisi. Pastikan semua tampilan yang dapat difokus berada di dalam FocusArea
.
Contoh FocusArea
di RotaryPlayground
ditunjukkan 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 memutar dan menyenggol,
RotaryService
mencari contohFocusArea
dalam hierarki tampilan. - Saat menerima peristiwa rotasi,
RotaryService
memindahkan fokus ke Tampilan lain yang dapat mengambil fokus diFocusArea
yang sama. - Saat menerima peristiwa dorongan,
RotaryService
memindahkan fokus ke tampilan lain yang dapat mengambil fokus diFocusArea
lain (biasanya berdekatan).
Jika Anda tidak menyertakan FocusAreas
apa pun dalam tata letak Anda, tampilan akar akan diperlakukan sebagai area fokus implisit. Pengguna tidak dapat mendorong untuk bernavigasi di aplikasi. Sebaliknya, mereka akan memutar seluruh tampilan yang dapat difokuskan, yang mungkin cukup untuk dialog.
Kustomisasi Area Fokus
Dua atribut Tampilan standar dapat digunakan untuk menyesuaikan navigasi putar:
-
android:nextFocusForward
memungkinkan pengembang aplikasi menentukan urutan rotasi di area fokus. Ini adalah atribut yang sama 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:focusedByDefault
memungkinkan pengembang aplikasi menentukan tampilan fokus default di jendela. JANGAN gunakan atribut danapp:defaultFocus
ini (lihat di bawah) diFocusArea
yang sama.
FocusArea
juga menentukan beberapa atribut untuk menyesuaikan navigasi putar. Area fokus implisit tidak dapat disesuaikan dengan atribut ini.
- ( Android 11 QPR3, Android 11 Mobil, Android 12 )
app:defaultFocus
dapat digunakan untuk menentukan ID tampilan turunan yang dapat difokus, yang harus difokuskan ketika pengguna mengarahkan keFocusArea
ini. - ( Android 11 QPR3, Android 11 Mobil, Android 12 )
app:defaultFocusOverridesHistory
dapat disetel ketrue
untuk membuat tampilan yang ditentukan di atas mengambil fokus meskipun dengan riwayat untuk menunjukkan tampilan lain diFocusArea
ini telah difokuskan. - ( Android 12 )
Gunakanapp:nudgeLeftShortcut
,app:nudgeRightShortcut
,app:nudgeUpShortcut
, danapp:nudgeDownShortcut
untuk menentukan ID tampilan turunan yang dapat difokuskan, yang harus difokuskan saat pengguna mendorong ke arah tertentu. Untuk mempelajari lebih lanjut, lihat konten pintasan nudge di bawah.( Android 11 QPR3, Android 11 Car, tidak digunakan lagi di Android 12 )
app:nudgeShortcut
danapp:nudgeShortcutDirection
hanya mendukung satu pintasan nudge. - ( Android 11 QPR3, Android 11 Mobil, Android 12 )
Untuk mengaktifkan rotasi diFocusArea
ini,app:wrapAround
dapat disetel ketrue
. Ini paling sering digunakan ketika tampilan disusun dalam lingkaran atau oval. - ( Android 11 QPR3, Android 11 Mobil, Android 12 )
Untuk menyesuaikan padding sorotan diFocusArea
ini, gunakanapp:highlightPaddingStart
,app:highlightPaddingEnd
,app:highlightPaddingTop
,app:highlightPaddingBottom
,app:highlightPaddingHorizontal
, danapp:highlightPaddingVertical
. - ( Android 11 QPR3, Android 11 Mobil, Android 12 )
Untuk menyesuaikan batas yang dirasakanFocusArea
ini guna menemukan target dorongan, gunakanapp:startBoundOffset
,app:endBoundOffset
,app:topBoundOffset
,app:bottomBoundOffset
,app:horizontalBoundOffset
, danapp:verticalBoundOffset
. - ( Android 11 QPR3, Android 11 Mobil, Android 12 )
Untuk secara eksplisit menentukan IDFocusArea
(atau area) yang berdekatan dalam arah tertentu, gunakanapp:nudgeLeft
,app:nudgeRight
,app:nudgeUp
, danapp:nudgeDown
. Gunakan ini ketika pencarian geometris yang digunakan secara default tidak menemukan target yang diinginkan.
Menyenggol biasanya menavigasi di antara Area Fokus. Namun dengan pintasan dorongan, terkadang dorongan akan menavigasi terlebih dahulu dalam FocusArea
sehingga pengguna mungkin perlu mendorong dua kali untuk menavigasi ke FocusArea
berikutnya. Pintasan dorongan berguna ketika FocusArea
berisi daftar panjang diikuti dengan Tombol Tindakan Mengambang , seperti pada contoh di bawah ini:
Tanpa pintasan dorongan, pengguna harus memutar seluruh daftar untuk mencapai FAB.
Kustomisasi sorotan fokus
Seperti disebutkan di atas, RotaryService
dibangun berdasarkan konsep fokus tampilan kerangka Android yang sudah ada. Saat pengguna memutar dan mendorong, RotaryService
memindahkan fokus, memfokuskan satu tampilan dan menghilangkan fokus lainnya. Di Android, saat tampilan terfokus, jika tampilan:
- Telah menentukan 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 kerangka kerja Android dan dapat diganti oleh OEM. Pengembang aplikasi menerimanya ketika tema yang mereka gunakan berasal dari Theme.DeviceDefault
.
Untuk pengalaman pengguna yang konsisten, andalkan sorotan fokus default bila memungkinkan. Jika Anda memerlukan sorotan fokus berbentuk khusus (misalnya, bulat atau berbentuk pil), atau jika Anda menggunakan tema yang bukan berasal dari Theme.DeviceDefault
, gunakan sumber daya car-ui-library untuk menentukan sorotan fokus Anda sendiri untuk setiap tampilan.
Untuk menentukan sorotan fokus kustom pada suatu tampilan, ubah latar belakang atau latar depan tampilan menjadi sumber daya dapat digambar yang berbeda saat tampilan difokuskan. Biasanya, Anda akan mengubah latar belakang. Sumber daya dapat digambar 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 yang dicetak tebal pada contoh di atas mengidentifikasi resource yang ditentukan oleh car-ui-library. OEM mengesampingkannya agar konsisten dengan sorotan fokus default yang mereka tentukan. Hal ini memastikan bahwa warna sorotan fokus, lebar guratan, dan sebagainya tidak berubah saat pengguna menavigasi antara tampilan dengan sorotan fokus kustom dan tampilan dengan sorotan fokus default. Item terakhir adalah riak yang digunakan untuk sentuhan. Nilai default yang digunakan untuk sumber daya yang dicetak tebal muncul sebagai berikut:
Selain itu, sorotan fokus khusus dipanggil ketika tombol diberi warna latar belakang solid untuk menarik perhatian pengguna, seperti pada contoh di bawah. Hal ini dapat membuat sorotan fokus sulit dilihat. Dalam situasi ini, tentukan sorotan fokus khusus menggunakan warna sekunder :
- ( 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
Misalnya:
Fokus, bukan ditekan | Fokus, ditekan |
Pengguliran putar
Jika aplikasi Anda menggunakan RecyclerView
s, Anda HARUS menggunakan CarUiRecyclerView
s sebagai gantinya. Hal ini memastikan bahwa UI Anda konsisten dengan yang lain karena penyesuaian OEM berlaku untuk semua CarUiRecyclerView
s.
Jika semua elemen dalam daftar Anda dapat difokuskan, Anda tidak perlu melakukan hal lain. Navigasi putar memindahkan fokus melalui elemen dalam daftar dan daftar bergulir untuk membuat elemen fokus baru terlihat.
( Android 11 QPR3, Android 11 Mobil, Android 12 )
Jika terdapat campuran elemen yang dapat difokuskan dan tidak dapat difokuskan, atau jika semua elemen tidak dapat fokus, Anda dapat mengaktifkan pengguliran putar, yang memungkinkan pengguna menggunakan pengontrol putar untuk menggulir daftar secara bertahap tanpa melewatkan item yang tidak dapat fokus. Untuk mengaktifkan pengguliran putar, setel atribut app:rotaryScrollEnabled
ke true
.
( Android 11 QPR3, Android 11 Mobil, Android 12 )
Anda dapat mengaktifkan pengguliran putar dalam tampilan apa pun yang dapat digulir, termasuk CarUiRecyclerView
, dengan metode setRotaryScrollEnabled()
di CarUiUtils
. Jika Anda melakukannya, Anda perlu:
- Menjadikan tampilan yang dapat digulir dapat difokuskan sehingga dapat difokuskan ketika tidak ada tampilan turunan yang dapat difokus yang terlihat,
- Nonaktifkan sorotan fokus default pada tampilan yang dapat digulir dengan memanggil
setDefaultFocusHighlightEnabled(false)
sehingga tampilan yang dapat digulir tidak tampak fokus, - Pastikan tampilan yang dapat digulir difokuskan sebelum turunannya dengan memanggil
setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS)
. - Dengarkan MotionEvents dengan
SOURCE_ROTARY_ENCODER
danAXIS_VSCROLL
atauAXIS_HSCROLL
untuk menunjukkan jarak untuk menggulir dan arah (melalui tanda).
Saat pengguliran putar diaktifkan pada CarUiRecyclerView
dan pengguna memutar ke area di mana tidak ada tampilan yang dapat difokuskan, bilah gulir akan berubah dari abu-abu menjadi biru, seolah-olah menunjukkan bahwa bilah gulir sedang difokuskan. Anda dapat menerapkan efek serupa jika Anda mau.
MotionEvents sama dengan yang dihasilkan oleh roda gulir pada mouse, kecuali sumbernya.
Mode manipulasi langsung
Biasanya, dorongan dan rotasi menavigasi antarmuka pengguna, sementara penekanan tombol Tengah akan mengambil tindakan, meskipun hal ini tidak selalu terjadi. Misalnya, jika pengguna ingin menyesuaikan volume alarm, mereka mungkin menggunakan pengontrol putar untuk menavigasi ke penggeser volume, tekan tombol Tengah, putar pengontrol untuk menyesuaikan volume alarm, lalu tekan tombol Kembali untuk kembali ke navigasi . Ini disebut sebagai mode manipulasi langsung (DM) . Dalam mode ini, pengontrol putar digunakan untuk berinteraksi dengan tampilan secara langsung, bukan untuk bernavigasi.
Terapkan DM dengan salah satu dari dua cara. Jika Anda hanya perlu menangani rotasi dan tampilan yang ingin Anda manipulasi merespons ACTION_SCROLL_FORWARD
dan ACTION_SCROLL_BACKWARD
AccessibilityEvent
dengan tepat, gunakan mekanisme sederhana . Jika tidak, gunakan mekanisme lanjutan .
Mekanisme sederhana adalah satu-satunya pilihan di sistem windows; 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 terfokus. Saat dalam mode DM, rotasi dilakukan ACTION_SCROLL_FORWARD
atau ACTION_SCROLL_BACKWARD
dan keluar dari mode DM ketika pengguna menekan tombol Kembali. Mekanisme sederhananya mengubah status tampilan yang dipilih saat masuk dan keluar dari mode DM.
Untuk memberikan isyarat visual bahwa pengguna sedang dalam mode DM, buat tampilan Anda tampil berbeda saat dipilih. Misalnya, ubah latar belakang jika android:state_selected
bernilai true
.
Mekanisme tingkat lanjut
Aplikasi ini menentukan kapan RotaryService
masuk dan keluar dari mode DM. Untuk pengalaman pengguna yang konsisten, menekan tombol Tengah dengan tampilan DM terfokus akan masuk ke mode DM dan tombol Kembali harus keluar dari mode DM. Jika tombol Tengah dan/atau dorongan tidak digunakan, itu bisa menjadi cara alternatif untuk keluar dari mode DM. Untuk aplikasi seperti Maps, tombol untuk mewakili DM dapat digunakan untuk masuk ke mode DM.
Untuk mendukung mode DM tingkat lanjut, tampilan:
- ( Android 11 QPR3, Android 11 Mobil, Android 12 ) HARUS mendengarkan peristiwa
KEYCODE_DPAD_CENTER
untuk masuk ke mode DM dan mendengarkan peristiwaKEYCODE_BACK
untuk keluar dari mode DM, dengan memanggilDirectManipulationHelper.enableDirectManipulationMode()
dalam setiap kasus. Untuk mendengarkan peristiwa ini, lakukan salah satu hal berikut:- Daftarkan
OnKeyListener
. atau, - Perluas tampilan lalu ganti metode
dispatchKeyEvent()
-nya.
- Daftarkan
- HARUS mendengarkan peristiwa nudge (
KEYCODE_DPAD_UP
,KEYCODE_DPAD_DOWN
,KEYCODE_DPAD_LEFT
, atauKEYCODE_DPAD_RIGHT
) jika tampilan harus menangani nudge. - HARUS mendengarkan
MotionEvent
dan mendapatkan jumlah rotasi diAXIS_SCROLL
jika tampilan ingin menangani rotasi. Ada beberapa cara untuk melakukan ini:- Daftarkan
OnGenericMotionListener
. - Perluas tampilan dan ganti metode
dispatchTouchEvent()
-nya.
- Daftarkan
- Untuk menghindari terjebak dalam mode DM, HARUS keluar dari mode DM ketika Fragmen atau Aktivitas yang dimiliki 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 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 proyek RotaryPlayground
.
Tampilan Aktivitas
Saat menggunakan ActivityView:
-
ActivityView
tidak boleh fokus. - ( Android 11 QPR3, Android 11 Mobil, tidak digunakan lagi di Android 11 )
KontenActivityView
HARUS berisiFocusParkingView
sebagai tampilan fokus pertama, dan atributapp:shouldRestoreFocus
-nya HARUSfalse
. - Konten
ActivityView
tidak boleh memiliki tampilanandroid:focusByDefault
.
Bagi pengguna, ActivityViews seharusnya tidak berpengaruh pada navigasi kecuali area fokus tidak dapat menjangkau ActivityViews. Dengan kata lain, Anda tidak bisa memiliki satu area fokus yang memiliki konten di dalam dan di luar ActivityView
. Jika Anda tidak menambahkan FocusArea apa pun ke ActivityView
Anda, akar hierarki tampilan di ActivityView
dianggap sebagai area fokus implisit.
Tombol yang beroperasi saat ditekan
Kebanyakan tombol menyebabkan beberapa tindakan saat diklik. Beberapa tombol beroperasi ketika ditekan. Misalnya, tombol Fast Forward dan Rewind biasanya beroperasi saat ditekan. Untuk membuat tombol tersebut mendukung putaran, 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 memutar ulang) dan menjadwalkan dirinya untuk dijalankan setelah penundaan.
Modus sentuh
Pengguna dapat menggunakan pengontrol putar untuk berinteraksi dengan head unit di dalam mobil dengan dua cara, baik menggunakan pengontrol putar atau dengan menyentuh layar. Saat menggunakan pengontrol putar, salah satu tampilan yang dapat difokuskan disorot. Saat menyentuh layar, tidak ada sorotan fokus yang muncul. Pengguna dapat beralih di antara mode masukan ini kapan saja:
- Putar → sentuh. Saat pengguna menyentuh layar, sorotan fokus menghilang.
- Sentuh → putar. Saat pengguna menyenggol, memutar, atau menekan tombol Tengah, sorotan fokus muncul.
Tombol Kembali dan Beranda tidak berpengaruh pada mode input.
Dukungan putar pada konsep mode sentuh yang ada di Android. Anda dapat menggunakan View.isInTouchMode()
untuk menentukan mode input mana yang digunakan pengguna. Anda dapat menggunakan OnTouchModeChangeListener
untuk mendengarkan perubahan. Meskipun ini dapat digunakan untuk menyesuaikan antarmuka pengguna Anda untuk mode masukan saat ini, hindari perubahan besar apa pun karena dapat membingungkan.
Penyelesaian masalah
Dalam aplikasi yang didesain untuk sentuhan, biasanya terdapat tampilan terfokus yang bertumpuk. Misalnya, mungkin ada FrameLayout
di sekitar ImageButton
, keduanya dapat difokus. Hal ini tidak membahayakan sentuhan tetapi dapat mengakibatkan pengalaman pengguna yang buruk untuk memutar karena pengguna harus memutar pengontrol dua kali untuk berpindah ke tampilan interaktif berikutnya. Untuk pengalaman pengguna yang baik, Google menyarankan Anda membuat tampilan luar atau tampilan dalam dapat fokus, namun tidak keduanya.
Jika tombol atau sakelar kehilangan fokus saat ditekan melalui pengontrol putar, salah satu kondisi berikut mungkin berlaku:
- Tombol atau sakelar dinonaktifkan (sebentar atau tanpa batas waktu) karena tombol ditekan. Apa pun kasusnya, ada dua cara untuk mengatasi hal ini:
- Biarkan status
android:enabled
sebagaitrue
dan gunakan status kustom untuk menghilangkan warna tombol atau tombol seperti yang dijelaskan dalam Custom State . - Gunakan wadah untuk mengelilingi tombol atau sakelar dan buat wadah tersebut dapat difokuskan, bukan tombol atau sakelar. (Pemroses klik harus ada di penampung.)
- Biarkan status
- Tombol atau sakelar sedang diganti. Misalnya, tindakan yang diambil saat tombol ditekan atau tombol dialihkan mungkin memicu penyegaran tindakan yang tersedia sehingga menyebabkan tombol baru menggantikan tombol yang sudah ada. Ada dua cara untuk mengatasi hal ini:
- Daripada membuat tombol atau tombol baru, atur ikon dan/atau teks tombol atau tombol yang ada.
- Seperti di atas, tambahkan wadah yang dapat difokuskan di sekitar tombol atau sakelar.
Taman Bermain Putar
RotaryPlayground
adalah aplikasi referensi untuk rotary. Gunakan ini untuk mempelajari cara mengintegrasikan fitur putar ke dalam aplikasi Anda. RotaryPlayground
disertakan dalam build emulator dan build untuk perangkat yang menjalankan Android Automotive OS (AAOS).
- Repositori
RotaryPlayground
:packages/apps/Car/tests/RotaryPlayground/
- Versi: Android 11 QPR3, Android 11 Mobil, dan Android 12
Aplikasi RotaryPlayground
menampilkan tab berikut di sebelah kiri:
- Kartu-kartu. Uji navigasi di sekitar area fokus, lewati elemen yang tidak fokus 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 Sistem UI. Uji widget yang mendukung manipulasi langsung di jendela sistem yang hanya mendukung mode manipulasi langsung sederhana.
- jaringan. Uji navigasi putar pola-z dengan menggulir.
- Pemberitahuan. Uji dorongan masuk dan keluar dari notifikasi pendahuluan.
- Menggulir. Uji menelusuri campuran konten yang dapat difokuskan dan tidak dapat difokuskan.
- Tampilan Web. Uji navigasi melalui tautan di
WebView
. -
FocusArea
Kustom. Uji kustomisasiFocusArea
:- Membungkus.
-
android:focusedByDefault
danapp:defaultFocus
. - Target dorongan yang eksplisit.
- Dorongan jalan pintas.
-
FocusArea
tanpa tampilan yang dapat difokuskan.