Tài liệu sau đây là dành cho nhà phát triển ứng dụng.
Để ứng dụng hỗ trợ ở chế độ xoay, bạn PHẢI:
- Đặt
FocusParkingView
vào bố cục hoạt động tương ứng. - Đảm bảo các chế độ xem có thể (hoặc không thể) làm tâm điểm.
- Dùng
FocusArea
để bao quanh tất cả khung hiển thị có thể làm tâm điểm, ngoại trừFocusParkingView
.
Từng tác vụ này được nêu chi tiết dưới đây, sau khi bạn thiết lập môi trường của bạn để phát triển các ứng dụng hỗ trợ xoay.
Thiết lập bộ điều khiển xoay
Trước khi có thể bắt đầu phát triển các ứng dụng hỗ trợ xoay, bạn cần một bộ điều khiển xoay hoặc quảng cáo đứng. Bạn có các lựa chọn như mô tả ở bên dưới.
Trình mô phỏng
source build/envsetup.sh && lunch car_x86_64-userdebug m -j emulator -wipe-data -no-snapshot -writable-system
Bạn cũng có thể sử dụng aosp_car_x86_64-userdebug
.
Cách truy cập vào bộ điều khiển xoay được mô phỏng:
- Nhấn vào biểu tượng ba dấu chấm ở cuối thanh công cụ:
- Chọn Chế độ xoay ô tô trong cửa sổ điều khiển mở rộng:
Bàn phím USB
- Cắm bàn phím USB vào thiết bị chạy Android Automotive OS (AAOS). Trong một số trường hợp, thao tác này sẽ ngăn bàn phím ảo xuất hiện.
- Sử dụng bản dựng
userdebug
hoặceng
. - Bật tính năng lọc sự kiện chính:
adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
- Hãy xem bảng dưới đây để tìm khoá tương ứng cho từng hành động:
Khoá Thao tác xoay Hỏi Xoay ngược chiều kim đồng hồ E Xoay theo chiều kim đồng hồ A Dịch sang trái D Dịch sang phải W Dịch lên trên S Dịch xuống dưới F hoặc Dấu phẩy Nút giữa R hoặc Esc Nút quay lại
Lệnh ADB
Bạn có thể dùng các lệnh car_service
để chèn các sự kiện nhập dữ liệu xoay. Các lệnh này
có thể chạy trên các thiết bị chạy Android Automotive OS (AAOS) hoặc trên một trình mô phỏng.
lệnh car_service | Phương thức nhập dữ liệu xoay |
---|---|
adb shell cmd car_service inject-rotary |
Xoay ngược chiều kim đồng hồ |
adb shell cmd car_service inject-rotary -c true |
Xoay theo chiều kim đồng hồ |
adb shell cmd car_service inject-rotary -dt 100 50 |
Xoay ngược chiều kim đồng hồ nhiều lần (100 mili giây trước và 50 mili giây trước) |
adb shell cmd car_service inject-key 282 |
Dịch sang trái |
adb shell cmd car_service inject-key 283 |
Dịch sang phải |
adb shell cmd car_service inject-key 280 |
Dịch lên trên |
adb shell cmd car_service inject-key 281 |
Dịch xuống dưới |
adb shell cmd car_service inject-key 23 |
Nhấp vào nút giữa |
adb shell input keyevent inject-key 4 |
Nhấp vào nút quay lại |
Bộ điều khiển xoay của OEM
Khi phần cứng bộ điều khiển xoay của bạn được thiết lập và chạy, đây là tùy chọn thực tế. Điều này đặc biệt hữu ích khi kiểm thử tính năng xoay nhanh.
Chế độ xem đỗ xe lấy nét
FocusParkingView
là chế độ xem trong suốt
Thư viện Giao diện người dùng ô tô (car-ui-library).
RotaryService
sử dụng lớp này để hỗ trợ điều hướng bộ điều khiển xoay.
FocusParkingView
phải là chế độ xem có thể làm tâm điểm đầu tiên
trong bố cục. Đoạn mã sự kiện phải được đặt bên ngoài tất cả các FocusArea
. Mỗi cửa sổ phải có một
FocusParkingView
. Nếu bạn đã sử dụng bố cục cơ sở car-ui-library,
chứa FocusParkingView
, bạn không cần thêm đoạn mã khác
FocusParkingView
. Dưới đây là một ví dụ về FocusParkingView
trong
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>
Dưới đây là lý do bạn cần có FocusParkingView
:
- Android không tự động xoá tiêu điểm khi đặt tiêu điểm trong một cửa sổ khác. Nếu bạn
cố gắng xóa tiêu điểm trong cửa sổ trước, Android sẽ lấy nét lại chế độ xem trong cửa sổ đó.
dẫn đến việc hai cửa sổ được lấy làm tiêu điểm cùng một lúc. Thêm một
FocusParkingView
cho mỗi cửa sổ có thể khắc phục sự cố này. Chế độ xem này có màu trong suốt và được làm nổi bật theo tiêu điểm mặc định bị tắt để người dùng không thể nhìn thấy tiện ích bổ sung này bất kể có lấy tiêu điểm hay không. Thành phần này có thể lấy tiêu điểm đểRotaryService
có thể thu hút tiêu điểm vào đó để xoá tiêu điểm được làm nổi bật. - Nếu chỉ có một
FocusArea
trong cửa sổ hiện tại, hãy xoay bộ điều khiển trongFocusArea
khiếnRotaryService
di chuyển tâm điểm từ chế độ xem ở bên phải sang chế độ xem ở bên trái (và ngược lại). Đang thêm chế độ xem này cho từng cửa sổ có thể khắc phục sự cố. KhiRotaryService
xác định tiêu điểm mục tiêu làFocusParkingView
, nó có thể xác định vòng bao quanh là sắp xảy ra tại thời điểm mà nó tránh được vòng bao quanh bằng cách không di chuyển tiêu điểm. - Khi chế độ điều khiển xoay chạy một ứng dụng, Android sẽ tập trung vào khung hiển thị có thể làm tâm điểm đầu tiên,
luôn là
FocusParkingView
.FocusParkingView
xác định chế độ xem tối ưu để lấy tiêu điểm, sau đó áp dụng tiêu điểm.
Chế độ xem có thể lấy tiêu điểm
RotaryService
được xây dựng dựa trên khung Android
hiện tại
về tiêu điểm xem, có từ khi điện thoại có bàn phím vật lý và bàn phím D.
Thuộc tính android:nextFocusForward
hiện có được chuyển đổi mục đích sử dụng cho chế độ xoay
(xem tuỳ chỉnh FocusArea), nhưng
android:nextFocusLeft
, android:nextFocusRight
,
android:nextFocusUp
và android:nextFocusDown
thì không.
RotaryService
chỉ tập trung vào các chế độ xem có thể làm tâm điểm. Một số chế độ xem,
chẳng hạn như Button
,
thường có thể lấy làm tâm điểm. Các thuộc tính khác, chẳng hạn như TextView
và ViewGroup
,
thường thì không. Chế độ xem có thể nhấp vào có thể tự động lấy tiêu điểm và chế độ xem sẽ tự động
có thể nhấp khi chúng có trình nghe lượt nhấp. Nếu logic tự động này dẫn đến kết quả mong muốn
bạn không cần đặt rõ ràng khả năng lấy tiêu điểm của thành phần hiển thị. Nếu logic tự động không
để có thể lấy nét như mong muốn, hãy đặt thuộc tính android:focusable
thành
true
hoặc false
hoặc đặt khả năng lấy tiêu điểm của thành phần hiển thị theo cách lập trình với
View.setFocusable(boolean)
. Để RotaryService
tập trung vào đó, một khung hiển thị PHẢI
đáp ứng các yêu cầu sau:
- Có thể lấy tiêu điểm
- Đã bật
- Đã hiển thị
- Có các giá trị chiều rộng và chiều cao khác 0
Nếu một khung hiển thị không đáp ứng tất cả các yêu cầu này (ví dụ: một nút có thể làm tâm điểm nhưng bị vô hiệu hoá),
người dùng không thể sử dụng nút điều khiển xoay để tập trung vào đó. Nếu bạn muốn tập trung vào các chế độ xem đã tắt,
hãy cân nhắc sử dụng trạng thái tuỳ chỉnh thay vì android:state_enabled
để kiểm soát cách
khung hiển thị đó xuất hiện mà không cho biết rằng Android nên xem như nó đã tắt. Ứng dụng của bạn có thể cung cấp thông tin
cho người dùng lý do chế độ xem bị tắt khi được nhấn. Phần tiếp theo sẽ giải thích cách thực hiện việc này.
Trạng thái tuỳ chỉnh
Cách thêm trạng thái tuỳ chỉnh:
- Cách thêm thuộc tính tuỳ chỉnh
vào chế độ xem của bạn. Ví dụ: để thêm trạng thái tuỳ chỉnh
state_rotary_enabled
vào giá trị Lớp khung hiển thịCustomView
, hãy sử dụng:<declare-styleable name="CustomView"> <attr name="state_rotary_enabled" format="boolean" /> </declare-styleable>
- Để theo dõi trạng thái này, hãy thêm một biến thực thể vào khung hiển thị của bạn cùng với các phương thức trình truy cập:
private boolean mRotaryEnabled; public boolean getRotaryEnabled() { return mRotaryEnabled; } public void setRotaryEnabled(boolean rotaryEnabled) { mRotaryEnabled = rotaryEnabled; }
- Cách đọc giá trị của thuộc tính khi khung hiển thị được tạo:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView); mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
- Trong lớp thành phần hiển thị, hãy ghi đè phương thức
onCreateDrawableState()
, sau đó thêm trạng thái tuỳ chỉnh, khi thích hợp. Ví dụ:@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; }
- Làm cho trình xử lý lượt nhấp của khung hiển thị hoạt động khác nhau tuỳ thuộc vào trạng thái của trình xử lý lượt nhấp. Ví dụ:
trình xử lý lượt nhấp có thể không làm gì hoặc có thể bật thông báo ngắn khi
mRotaryEnabled
làfalse
. - Để nút này có vẻ như bị vô hiệu hoá, trong đối tượng có thể vẽ ở chế độ nền của chế độ xem, hãy sử dụng
app:state_rotary_enabled
thay vìandroid:state_enabled
. Nếu chưa có, bạn cần phải thêm:xmlns:app="http://schemas.android.com/apk/res-auto"
- Nếu chế độ xem của bạn bị tắt trong bất kỳ bố cục nào, hãy thay thế
android:enabled="false"
bằngapp:state_rotary_enabled="false"
, sau đó thêm không gian tênapp
, như trên. - Nếu chế độ xem của bạn bị tắt theo phương thức lập trình, hãy thay thế các lệnh gọi thành
setEnabled()
bằng các lệnh gọi tớisetRotaryEnabled()
.
Khu vực tiêu điểm
Dùng FocusAreas
để phân vùng chế độ xem có thể làm tâm điểm thành các khối để hỗ trợ điều hướng
dễ dàng hơn và nhất quán với các ứng dụng khác. Ví dụ: nếu ứng dụng có thanh công cụ, thanh công cụ
phải được đặt trong một FocusArea
riêng biệt với phần còn lại của ứng dụng. Thanh tab và
các thành phần điều hướng khác cũng cần được tách biệt với phần còn lại của ứng dụng. Danh sách lớn
thường sẽ có FocusArea
riêng. Nếu không, người dùng phải xoay vòng
toàn bộ danh sách để truy cập vào một số chế độ xem.
FocusArea
là một lớp con của LinearLayout
trong car-ui-library.
Khi tính năng này được bật, FocusArea
sẽ vẽ một vùng đánh dấu khi một trong
các thành phần con được lấy làm tâm điểm. Để tìm hiểu thêm, hãy xem
Tuỳ chỉnh tính năng làm nổi bật tiêu điểm.
Khi tạo khối điều hướng trong tệp bố cục, nếu bạn định sử dụng
LinearLayout
làm vùng chứa khối đó, hãy sử dụng FocusArea
.
Nếu không, hãy gói khối trong một FocusArea
.
KHÔNG lồng FocusArea
vào một FocusArea
khác.
Làm như vậy sẽ dẫn đến hành vi điều hướng không xác định. Đảm bảo rằng tất cả các chế độ xem có thể làm tâm điểm
được lồng trong một FocusArea
.
Ví dụ về FocusArea
trong
RotaryPlayground
được hiển thị dưới đây:
<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
hoạt động như sau:
- Khi xử lý các thao tác xoay và nhắc,
RotaryService
sẽ tìm các thực thểFocusArea
trong hệ phân cấp khung hiển thị. - Khi nhận được một sự kiện xoay,
RotaryService
sẽ di chuyển tiêu điểm đến một sự kiện khác Khung hiển thị có thể lấy tiêu điểm trong cùng mộtFocusArea
. - Khi nhận được một sự kiện nhắc,
RotaryService
sẽ di chuyển tiêu điểm sang một khung hiển thị khác có thể lấy tiêu điểm ở mộtFocusArea
(thường liền kề) khác.
Nếu bạn không đưa FocusAreas
nào vào bố cục, thì khung hiển thị gốc sẽ được xử lý
làm khía cạnh ngầm tập trung. Người dùng không thể nhắc nhở hoạt động trong ứng dụng. Thay vào đó, họ sẽ
xoay qua tất cả các khung hiển thị có thể làm tâm điểm (có thể vừa đủ cho hộp thoại).
Tuỳ chỉnh FocusArea
Bạn có thể dùng 2 thuộc tính Khung hiển thị chuẩn để tuỳ chỉnh chế độ điều hướng xoay:
android:nextFocusForward
cho phép nhà phát triển ứng dụng chỉ định chế độ xoay theo một khía cạnh trọng tâm. Đây cũng là thuộc tính được dùng để kiểm soát Thứ tự thẻ cho điều hướng bằng bàn phím. KHÔNG sử dụng thuộc tính này để tạo vòng lặp. Thay vào đó, hãy sử dụngapp:wrapAround
(xem bên dưới) để tạo vòng lặp.android:focusedByDefault
cho phép nhà phát triển ứng dụng chỉ định chế độ xem tiêu điểm mặc định trong cửa sổ. KHÔNG sử dụng thuộc tính này vàapp:defaultFocus
(xem bên dưới) trong cùng mộtFocusArea
.
FocusArea
cũng xác định một số thuộc tính để tuỳ chỉnh thao tác xoay.
Bạn không thể tuỳ chỉnh các khu vực tâm điểm ngầm ẩn bằng những thuộc tính này.
- (Android 11 QPR3, Ô tô Android 11,
Android 12)
app:defaultFocus
có thể được dùng để chỉ định mã nhận dạng của một khung hiển thị con có thể làm tâm điểm. Cần tập trung vào thời điểm người dùng nhắc đếnFocusArea
này. - (Android 11 QPR3, Ô tô Android 11,
Android 12)
app:defaultFocusOverridesHistory
có thể được đặt thànhtrue
để làm cho chế độ xem được chỉ định ở trên lấy tiêu điểm ngay cả khi để cho biết một chế độ xem khác trongFocusArea
này đã được lấy làm tâm điểm. - (Android 12)
Sử dụngapp:nudgeLeftShortcut
,app:nudgeRightShortcut
app:nudgeUpShortcut
vàapp:nudgeDownShortcut
để chỉ định mã nhận dạng của một khung hiển thị con có thể làm tâm điểm. Chế độ xem này cần được lấy tiêu điểm khi người dùng nhắc theo một hướng nhất định. Để tìm hiểu thêm, hãy xem nội dung dành cho nhắc nhở hoạt động lối tắt ở bên dưới.(Android 11 QPR3, Ô tô Android 11, không dùng nữa trong Android 12)
app:nudgeShortcut
vàapp:nudgeShortcutDirection
chỉ hỗ trợ một phím tắt nhắc nhở hoạt động. - (Android 11 QPR3, Ô tô Android 11,
Android 12)
Để bật tính năng xoay bao quanhFocusArea
này, hãyapp:wrapAround
có thể đặt thànhtrue
. Thành phần này thường được sử dụng nhất khi các thành phần hiển thị được sắp xếp trong một hình tròn hoặc hình bầu dục. - (Android 11 QPR3, Ô tô Android 11,
Android 12)
Để điều chỉnh khoảng đệm của vùng đánh dấu trongFocusArea
này, sử dụngapp:highlightPaddingStart
,app:highlightPaddingEnd
,app:highlightPaddingTop
,app:highlightPaddingBottom
,app:highlightPaddingHorizontal
, vàapp:highlightPaddingVertical
. - (Android 11 QPR3, Ô tô Android 11,
Android 12)
Để điều chỉnh giới hạn quan sát được củaFocusArea
này nhằm tìm mục tiêu nhắc nhở, sử dụngapp:startBoundOffset
,app:endBoundOffset
,app:topBoundOffset
,app:bottomBoundOffset
,app:horizontalBoundOffset
vàapp:verticalBoundOffset
. - (Android 11 QPR3, Ô tô Android 11,
Android 12)
Để chỉ định rõ ID của mộtFocusArea
(hoặc các khu vực) liền kề theo chỉ dẫn đã cho, sử dụngapp:nudgeLeft
,app:nudgeRight
,app:nudgeUp
vàapp:nudgeDown
. Sử dụng tùy chọn này khi tìm kiếm hình học được sử dụng theo mặc định nhưng không tìm thấy mục tiêu mong muốn.
Tính năng Nhắc nhở hoạt động thường di chuyển giữa các FocusAreas. Tuy nhiên, với các lối tắt nhắc nhở,
nhắc nhở hoạt động đôi khi điều hướng lần đầu trong FocusArea
để người dùng có thể cần
nhắc hai lần để chuyển đến FocusArea
tiếp theo. Phím tắt nhắc rất hữu ích
khi FocusArea
chứa một danh sách dài, theo sau là một
Nút hành động nổi,
như trong ví dụ dưới đây:
Nếu không có lối tắt nhắc nhở hoạt động, người dùng sẽ phải xoay qua toàn bộ danh sách để truy cập FAB.
Tuỳ chỉnh tính năng làm nổi bật tiêu điểm
Như đã lưu ý ở trên, RotaryService
được xây dựng dựa trên khái niệm hiện có của khung Android
tiêu điểm xem. Khi người dùng xoay và nhắc, RotaryService
sẽ di chuyển tiêu điểm xung quanh,
lấy tiêu điểm một thành phần hiển thị và không lấy tiêu điểm thành tiêu điểm khác. Trong Android, khi một khung hiển thị được lấy làm tâm điểm, nếu khung hiển thị đó:
- Đã chỉ định điểm làm nổi bật tiêu điểm riêng, Android sẽ vẽ tiêu điểm của thành phần hiển thị này.
- Không chỉ định tính năng làm nổi bật tiêu điểm và tính năng làm nổi bật tiêu điểm mặc định không bị tắt, Android vẽ tiêu điểm đánh dấu mặc định cho khung hiển thị.
Ứng dụng được thiết kế cho thao tác chạm thường không chỉ định các điểm nổi bật cần lấy nét thích hợp.
Làm nổi bật tiêu điểm mặc định do khung Android cung cấp và có thể ghi đè
bởi OEM (Nhà sản xuất thiết bị gốc). Nhà phát triển ứng dụng sẽ nhận được mã này khi giao diện họ đang sử dụng được lấy từ
Theme.DeviceDefault
.
Để mang đến trải nghiệm nhất quán cho người dùng, hãy sử dụng tính năng làm nổi bật tiêu điểm theo mặc định bất cứ khi nào có thể.
Nếu bạn cần làm nổi bật tiêu điểm theo hình dạng tuỳ chỉnh (ví dụ: hình tròn hoặc hình viên thuốc), hoặc nếu bạn đang
sử dụng một giao diện không bắt nguồn từ Theme.DeviceDefault
, hãy dùng car-ui-library
để chỉ định tiêu điểm nổi bật của riêng bạn cho mỗi khung hiển thị.
Để chỉ định một tiêu điểm làm nổi bật tuỳ chỉnh cho một khung hiển thị, hãy thay đổi đối tượng có thể vẽ ở nền trước hoặc nền trước của chế độ xem thành một đối tượng có thể vẽ sẽ khác khi chế độ xem được lấy làm tâm điểm. Thông thường, bạn sẽ thay đổi nền. Các đối tượng có thể vẽ sau đây, nếu được dùng làm nền cho chế độ xem hình vuông, sẽ tạo ra một tiêu điểm dạng tròn:
<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, Ô tô Android 11, Android 12) Tệp tham chiếu tài nguyên In đậm trong mẫu ở trên xác định các tài nguyên do car-ui-library xác định. OEM ghi đè các giá trị này để đảm bảo tính nhất quán với tiêu điểm đánh dấu mặc định mà họ chỉ định. Điều này đảm bảo rằng màu làm nổi bật tiêu điểm, chiều rộng của nét vẽ, v.v. không thay đổi khi người dùng di chuyển giữa một khung hiển thị có tiêu điểm tuỳ chỉnh và khung hiển thị có làm nổi bật tiêu điểm mặc định. Mục cuối cùng là một gợn sóng dùng để chạm. Giá trị mặc định được sử dụng cho các tài nguyên in đậm xuất hiện như sau:
Ngoài ra, tính năng làm nổi bật tiêu điểm tuỳ chỉnh sẽ được gọi khi một nút nhấn có một khối màu nền để thu hút sự chú ý của người dùng, như trong ví dụ dưới đây. Điều này có thể giúp điểm nổi bật lấy tiêu điểm khó nhìn. Trong trường hợp này, hãy chỉ định đánh dấu tiêu điểm tuỳ chỉnh bằng cách sử dụng Màu secondary (phụ):
- (Android 11 QPR3, Ô tô Android 11,
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
Ví dụ:
Lấy nét, không nhấn | Lấy nét, nhấn |
Cuộn xoay
Nếu ứng dụng của bạn dùng RecyclerView
, bạn NÊN sử dụng
CarUiRecyclerView
. Điều này đảm bảo rằng giao diện người dùng nhất quán với
các lỗi khác vì chế độ tuỳ chỉnh của OEM áp dụng cho tất cả các CarUiRecyclerView
.
Nếu tất cả các phần tử trong danh sách của bạn đều có thể làm tâm điểm, thì bạn không cần làm gì thêm. Chế độ điều hướng xoay sẽ di chuyển tiêu điểm qua các phần tử trong danh sách, còn danh sách sẽ cuộn để hiển thị phần tử mới được đặt tiêu điểm.
(Android 11 QPR3, Ô tô Android 11,
Android 12)
Nếu có sự kết hợp giữa nội dung có thể làm tâm điểm và không thể làm tâm điểm
hoặc nếu tất cả các phần tử đều không thể làm tâm điểm, bạn có thể bật tính năng cuộn xoay để cho phép
người dùng sử dụng bộ điều khiển xoay để cuộn dần qua danh sách mà không bỏ qua
mục không thể đặt tiêu điểm. Để bật tính năng cuộn xoay, hãy đặt app:rotaryScrollEnabled
cho true
.
(Android 11 QPR3, Ô tô Android 11,
Android 12)
Bạn có thể bật tính năng cuộn xoay trong bất kỳ
chế độ xem có thể cuộn, bao gồm cả avCarUiRecyclerView
, với
setRotaryScrollEnabled()
trong CarUiUtils
. Nếu bạn làm như vậy,
bạn cần:
- Đặt chế độ xem có thể cuộn làm tâm điểm để có thể lấy tiêu điểm khi không có các khung hiển thị con có thể làm tâm điểm đều có thể nhìn thấy
- Tắt tính năng làm nổi bật tiêu điểm mặc định trên chế độ xem có thể cuộn bằng cách gọi
setDefaultFocusHighlightEnabled(false)
để chế độ xem có thể cuộn có vẻ không được đặt tiêu điểm, - Đảm bảo rằng chế độ xem có thể cuộn được lấy tiêu điểm trước các thành phần con cháu bằng cách gọi
setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS)
. - Nghe MotionEvents với
SOURCE_ROTARY_ENCODER
vàAXIS_VSCROLL
hoặcAXIS_HSCROLL
để cho biết khoảng cách cuộn và hướng (thông qua dấu hiệu).
Khi tính năng cuộn xoay được bật trên CarUiRecyclerView
và người dùng xoay
sang một khu vực không có chế độ xem có thể làm tâm điểm, thanh cuộn sẽ chuyển từ màu xám sang màu xanh dương, như thể
để cho biết thanh cuộn được lấy làm tâm điểm. Bạn có thể triển khai hiệu ứng tương tự nếu muốn.
MotionEvents cũng giống như các sự kiện do con lăn chuột tạo ra, ngoại trừ nguồn.
Chế độ thao túng trực tiếp
Thông thường, tính năng nhắc nhở hoạt động và xoay sẽ di chuyển trong giao diện người dùng, trong khi thao tác nhấn nút giữa hành động, mặc dù điều này không phải lúc nào cũng đúng. Ví dụ: nếu người dùng muốn điều chỉnh âm lượng báo thức, họ có thể sử dụng bộ điều khiển xoay để điều hướng đến thanh trượt âm lượng, nhấn Nút giữa, xoay bộ điều khiển để điều chỉnh âm lượng chuông báo, sau đó nhấn nút Quay lại để quay lại điều hướng. Đây được gọi là chế độ thao tác trực tiếp (DM). Trong phần này chế độ xem này, bộ điều khiển xoay được dùng để tương tác trực tiếp với thành phần hiển thị thay vì điều hướng.
Triển khai DM theo một trong hai cách. Nếu bạn chỉ cần xử lý chế độ xoay và khung hiển thị mà bạn muốn
để thao tác phản hồi với ACTION_SCROLL_FORWARD
và
ACTION_SCROLL_BACKWARD
AccessibilityEvent
một cách thích hợp, hãy sử dụng
đơn giản. Nếu không, hãy sử dụng cơ chế nâng cao.
Cơ chế đơn giản là lựa chọn duy nhất trong các cửa sổ hệ thống; ứng dụng có thể sử dụng một trong hai cơ chế.
Cơ chế đơn giản
(Android 11 QPR3, Ô tô Android 11,
Android 12)
Ứng dụng của bạn sẽ gọi
DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable)
.
RotaryService
nhận ra khi người dùng đang ở chế độ DM và chuyển sang chế độ DM khi người dùng
nhấn vào nút Căn giữa khi một khung hiển thị được lấy tiêu điểm. Khi ở chế độ DM, hoạt động xoay sẽ thực hiện
ACTION_SCROLL_FORWARD
hoặc ACTION_SCROLL_BACKWARD
và thoát khỏi chế độ tin nhắn trực tiếp
khi người dùng nhấn vào nút Quay lại. Cơ chế đơn giản chuyển đổi trạng thái đã chọn của
chế độ xem khi vào và thoát khỏi chế độ DM.
Để đưa ra chỉ dẫn trực quan cho biết người dùng đang ở chế độ tin nhắn trực tiếp (DM), hãy làm cho chế độ xem của bạn có vẻ khác
khi được chọn. Ví dụ: thay đổi nền khi
android:state_selected
là true
.
Cơ chế nâng cao
Ứng dụng này xác định thời điểm RotaryService
chuyển sang và thoát khỏi chế độ DM. Để có sự nhất quán
trải nghiệm người dùng, nhấn nút Trung tâm với chế độ xem DM tập trung sẽ chuyển sang chế độ DM
và nút Quay lại sẽ thoát khỏi chế độ DM. Nếu bạn không sử dụng nút Căn giữa và/hoặc lời nhắc,
chúng có thể là những cách khác để thoát khỏi chế độ DM. Đối với các ứng dụng như Maps, một nút để thể hiện
Có thể dùng DM để chuyển sang chế độ DM.
Để hỗ trợ chế độ DM nâng cao, một chế độ xem sẽ:
- (Android 11 QPR3, Ô tô Android 11,
Android 12) PHẢI theo dõi
KEYCODE_DPAD_CENTER
sự kiện để vào chế độ DM và theo dõi sự kiệnKEYCODE_BACK
để thoát khỏi chế độ DM, gọiDirectManipulationHelper.enableDirectManipulationMode()
trong mỗi trường hợp. Để nghe những sự kiện này, hãy làm theo một trong những cách sau:- Đăng ký một
OnKeyListener
.
hoặc
- Mở rộng khung hiển thị, sau đó ghi đè phương thức
dispatchKeyEvent()
.
- Đăng ký một
- NÊN theo dõi các sự kiện nhắc nhở (
KEYCODE_DPAD_UP
,KEYCODE_DPAD_DOWN
,KEYCODE_DPAD_LEFT
hoặcKEYCODE_DPAD_RIGHT
) nếu khung hiển thị này xử lý thông báo nhắc nhở. - NÊN nghe
MotionEvent
và nhận số lượng xoay trongAXIS_SCROLL
nếu khung hiển thị muốn xử lý việc xoay. Có một số cách để thực hiện việc này:- Đăng ký một
OnGenericMotionListener
. - Mở rộng khung hiển thị và ghi đè phương thức
dispatchTouchEvent()
.
- Đăng ký một
- Để tránh bị mắc kẹt ở chế độ DM, PHẢI thoát khỏi chế độ DM khi Mảnh hoặc Hoạt động hiển thị thuộc về không tương tác.
- NÊN cung cấp chỉ dẫn bằng hình ảnh để cho biết chế độ xem đang ở chế độ DM.
Dưới đây là mẫu của chế độ xem tuỳ chỉnh sử dụng chế độ DM để xoay và thu phóng bản đồ:
/** 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(); }
Bạn có thể xem thêm ví dụ trong
Dự án RotaryPlayground
.
ActivityView (chế độ xem hoạt động)
Khi sử dụng ActivityView:
ActivityView
không được đặt làm tâm điểm.- (Android 11 QPR3, Ô tô Android 11,
không dùng nữa trong Android 11)
Nội dung củaActivityView
PHẢI chứaFocusParkingView
là chế độ xem có thể làm tâm điểm đầu tiên vàapp:shouldRestoreFocus
thuộc tính PHẢI làfalse
. - Nội dung của
ActivityView
không được cóandroid:focusByDefault
lượt xem.
Đối với người dùng, ActivityViews sẽ không ảnh hưởng đến hoạt động điều hướng ngoại trừ tiêu điểm đó
không thể mở rộng ActivityViews. Nói cách khác, bạn không thể có một lĩnh vực trọng tâm duy nhất
có nội dung bên trong và bên ngoài ActivityView
. Nếu bạn không thêm
bất kỳ FocusAreas nào vào ActivityView
của bạn, gốc của hệ phân cấp khung hiển thị trong
ActivityView
được coi là một khu vực tập trung ngầm ẩn.
Các nút hoạt động khi nhấn giữ
Hầu hết các nút đều thực hiện một số thao tác khi nhấp vào. Một số nút sẽ hoạt động khi bạn nhấn giữ.
Ví dụ: các nút Tua nhanh và Tua lại thường hoạt động khi nhấn giữ. Để thực hiện điều này
các nút hỗ trợ xoay, hãy lắng nghe KEYCODE_DPAD_CENTER
KeyEvents
như sau:
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; });
Trong đó mRunnable
thực hiện một hành động (chẳng hạn như tua lại) và tự lên lịch để
sẽ chạy sau độ trễ.
Chế độ cảm ứng
Người dùng có thể sử dụng bộ điều khiển xoay để tương tác với đầu phát trung tâm trong ô tô theo hai cách: bằng cách sử dụng bộ điều khiển xoay hoặc chạm vào màn hình. Khi sử dụng bộ điều khiển xoay, một trong các chế độ xem có thể làm tâm điểm được làm nổi bật. Khi chạm vào màn hình, không có phần nổi bật lấy tiêu điểm sẽ xuất hiện. Người dùng có thể chuyển đổi giữa các chế độ nhập này bất kỳ lúc nào:
- Xoay → chạm. Khi người dùng chạm vào màn hình, điểm nổi bật lấy tiêu điểm sẽ biến mất.
- Chạm → xoay. Khi người dùng di chuyển, xoay hoặc nhấn nút giữa, làm nổi bật tiêu điểm.
Nút Quay lại và Màn hình chính không ảnh hưởng đến chế độ nhập.
Xoay vòng khái niệm về
chế độ cảm ứng.
Bạn có thể sử dụng
View.isInTouchMode()
để xác định chế độ nhập mà người dùng đang sử dụng. Bạn có thể sử dụng
OnTouchModeChangeListener
để theo dõi những thay đổi. Mặc dù công cụ này có thể được dùng để tuỳ chỉnh giao diện người dùng của bạn cho
chế độ nhập, hãy tránh mọi thay đổi lớn vì chúng có thể gây khó chịu.
Khắc phục sự cố
Trong một ứng dụng được thiết kế cho thao tác chạm, thông thường, chúng tôi sẽ lồng ghép các khung hiển thị có thể làm tâm điểm.
Ví dụ: có thể có FrameLayout
xung quanh ImageButton
,
cả hai đều có thể làm tâm điểm. Điều này không có hại khi chạm vào nhưng có thể dẫn đến
trải nghiệm người dùng khi xoay vì người dùng phải xoay bộ điều khiển hai lần để di chuyển tới
chế độ xem tương tác tiếp theo. Để có được trải nghiệm người dùng tốt, Google khuyên bạn nên thực hiện một trong hai
chế độ xem bên ngoài hoặc chế độ xem bên trong có thể làm tâm điểm, nhưng không thể làm tâm điểm cả hai.
Nếu một nút hoặc công tắc bị mất tiêu điểm khi được nhấn qua bộ điều khiển xoay, thì một trong các điều kiện sau có thể áp dụng:
- Nút hoặc nút chuyển đang bị tắt (trong một thời gian ngắn hoặc vô thời hạn) do
đang được nhấn. Trong cả hai trường hợp, có hai cách để giải quyết vấn đề này:
- Để trạng thái
android:enabled
làtrue
và sử dụng chế độ tuỳ chỉnh trạng thái để chuyển nút sang màu xám hoặc chuyển đổi như được mô tả trong Trạng thái tuỳ chỉnh. - Dùng một vùng chứa để bao quanh nút hoặc nút chuyển và làm cho vùng chứa đó có thể làm tâm điểm thay vì dùng nút hoặc công tắc. (Trình nghe lượt nhấp phải nằm trên vùng chứa.)
- Để trạng thái
- Nút hoặc công tắc đang được thay thế. Ví dụ: hành động được thực hiện khi nút
được nhấn hoặc nút bật/tắt có thể kích hoạt làm mới các hành động hiện có
khiến các nút mới thay thế các nút hiện có. Có hai cách để giải quyết vấn đề này:
- Thay vì tạo một nút hoặc nút chuyển mới, hãy đặt biểu tượng và/hoặc văn bản của nút hoặc công tắc hiện có.
- Như trên, hãy thêm một vùng chứa có thể làm tâm điểm xung quanh nút hoặc nút chuyển.
Sân chơi xoay
RotaryPlayground
là một ứng dụng tham khảo cho chế độ xoay. Hãy sử dụng công cụ này để tìm hiểu cách tích hợp
các tính năng xoay trong ứng dụng của bạn. RotaryPlayground
có trong các bản dựng trình mô phỏng và trong
dành cho các thiết bị chạy Android Automotive OS (AAOS).
- Kho lưu trữ
RotaryPlayground
:packages/apps/Car/tests/RotaryPlayground/
- Phiên bản: Android 11 QPR3, Android 11 Car, và Android 12
Ứng dụng RotaryPlayground
hiện các thẻ sau ở bên trái:
- Thẻ. Thử nghiệm việc di chuyển xung quanh các khu vực trọng tâm, bỏ qua những phần không thể làm tâm điểm và nhập văn bản.
- Thao túng trực tiếp. Tiện ích kiểm thử hỗ trợ đơn giản và nâng cao chế độ thao túng trực tiếp. Thẻ này dành riêng cho thao tác trực tiếp trong cửa sổ ứng dụng.
- Thao tác với giao diện người dùng hệ thống. Kiểm thử các tiện ích hỗ trợ thao tác trực tiếp trong cửa sổ hệ thống chỉ hỗ trợ chế độ thao tác trực tiếp đơn giản.
- Lưới. Kiểm thử thao tác điều hướng xoay mẫu z bằng thao tác cuộn.
- Thông báo. Thử nghiệm nhắc vào và ra khỏi thông báo quan trọng.
- Cuộn. Thử nghiệm cuộn qua cả lựa chọn có thể làm tâm điểm và không thể làm tâm điểm nội dung.
- WebView. Kiểm thử việc điều hướng qua các đường liên kết trong
WebView
. - Tuỳ chỉnh
FocusArea
. Kiểm thử tuỳ chỉnhFocusArea
:- Tổng kết.
android:focusedByDefault
vàapp:defaultFocus
.
- Mục tiêu nhắc nhở rõ ràng.
- Dịch lối tắt.
FocusArea
không có chế độ xem có thể làm tâm điểm.