Trên các thiết bị màn hình lớn, người dùng thường tương tác với các ứng dụng bằng cách sử dụng bàn phím, chuột, bàn di chuột, bút cảm ứng hoặc tay điều khiển trò chơi. Để cho phép ứng dụng chấp nhận dữ liệu đầu vào từ các thiết bị ngoại vi, hãy làm như sau:
- Kiểm thử tính năng hỗ trợ bàn phím cơ bản, chẳng hạn như Ctrl+Z để huỷ, Ctrl+C để sao chép và Ctrl+S để lưu. Hãy xem phần Xử lý thao tác trên bàn phím để biết danh sách phím tắt mặc định.
- Kiểm thử khả năng hỗ trợ bàn phím nâng cao, ví dụ: điều hướng bằng phím Tab và phím mũi tên, xác nhận mục nhập văn bản bằng phím Enter và phát/tạm dừng bằng phím Dấu cách trong các ứng dụng đa phương tiện.
- Kiểm thử các hoạt động tương tác cơ bản với chuột, bao gồm cả thao tác nhấp chuột phải để mở trình đơn theo bối cảnh, thay đổi biểu tượng khi di chuột và con lăn chuột hoặc sự kiện cuộn trên bàn di chuột trên các thành phần tuỳ chỉnh.
- Kiểm thử các thiết bị đầu vào dành riêng cho ứng dụng, chẳng hạn như bút cảm ứng, tay điều khiển trò chơi và bộ điều khiển MIDI của ứng dụng nhạc.
- Cân nhắc việc hỗ trợ phương thức nhập nâng cao để có thể giúp ứng dụng trở nên nổi bật trong môi trường máy tính; ví dụ: bàn di chuột khi thích hợp cho các ứng dụng DJ, ẩn con trỏ chuột trong các trò chơi và các phím tắt mở rộng cho người dùng thành thạo.
Bàn phím
Cách ứng dụng phản hồi dữ liệu nhập bằng bàn phím góp phần mang lại trải nghiệm người dùng trên màn hình lớn. Có 3 cách nhập bằng bàn phím: di chuyển,tổ hợp phím và phím tắt.
Di chuyển
Tính năng di chuyển trên bàn phím hiếm khi được triển khai trong các ứng dụng tập trung vào thao tác chạm, nhưng người dùng mong đợi điều này khi họ sử dụng ứng dụng và bàn phím. Điều hướng bằng bàn phím có thể rất cần thiết trên điện thoại, máy tính bảng, thiết bị có thể gập lại và máy tính cho những người dùng có nhu cầu hỗ trợ tiếp cận.
Đối với nhiều ứng dụng, phím mũi tên và thao tác trên thẻ được khung Android xử lý tự động. Ví dụ: Button
có thể lấy tiêu điểm theo mặc định và hoạt động điều hướng bằng bàn phím thường sẽ hoạt động mà không cần thêm mã nào. Để bật tính năng di chuyển bằng bàn phím cho các thành phần hiển thị không thể lấy tiêu điểm theo mặc định, hãy đánh dấu các thành phần hiển thị đó là có thể lấy tiêu điểm. Bạn có thể thực hiện việc này theo cách lập trình hoặc trong XML:
Kotlin
yourView.isFocusable = true
Java
yourView.setFocusable(true);
Ngoài ra, bạn có thể thiết lập thuộc tính focusable
trong tệp bố cục:
android:focusable="true"
Để tìm hiểu thêm, hãy xem phần Xử lý tiêu điểm.
Khi tiêu điểm được bật, khung Android sẽ tạo một mục ánh xạ điều hướng cho mọi chế độ xem có thể lấy tiêu điểm dựa vào vị trí của chúng. Phương thức này thường hoạt động như dự kiến và bạn không cần làm gì thêm. Khi mối liên kết mặc định không chính xác đối với nhu cầu của ứng dụng, bạn có thể ghi đè mối liên kết đó như sau:
Kotlin
// Arrow keys yourView.nextFocusLeftId = R.id.view_to_left yourView.nextFocusRightId = R.id.view_to_right yourView.nextFocusTopId = R.id.view_above yourView.nextFocusBottomId = R.id.view_below // Tab key yourView.nextFocusForwardId = R.id.next_view
Java
// Arrow keys yourView.setNextFocusLeftId(R.id.view_to_left); yourView.setNextFocusRightId(R.id.view_to_left); yourView.setNextFocusTopId(R.id.view_to_left); yourView.setNextFocusBottomId(R.id.view_to_left); // Tab key yourView.setNextFocusForwardId(R.id.next_view);
Kiểm thử quyền truy cập vào mọi thành phần trên giao diện người dùng của ứng dụng chỉ bằng bàn phím. Người dùng phải truy cập được các thành phần thường dùng mà không cần phải sử dụng chuột hoặc thao tác chạm.
Lưu ý rằng hỗ trợ bàn phím có thể rất cần thiết cho những người dùng có nhu cầu hỗ trợ tiếp cận tính năng.
Thao tác phím
Đối với văn bản nhập bằng bàn phím ảo trên màn hình (IME), chẳng hạn như đối với, EditText
,, ứng dụng sẽ hoạt động như dự tính trên các thiết bị màn hình lớn mà nhà phát triển không phải làm gì thêm. Đối với các tổ hợp phím khung không thể đoán trước được, ứng dụng cần phải tự xử lý hành vi. Điều này đặc biệt đúng với các ứng dụng có chế độ xem tuỳ chỉnh.
Một số ví dụ là ứng dụng trò chuyện sử dụng phím Enter để gửi tin nhắn, ứng dụng nghe nhìn bắt đầu và dừng phát bằng Phím cách và các trò chơi điều khiển di chuyển bằng các phím w, a, s và d.
Hầu hết các ứng dụng đều ghi đè lệnh gọi lại onKeyUp()
và thêm hành vi dự kiến cho mỗi mã phím nhận được:
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when (keyCode) { KeyEvent.KEYCODE_ENTER -> { sendChatMessage() true } KeyEvent.KEYCODE_SPACE -> { playOrPauseMedia() true } else -> super.onKeyUp(keyCode, event) } }
Java
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { sendMessage(); return true; } else if (KeyEvent.KEYCODE_SPACE){ playOrPauseMedia(); return true; } else { return super.onKeyUp(keyCode, event); } }
Sự kiện onKeyUp
xảy ra khi một phím được nhả. Khi dùng lệnh gọi lại này, ứng dụng sẽ không cần phải xử lý nhiều sự kiện onKeyDown
nếu một phím được nhấn giữ hoặc thả chậm. Các trò chơi và ứng dụng cần phát hiện thời điểm nhấn phím hoặc liệu người dùng có đang nhấn và giữ phím hay không có thể nghe sự kiện onKeyDown
và tự xử lý các sự kiện onKeyDown
lặp lại.
Để biết thêm thông tin, hãy xem phần Xử lý thao tác trên bàn phím.
Phím tắt
Bạn nên sử dụng các phím tắt thông thường như Ctrl, Alt, Shift và Meta khi sử dụng bàn phím phần cứng. Nếu một ứng dụng không triển khai phím tắt, người dùng có thể cảm thấy khó chịu với trải nghiệm đó. Người dùng nâng cao cũng đánh giá cao các phím tắt cho các tác vụ thường dùng trong ứng dụng. Phím tắt giúp ứng dụng dễ sử dụng hơn và đem lại sự khác biệt của nó đối với ứng dụng không có phím tắt.
Một số phím tắt phổ biến bao gồm Ctrl+S (lưu), Ctrl+Z (huỷ) và Ctrl+Shift+Z (làm lại). Để biết danh sách phím tắt mặc định, hãy xem phần Xử lý thao tác trên bàn phím.
Bạn có thể bật phím tắt bằng cách triển khai dispatchKeyShortcutEvent()
để chặn mọi tổ hợp phím (Alt, Ctrl, Shift và Meta) cho một mã phím nhất định.
Để kiểm tra một phím bổ trợ cụ thể, hãy sử dụng:
KeyEvent.isCtrlPressed()
,KeyEvent.isShiftPressed()
,KeyEvent.isAltPressed()
,KeyEvent.isMetaPressed()
hoặc
Kotlin
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean { return when (event.keyCode) { KeyEvent.KEYCODE_O -> { openFile() // Ctrl+O, Shift+O, Alt+O true } KeyEvent.KEYCODE_Z-> { if (event.isCtrlPressed) { if (event.isShiftPressed) { redoLastAction() // Ctrl+Shift+Z pressed true } else { undoLastAction() // Ctrl+Z pressed true } } } else -> { return super.dispatchKeyShortcutEvent(event) } } }
Java
@Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_O) { openFile(); // Ctrl+O, Shift+O, Alt+O return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_Z) { if (event.isCtrlPressed()) { if (event.isShiftPressed()) { redoLastAction(); return true; } else { undoLastAction(); return true; } } } return super.dispatchKeyShortcutEvent(event); }
Việc tách mã phím tắt khỏi các thao tác tổ hợp phím khác (chẳng hạn như onKeyUp()
và onKeyDown()
) sẽ chấp nhận các phím sửa đổi theo mặc định mà không cần phải triển khai kiểm tra phím sửa đổi theo cách thủ công trong mọi trường hợp. Việc cho phép tất cả các tổ hợp phím sửa đổi cũng có thể thuận tiện hơn cho những người dùng quen với bố cục bàn phím và hệ điều hành khác.
Tuy nhiên, bạn cũng có thể triển khai phím tắt trong onKeyUp()
bằng cách kiểm tra KeyEvent.isCtrlPressed()
, KeyEvent.isShiftPressed()
hoặc KeyEvent.isAltPressed()
. Điều này có thể dễ dàng duy trì hơn nếu hành vi phím đã sửa đổi thay đổi nhiều hơn hành vi ứng dụng so với phím tắt. Ví dụ: trong các trò chơi, khi W có nghĩa là "đi về phía trước" và Shift+W có nghĩa là "chạy về phía trước".
Kotlin
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when(keyCode) { KeyEvent.KEYCODE_W-> { if (event.isShiftPressed) { if (event.isCtrlPressed) { flyForward() // Ctrl+Shift+W pressed true } else { runForward() // Shift+W pressed true } } else { walkForward() // W pressed true } } else -> super.onKeyUp(keyCode, event) } }
Java
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_W) { if (event.isShiftPressed()) { if (event.isCtrlPressed()) { flyForward(); // Ctrl+Shift+W pressed return true; } else { runForward(); // Shift+W pressed return true; } } else { walkForward(); return true; } } return super.onKeyUp(keyCode, event); }
Xem thêm Trình trợ giúp phím tắt.
Bút cảm ứng
Nhiều thiết bị màn hình lớn có bút cảm ứng. Các ứng dụng Android xử lý bút cảm ứng dưới dạng thao tác trên màn hình cảm ứng. Một số thiết bị cũng có thể có USB hoặc bảng vẽ Bluetooth, như Wacom Intuos. Các ứng dụng Android có thể nhận đầu vào bằng Bluetooth nhưng không nhận được đầu vào qua USB.
Sự kiện bút cảm ứng được báo cáo là sự kiện có màn hình cảm ứng qua View#onTouchEvent()
hoặc View#onGenericMotionEvent()
và chứa một MotionEvent#getSource()
thuộc loại SOURCE_STYLUS
.
Đối tượng MotionEvent
chứa thông tin về sự kiện:
MotionEvent#getToolType()
trả vềTOOL_TYPE_FINGER
,TOOL_TYPE_STYLUS
hoặcTOOL_TYPE_ERASER
tuỳ thuộc vào công cụ chạm vào màn hìnhMotionEvent#getPressure()
báo cáo áp lực vật lý áp dụng cho bút cảm ứng (nếu được hỗ trợ)MotionEvent#getAxisValue()
thông quaMotionEvent.AXIS_TILT
vàMotionEvent.AXIS_ORIENTATION
cung cấp độ nghiêng vật lý và hướng của bút cảm ứng (nếu được hỗ trợ)
Điểm trước đó
Android phân chia hàng loạt sự kiện đầu vào và phân phối chúng cho mỗi khung. Bút cảm ứng có thể báo cáo các sự kiện có tần suất cao hơn nhiều so với màn hình. Khi tạo các ứng dụng vẽ, hãy kiểm tra các sự kiện có thể xảy ra trong quá khứ gần bằng cách sử dụng các API getHistorical
:
MotionEvent#getHistoricalX()
MotionEvent#getHistoricalY()
MotionEvent#getHistoricalPressure()
MotionEvent#getHistoricalAxisValue()
Tính năng chống tì tay
Khi người dùng vẽ, viết hoặc tương tác với ứng dụng của bạn bằng bút cảm ứng, đôi khi người dùng chạm lòng bàn tay vào màn hình. Sự kiện chạm (được đặt thành ACTION_DOWN
hoặc ACTION_POINTER_DOWN
) có thể được báo cáo cho ứng dụng của bạn trước khi hệ thống nhận dạng và bỏ qua thao tác chạm vô tình.
Android huỷ các sự kiện chạm tay bằng cách gửi một MotionEvent
. Nếu ứng dụng của bạn nhận được ACTION_CANCEL
, hãy huỷ cử chỉ. Nếu ứng dụng của bạn nhận được ACTION_POINTER_UP
, hãy kiểm tra xem FLAG_CANCELED
đã được đặt hay chưa. Nếu có, hãy huỷ cử chỉ.
Đừng chỉ tìm kiếm FLAG_CANCELED
. Trên Android 13 (API cấp 33) trở lên, hệ thống sẽ đặt FLAG_CANCELED
cho các sự kiện ACTION_CANCEL
, nhưng hệ thống không đặt cờ trên các phiên bản Android thấp hơn.
Android 12
Trên Android 12 (API cấp 32) trở xuống, bạn chỉ có thể phát hiện tính năng từ chối cảm ứng bằng lòng bàn tay đối với các sự kiện chạm con trỏ một lần. Nếu thao tác chạm lòng bàn tay là sự kiện con trỏ duy nhất, hệ thống sẽ huỷ sự kiện bằng cách đặt ACTION_CANCEL
trên đối tượng sự kiện chuyển động. Nếu các con trỏ khác không hoạt động, hệ thống sẽ đặt ACTION_POINTER_UP
, điều này không đủ để phát hiện tính năng từ chối cảm ứng bằng lòng bàn tay.
Android 13
Trên Android 13 (API cấp 33) trở lên, nếu thao tác chạm lòng bàn tay là sự kiện con trỏ duy nhất, hệ thống sẽ huỷ sự kiện bằng cách đặt ACTION_CANCEL
và FLAG_CANCELED
trên đối tượng sự kiện chuyển động. Nếu các con trỏ khác không hoạt động, hệ thống sẽ đặt ACTION_POINTER_UP
và FLAG_CANCELED
.
Bất cứ khi nào ứng dụng của bạn nhận được một sự kiện chuyển động bằng ACTION_POINTER_UP
, hãy kiểm tra
FLAG_CANCELED
để xác định xem sự kiện đó có cho thấy việc từ chối cảm ứng bằng lòng bàn tay (hoặc sự kiện nào đó bị huỷ) hay không.
Ứng dụng ghi chú
ChromeOS có ý định đặc biệt là hiển thị các ứng dụng ghi chú đã đăng ký cho người dùng. Để đăng ký một ứng dụng làm ứng dụng ghi chú, hãy thêm đoạn mã sau vào tệp kê khai ứng dụng:
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Khi một ứng dụng được đăng ký với hệ thống, người dùng có thể chọn ứng dụng đó làm ứng dụng ghi chú mặc định. Khi có yêu cầu ghi chú mới, ứng dụng sẽ tạo một ghi chú trống để sẵn sàng nhập văn bản bằng bút cảm ứng. Khi người dùng muốn chú thích một hình ảnh (chẳng hạn như ảnh chụp màn hình hoặc hình đã tải xuống), ứng dụng sẽ chạy với ClipData
chứa một hoặc nhiều mục content://
có nhiều URI. Ứng dụng sẽ tạo một ghi chú sử dụng hình ảnh đính kèm đầu tiên làm hình nền và chuyển sang chế độ người dùng có thể vẽ trên màn hình bằng bút cảm ứng.
Kiểm thử ý định ghi chú không cần bút cảm ứng
[TBD remove section.]
Để kiểm tra xem một ứng dụng có phản hồi chính xác các ý định ghi chú không cần dùng bút cảm ứng đang hoạt động hay không, hãy sử dụng phương thức sau để hiển thị các tuỳ chọn ghi chú trên ChromeOS:
- Chuyển sang chế độ nhà phát triển và đặt thiết bị ở chế độ có thể ghi
- Nhấn tổ hợp phím Ctrl+Alt+F2 để mở một thiết bị đầu cuối
- Chạy lệnh
sudo vi /etc/chrome_dev.conf
- Nhấn
i
để chỉnh sửa và thêm--ash-enable-palette
vào một dòng mới ở cuối tệp - Lưu bằng cách nhấn phím Esc rồi nhập :, w, q rồi nhấn phím Enter
- Nhấn tổ hợp phím Ctrl+Alt+F1 để quay lại giao diện người dùng ChromeOS thông thường
- Đăng xuất rồi đăng nhập lại
Lúc này, bạn sẽ thấy một trình đơn bút cảm ứng trên kệ:
- Nhấn vào nút bút cảm ứng trên kệ và chọn Ghi chú mới. Thao tác này sẽ mở một bản ghi chú trống.
- Chụp ảnh màn hình. Từ kệ, hãy chọn nút bút cảm ứng > Chụp màn hình hoặc tải ảnh xuống. Bạn nên chọn Chú thích hình ảnh trong thông báo. Thao tác này sẽ mở ra ứng dụng có hình ảnh đã sẵn sàng chú thích.
Hỗ trợ chuột và bàn di chuột
Hầu hết các ứng dụng thường chỉ cần xử lý 3 sự kiện tập trung vào màn hình lớn: nhấp chuột phải, di chuột và kéo và thả.
Nhấp chuột phải
Mọi thao tác khiến ứng dụng hiển thị trình đơn theo bối cảnh, chẳng hạn như chạm và giữ một mục trong danh sách, cũng phải phản ứng với các sự kiện nhấp chuột phải.
Để xử lý các sự kiện nhấp chuột phải, ứng dụng cần đăng ký View.OnContextClickListener
:
Kotlin
yourView.setOnContextClickListener { showContextMenu() true }
Java
yourView.setOnContextClickListener(v -> { showContextMenu(); return true; });
Để biết thông tin chi tiết về cách tạo trình đơn theo bối cảnh, hãy xem phần Tạo trình đơn theo bối cảnh.
Khoảng cách di
Bạn có thể khiến bố cục ứng dụng của mình trông gọn gàng và dễ sử dụng hơn bằng cách xử lý các sự kiện di chuột. Điều này đặc biệt đúng đối với các thành phần lượt xem:
Kotlin
// Change the icon to a "hand" pointer on hover. // Highlight the view by changing the background. yourView.setOnHoverListener { view, _ -> addVisualHighlighting(true) view.pointerIcon = PointerIcon.getSystemIcon(view.context, PointerIcon.TYPE_HAND) true // Listener consumes the event. }
Java
// Change the icon to a "hand" pointer on hover. // Highlight the view by changing the background. yourView.setOnHoverListener((view, event) -> { addVisualHighlighting(true); view.setPointerIcon( PointerIcon.getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND) ); return true; // Listener consumes the event. });
Hai ví dụ phổ biến nhất về vấn đề này là:
- Cho người dùng biết liệu một phần tử có hành vi tương tác hay không, chẳng hạn như có thể nhấp hoặc chỉnh sửa bằng cách thay đổi biểu tượng con trỏ chuột
- Thêm phản hồi bằng hình ảnh vào các mục trong một danh sách lớn hoặc dạng lưới khi con trỏ đang di chuột qua các mục đó
Kéo và thả
Trong môi trường nhiều cửa sổ, người dùng muốn có thể kéo và thả các mục giữa các ứng dụng. Điều này đúng với các thiết bị máy tính bàn cũng như máy tính bảng, điện thoại và thiết bị gập ở chế độ chia đôi màn hình.
Cân nhắc xem liệu người dùng có khả năng kéo các mục vào ứng dụng của bạn hay không. Ví dụ: trình chỉnh sửa ảnh phải nhận được ảnh, trình phát âm thanh sẽ phải nhận được tệp âm thanh và chương trình vẽ sẽ phải nhận được ảnh.
Để thêm tính năng hỗ trợ kéo và thả, hãy xem bài viết Bật tính năng kéo và thả và bài đăng trên blog Android trên ChromeOS — Triển khai tính năng Kéo và thả.
Những điều cần đặc biệt lưu ý đối với ChromeOS
- Hãy nhớ yêu cầu quyền bằng
requestDragAndDropPermissions()
để truy cập vào các mục được kéo vào từ bên ngoài ứng dụng Một mục phải gắn cờ
View.DRAG_FLAG_GLOBAL
để được kéo vào các ứng dụng khác
Hỗ trợ con trỏ nâng cao
Các ứng dụng xử lý đầu vào bằng chuột và bàn di chuột nâng cao phải triển khai đối tượng sửa đổi
View#onGenericMotionEvent()
và sử dụng [MotionEvent.getSource()
][] để phân biệt giữa SOURCE_MOUSE
và SOURCE_TOUCHSCREEN
.
Kiểm tra đối tượng MotionEvent
để triển khai hành vi bắt buộc:
- Di chuyển tạo ra
ACTION_HOVER_MOVE
sự kiện. - Các nút tạo ra
ACTION_BUTTON_PRESS
vàACTION_BUTTON_RELEASE
sự kiện. Bạn cũng có thể kiểm tra trạng thái hiện tại của tất cả các nút chuột và bàn di chuột bằng cách sử dụnggetButtonState()
. - Thao tác cuộn con lăn chuột sẽ tạo ra
ACTION_SCROLL
sự kiện.
Tay điều khiển trò chơi
Một số thiết bị Android màn hình lớn hỗ trợ lên đến bốn tay điều khiển trò chơi. Sử dụng các API tay điều khiển trò chơi Android tiêu chuẩn để xử lý tay điều khiển trò chơi (xem phần Hỗ trợ tay điều khiển trò chơi).
Các nút trên tay điều khiển trò chơi được liên kết tới các giá trị chung theo một liên kết chung. Tuy nhiên, không phải nhà sản xuất tay điều khiển trò chơi nào cũng tuân theo cùng một quy ước liên kết. Bạn có thể cung cấp trải nghiệm tốt hơn nhiều nếu cho phép người dùng chọn cách sắp xếp tay điều khiển phổ biến khác nhau. Hãy xem bài viết Xử lý thao tác nhấn nút trên tay điều khiển trò chơi để biết thêm thông tin.
Chế độ dịch dữ liệu đầu vào
Theo mặc định, ChromeOS cho phép bật chế độ dịch. Đối với hầu hết ứng dụng Android, chế độ này giúp các ứng dụng hoạt động như mong muốn trong môi trường máy tính bàn. Một số ví dụ bao gồm việc tự động cho phép cuộn bằng hai ngón tay trên bàn di chuột, cuộn con lăn chuột và ánh xạ toạ độ màn hình thô đến toạ độ cửa sổ. Nhìn chung, các nhà phát triển ứng dụng không cần thiết phải tự triển khai bất kỳ hành vi nào trong số này.
Nếu một ứng dụng triển khai hành vi nhập dữ liệu tuỳ chỉnh, chẳng hạn như xác định một thao tác chụm bàn di chuột bằng hai ngón tay tuỳ chỉnh, hoặc các bản dịch đầu vào này không cung cấp các sự kiện nhập như ứng dụng mong đợi, bạn có thể tắt chế độ dịch đầu vào bằng cách thêm thẻ sau vào tệp kê khai Android:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />