Materi berikut ditujukan untuk developer aplikasi.
Agar aplikasi Anda mendukung tombol putar, Anda HARUS:
- Tempatkan
FocusParkingView
di tata letak aktivitas masing-masing. - Pastikan tampilan yang dapat (atau tidak) dapat difokuskan.
- Gunakan
FocusArea
untuk menggabungkan semua tampilan yang dapat difokuskan, kecualiFocusParkingView
.
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:
- Ketuk tiga titik di bagian bawah toolbar:
- Pilih Mobil rotary di jendela Extended controls:
Keyboard USB
- Colokkan keyboard USB ke perangkat yang menjalankan Android Automotive OS (AAOS). Dalam beberapa kasus, menyebabkan keyboard virtual tidak muncul.
- Gunakan build
userdebug
ataueng
. - 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
:
- 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 sehinggaRotaryService
dapat memarkir fokus padanya untuk menghapus sorotan fokus. - Jika hanya ada satu
FocusArea
di jendela saat ini, akan 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. SaatRotaryService
menentukan fokus targetnya adalahFocusParkingView
, alat ini dapat menentukan penyelesaiannya akan terjadi pada titik mana dapat menghindari penyelesaian dengan tidak memindahkan fokus. - 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:
- Untuk menambahkan atribut khusus
pada tampilan Anda. Misalnya, untuk menambahkan status kustom
state_rotary_enabled
ke 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 bersama dengan 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 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; }
- 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
adalahfalse
. - Agar tombol tampak nonaktif, pada 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 pada 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 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:
- Saat menangani tindakan rotasi dan geser,
RotaryService
akan mencari instance dariFocusArea
dalam hierarki tampilan. - Saat menerima peristiwa rotasi,
RotaryService
akan memindahkan fokus ke yang lain Tampilan yang dapat mengambil fokus dalamFocusArea
yang sama. - Saat menerima peristiwa saran tindak lanjut,
RotaryService
memindahkan fokus ke tampilan lain yang dapat mengambil fokus diFocusArea
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, gunakanapp:wrapAround
(lihat di bawah) untuk membuat loop.android:focusedByDefault
memungkinkan developer aplikasi menentukan tampilan fokus default di jendela. JANGAN gunakan atribut ini danapp:defaultFocus
(lihat di bawah) dalamFocusArea
yang sama.
FocusArea
juga menentukan beberapa atribut untuk menyesuaikan navigasi dari alat rotasi.
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 difokuskan, yang harus difokuskan saat pengguna saran tindak lanjut keFocusArea
ini. - (Android 11 QPR3, Android 11 Mobil,
Android 12)
app:defaultFocusOverridesHistory
dapat disetel ketrue
agar tampilan yang ditentukan di atas mengambil fokus meskipun dengan yang menunjukkan tampilan lain diFocusArea
ini telah difokuskan. - (Android 12)
Gunakanapp:nudgeLeftShortcut
,app:nudgeRightShortcut
,app:nudgeUpShortcut
, danapp: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
danapp:nudgeShortcutDirection
hanya mendukung satu pintasan saran tindak lanjut. - (Android 11 QPR3, Android 11 Mobil,
Android 12)
Untuk mengaktifkan rotasi yang dapat digabungkan dalamFocusArea
ini,app:wrapAround
dapat ditetapkan ketrue
. Ini paling sering digunakan saat tampilan diatur 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 dirasakan dariFocusArea
ini guna menemukan target dorongan, menggunakanapp:startBoundOffset
,app:endBoundOffset
,app:topBoundOffset
,app:bottomBoundOffset
,app:horizontalBoundOffset
, danapp:verticalBoundOffset
. - (Android 11 QPR3, Android 11 Mobil,
Android 12)
Untuk menetapkan secara eksplisit ID suatuFocusArea
(atau area) yang berdekatan pada arah yang ditentukan, gunakanapp:nudgeLeft
,app:nudgeRight
,app:nudgeUp
, danapp: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:
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:
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:
- (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 |
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
danAXIS_VSCROLL
atauAXIS_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:
- (Android 11 QPR3, Android 11 Mobil,
Android 12) HARUS memproses
KEYCODE_DPAD_CENTER
peristiwa untuk masuk ke mode DM dan memproses peristiwaKEYCODE_BACK
untuk keluar dari mode DM, memanggilDirectManipulationHelper.enableDirectManipulationMode()
dalam setiap kasus. Untuk memproses peristiwa ini, lakukan salah satu hal berikut:- Daftarkan
OnKeyListener
.
atau,
- Perluas tampilan lalu ganti metode
dispatchKeyEvent()
-nya.
- Daftarkan
- HARUS memproses peristiwa saran tindak lanjut (
KEYCODE_DPAD_UP
,KEYCODE_DPAD_DOWN
,KEYCODE_DPAD_LEFT
, atauKEYCODE_DPAD_RIGHT
) jika tampilan harus menangani dorongan. - HARUS memproses
MotionEvent
dtk dan dapatkan jumlah rotasi dalamAXIS_SCROLL
jika tampilan ingin menangani rotasi. Ada beberapa cara untuk melakukannya:- Daftarkan
OnGenericMotionListener
. - Perluas tampilan dan ganti metode
dispatchTouchEvent()
-nya.
- Daftarkan
- Untuk menghindari terjebak dalam mode DM, HARUS keluar dari mode DM saat Fragment atau Activity menampilkan tidak interaktif.
- 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)
KontenActivityView
HARUS berisiFocusParkingView
sebagai tampilan pertama yang dapat difokuskan, danapp:shouldRestoreFocus
-nya HARUSfalse
. - Konten
ActivityView
tidak boleh memilikiandroid: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
sebagaitrue
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.)
- Biarkan status
- 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 penyesuaianFocusArea
:- Penutup.
android:focusedByDefault
danapp:defaultFocus
.
- Target saran tindak lanjut eksplisit.
- Menggeser pintasan.
FocusArea
tanpa tampilan yang dapat difokuskan.