Na urządzeniach z dużym ekranem użytkownicy często wchodzą w interakcje z aplikacjami za pomocą klawiatury, myszy, trackpada, rysika lub pada do gier. Aby umożliwić aplikacji przyjmowanie danych wejściowych z urządzeń zewnętrznych:
- Przetestuj podstawową obsługę klawiatury, np. Ctrl+Z do cofania, Ctrl+C do kopiowania i Ctrl+S do zapisywania. Listę domyślnych skrótów klawiszowych znajdziesz w artykule Obsługa działań wykonywanych za pomocą klawiatury.
- Przetestuj zaawansowaną obsługę klawiatury, np. nawigację za pomocą klawisza Tab i strzałek, potwierdzanie wprowadzania tekstu za pomocą klawisza Enter, oraz odtwarzanie i wstrzymywanie w aplikacjach multimedialnych za pomocą spacji.
- Przetestuj podstawowe interakcje z myszą, w tym kliknięcie prawym przyciskiem myszy w celu otwarcia menu kontekstowego, zmiany ikon po najechaniu kursorem oraz zdarzenia przewijania za pomocą kółka myszy lub trackpada w komponentach niestandardowych.
- Przetestuj urządzenia wejściowe specyficzne dla aplikacji, takie jak rysik, kontrolery do gier i kontrolery MIDI w aplikacjach muzycznych.
- Rozważ obsługę zaawansowanych danych wejściowych, które mogą wyróżnić aplikację w środowiskach komputerowych, np. trackpad jako crossfader w aplikacjach dla DJ-ów, przechwytywanie myszy w grach i skróty klawiszowe dla użytkowników, którzy głównie korzystają z klawiatury.
Klawiatura
Sposób, w jaki aplikacja reaguje na dane wejściowe z klawiatury, wpływa na wygodę użytkowników korzystających z dużego ekranu. Istnieją 3 rodzaje danych wejściowych z klawiatury: nawigacja, naciśnięcia klawiszy, i skróty.
Nawigacja
Nawigacja za pomocą klawiatury jest rzadko implementowana w aplikacjach, w których główną rolę odgrywa dotyk, ale użytkownicy oczekują jej, gdy korzystają z aplikacji i mają ręce na klawiaturze. Nawigacja za pomocą klawiatury może być niezbędna na telefonach, tabletach, urządzeniach składanych i komputerach stacjonarnych dla użytkowników z potrzebami w zakresie ułatwień dostępu.
W przypadku wielu aplikacji nawigacja za pomocą strzałek i klawisza Tab jest obsługiwana automatycznie przez platformę Android. Na przykład element Button jest domyślnie możliwy do zaznaczenia, a nawigacja za pomocą klawiatury powinna działać bez dodatkowego kodu. Aby włączyć nawigację za pomocą klawiatury w przypadku widoków, które nie są domyślnie możliwe do zaznaczenia, oznacz je jako możliwe do zaznaczenia. Można to zrobić programowo lub w kodzie XML:
Kotlin
yourView.isFocusable = true
Java
yourView.setFocusable(true);
Możesz też ustawić atrybut focusable w pliku układu:
android:focusable="true"
Więcej informacji znajdziesz w artykule Obsługa zaznaczenia.
Gdy zaznaczenie jest włączone, platforma Android tworzy mapowanie nawigacyjne dla wszystkich widoków, które można zaznaczyć, na podstawie ich pozycji. Zwykle działa to zgodnie z oczekiwaniami i nie wymaga dalszego rozwoju. Jeśli domyślne mapowanie nie jest odpowiednie dla potrzeb aplikacji, można je zastąpić w ten sposób:
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);
Przetestuj dostęp do każdego elementu interfejsu aplikacji za pomocą samej klawiatury. Często używane elementy powinny być dostępne bez użycia myszy lub dotyku.
Pamiętaj, że obsługa klawiatury może być niezbędna dla użytkowników z potrzebami w zakresie ułatwień dostępu.
Naciśnięcia klawiszy
W przypadku wprowadzania tekstu, które byłoby obsługiwane przez ekranową klawiaturę wirtualną (IME),
takich jak
an EditText
, aplikacje powinny działać zgodnie z oczekiwaniami na urządzeniach z dużym ekranem bez dodatkowych
prac programistycznych. W przypadku naciśnięć klawiszy, których platforma nie może przewidzieć, aplikacje muszą samodzielnie obsługiwać zachowanie. Dotyczy to zwłaszcza aplikacji z widokami niestandardowymi.
Przykłady to aplikacje do czatowania, które używają klawisza Enter do wysyłania wiadomości, aplikacje multimedialne, które rozpoczynają i zatrzymują odtwarzanie za pomocą spacji, oraz gry które sterują ruchem za pomocą klawiszy w, a, s i d.
Większość aplikacji zastępuje wywołanie zwrotne onKeyUp() i dodaje oczekiwane zachowanie
dla każdego otrzymanego kodu klawisza:
Kotlin
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);
}
}
Zdarzenie onKeyUp występuje, gdy klawisz zostanie zwolniony. Użycie wywołania zwrotnego
zapobiega konieczności przetwarzania przez aplikacje wielu onKeyDown zdarzeń, jeśli klawisz
jest przytrzymywany lub zwalniany powoli. Gry i aplikacje, które muszą wykrywać moment naciśnięcia klawisza lub to, czy użytkownik przytrzymuje klawisz, mogą nasłuchiwać zdarzenia onKeyDown i samodzielnie obsługiwać powtarzające się zdarzenia onKeyDown.
Więcej informacji znajdziesz w artykule Obsługa działań wykonywanych za pomocą klawiatury.
Skróty
Podczas korzystania z klawiatury sprzętowej oczekuje się typowych skrótów klawiszowych, które obejmują klawisze Ctrl, Alt, Shift i Meta. Jeśli aplikacja nie implementuje skrótów, użytkownicy mogą być sfrustrowani. Zaawansowani użytkownicy doceniają też skróty do często używanych zadań specyficznych dla aplikacji. Skróty ułatwiają korzystanie z aplikacji i odróżniają ją od aplikacji, które nie mają skrótów.
Do typowych skrótów należą Ctrl+S (zapisz), Ctrl+Z (cofnij) i Ctrl+Shift+Z (przywróć). Listę domyślnych skrótów znajdziesz w artykule Obsługa działań wykonywanych za pomocą klawiatury.
Skróty można włączyć, implementując dispatchKeyShortcutEvent() w celu
przechwytywania wszystkich kombinacji klawiszy (Alt, Ctrl, Shift i Meta) dla danego kodu klawisza.
Aby sprawdzić określony klawisz modyfikujący, użyj:
KeyEvent.isCtrlPressed(),KeyEvent.isShiftPressed(),KeyEvent.isAltPressed(),KeyEvent.isMetaPressed()lub
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);
}
Oddzielenie kodu skrótu od innych funkcji obsługi naciśnięć klawiszy (np. onKeyUp() i onKeyDown()) domyślnie akceptuje klawisze modyfikujące bez konieczności ręcznego implementowania sprawdzania klawiszy modyfikujących w każdym przypadku. Umożliwienie wszystkich kombinacji klawiszy modyfikujących może być też wygodniejsze dla użytkowników, którzy są przyzwyczajeni do różnych układów klawiatury i systemów operacyjnych.
Możesz też implementować skróty w onKeyUp(), sprawdzając KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed() lub KeyEvent.isAltPressed(). Może to być łatwiejsze w utrzymaniu, jeśli zmodyfikowane zachowanie klawisza jest bardziej zmianą zachowania aplikacji niż skrótem. Na przykład w grach, gdy W oznacza „idź do przodu”, a Shift+W oznacza „biegnij do przodu”.
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);
}
Zobacz też Pomocnik skrótów klawiszowych.
Rysik
Wiele urządzeń z dużym ekranem jest wyposażonych w rysik. Aplikacje na Androida obsługują rysiki jako dane wejściowe z ekranu dotykowego. Niektóre urządzenia mogą też mieć tablet graficzny USB lub Bluetooth, np. Wacom Intuos. Aplikacje na Androida mogą odbierać dane wejściowe przez Bluetooth, ale nie przez USB.
Zdarzenie rysika jest zgłaszane jako zdarzenie ekranu dotykowego przez View#onTouchEvent()
lub View#onGenericMotionEvent() i zawiera
MotionEvent#getSource() typu SOURCE_STYLUS.
Obiekt MotionEvent zawiera informacje o zdarzeniu:
MotionEvent#getToolType()zwracaTOOL_TYPE_FINGER,TOOL_TYPE_STYLUSlubTOOL_TYPE_ERASERw zależności od narzędzia, które dotknęło wyświetlacza.MotionEvent#getPressure()zgłasza fizyczny nacisk wywierany na rysik (jeśli jest obsługiwany).MotionEvent#getAxisValue()zMotionEvent.AXIS_TILTiMotionEvent.AXIS_ORIENTATIONpodaje fizyczne nachylenie i orientację rysika (jeśli są obsługiwane).
Punkty historyczne
Android grupuje zdarzenia wejściowe i dostarcza je raz na klatkę. Rysik może zgłaszać zdarzenia z dużo większą częstotliwością niż wyświetlacz. Podczas tworzenia aplikacji do rysowania sprawdzaj zdarzenia, które mogły wystąpić w niedalekiej przeszłości, za pomocą interfejsów API getHistorical:
MotionEvent#getHistoricalX()MotionEvent#getHistoricalY()MotionEvent#getHistoricalPressure()MotionEvent#getHistoricalAxisValue()
Odrzucanie dotyku dłonią
Gdy użytkownicy rysują, piszą lub wchodzą w interakcje z Twoją aplikacją za pomocą rysika, czasami dotykają ekranu dłonią. Zdarzenie dotknięcia (ustawione na
ACTION_DOWN lub ACTION_POINTER_DOWN) może zostać zgłoszone do Twojej aplikacji
zanim system rozpozna i zignoruje przypadkowy dotyk dłonią.
Android anuluje zdarzenia dotyku dłonią, wysyłając MotionEvent. Jeśli Twoja
aplikacja otrzyma ACTION_CANCEL, anuluj gest. Jeśli Twoja aplikacja otrzyma
ACTION_POINTER_UP, sprawdź, czy ustawiona jest flaga FLAG_CANCELED. Jeśli tak, anuluj gest.
Nie sprawdzaj tylko FLAG_CANCELED. W Androidzie 13 (API na poziomie 33) i nowszym system ustawia FLAG_CANCELED dla zdarzeń ACTION_CANCEL, ale w starszych wersjach Androida system nie ustawia tej flagi.
Android 12
W Androidzie 12 (API na poziomie 32) i starszym wykrywanie odrzucania dotyku dłonią jest możliwe tylko w przypadku zdarzeń dotyku jednym palcem. Jeśli dotyk dłonią jest jedynym wskaźnikiem, system anuluje zdarzenie, ustawiając ACTION_CANCEL w obiekcie zdarzenia ruchu. Jeśli inne wskaźniki są wciśnięte, system ustawia ACTION_POINTER_UP, co jest niewystarczające do wykrycia odrzucania dotyku dłonią.
Android 13
W Androidzie 13 (API na poziomie 33) i nowszym, jeśli dotyk dłonią jest jedynym wskaźnikiem, system anuluje zdarzenie, ustawiając ACTION_CANCEL i FLAG_CANCELED w obiekcie zdarzenia ruchu. Jeśli inne wskaźniki są wciśnięte, system ustawia ACTION_POINTER_UP i FLAG_CANCELED.
Za każdym razem, gdy Twoja aplikacja otrzyma zdarzenie ruchu z ACTION_POINTER_UP, sprawdź, czy ustawiona jest flaga FLAG_CANCELED, aby określić, czy zdarzenie wskazuje na odrzucenie dotyku dłonią (lub inne anulowanie zdarzenia).
Aplikacje do robienia notatek
ChromeOS ma specjalny intent, który wyświetla użytkownikom zarejestrowane aplikacje do robienia notatek. Aby zarejestrować aplikację jako aplikację do robienia notatek, dodaj do manifestu aplikacji te informacje:
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Gdy aplikacja jest zarejestrowana w systemie, użytkownik może wybrać ją jako domyślną aplikację do robienia notatek. Gdy zostanie poproszony o utworzenie nowej notatki, aplikacja powinna utworzyć pustą notatkę gotową do wprowadzania danych za pomocą rysika. Gdy użytkownik chce dodać adnotacje do obrazu (np. zrzutu ekranu lub pobranego obrazu), aplikacja uruchamia się z ClipData zawierającym co najmniej 1 element z identyfikatorami URI content://. Aplikacja powinna utworzyć notatkę, która używa pierwszego załączonego obrazu jako obrazu tła, i przejść do trybu, w którym użytkownik może rysować na ekranie za pomocą rysika.
Testowanie intentów do robienia notatek bez rysika
Aby sprawdzić, czy aplikacja prawidłowo reaguje na intenty do robienia notatek bez aktywnego rysika, użyj tej metody, aby wyświetlić opcje robienia notatek w ChromeOS:
- Przejdź do trybu deweloperskiego i włącz zapisywanie na urządzeniu.
- Naciśnij Ctrl+Alt+F2, aby otworzyć terminal.
- Uruchom polecenie
sudo vi /etc/chrome_dev.conf. - Naciśnij
i, aby edytować, i dodaj--ash-enable-palettedo nowego wiersza na końcu pliku. - Zapisz, naciskając Esc, a następnie wpisując :, w, q i naciskając Enter
- Naciśnij Ctrl+Alt+F1, aby wrócić do zwykłego interfejsu ChromeOS.
- Wyloguj się, a następnie zaloguj się ponownie.
Na półce powinna teraz znajdować się ikona rysika:
- Kliknij przycisk rysika na półce i wybierz Nowa notatka. Powinna się otworzyć pusta notatka do rysowania.
- Zrób zrzut ekranu. Na półce kliknij przycisk rysika > Zrzut ekranu lub pobierz obraz. W powiadomieniu powinna być opcja Dodaj adnotacje do obrazu. Powinno to spowodować uruchomienie aplikacji z obrazem gotowym do dodania adnotacji.
Obsługa myszy i touchpada
Większość aplikacji musi zwykle obsługiwać tylko 3 zdarzenia związane z dużym ekranem: kliknięcie prawym przyciskiem myszy, najechanie i przeciąganie i upuszczanie.
Kliknięcie prawym przyciskiem
Wszystkie działania, które powodują wyświetlenie przez aplikację menu kontekstowego, np. dotknięcie i przytrzymanie elementu listy, powinny też reagować na zdarzenia kliknięcia prawym przyciskiem myszy.
Aby obsługiwać zdarzenia kliknięcia prawym przyciskiem myszy, aplikacje powinny zarejestrować
View.OnContextClickListener:
Kotlin
yourView.setOnContextClickListener {
showContextMenu()
true
}
Java
yourView.setOnContextClickListener(v -> {
showContextMenu();
return true;
});
Szczegółowe informacje o tworzeniu menu kontekstowych znajdziesz w artykule Tworzenie menu kontekstowego.
Najechanie
Obsługując zdarzenia najechania, możesz sprawić, że układy aplikacji będą bardziej dopracowane i łatwiejsze w użyciu. Dotyczy to zwłaszcza komponentów niestandardowych widoków:
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.
});
Oto 2 najczęstsze przykłady:
- Wskazywanie użytkownikom, czy element ma zachowanie interaktywne, np. czy można go kliknąć lub edytować, przez zmianę ikony wskaźnika myszy.
- Dodawanie wizualnych informacji zwrotnych do elementów na dużej liście lub w siatce, gdy wskaźnik znajduje się nad nimi.
Przeciągnij i upuść
W środowisku wielookienkowym użytkownicy oczekują, że będą mogli przeciągać elementy między aplikacjami. Dotyczy to zarówno komputerów stacjonarnych, jak i tabletów, telefonów i urządzeń składanych w trybie podzielonego ekranu.
Zastanów się, czy użytkownicy będą przeciągać elementy do Twojej aplikacji. Na przykład edytory zdjęć powinny oczekiwać otrzymywania zdjęć, odtwarzacze audio – plików audio, a programy do rysowania – zdjęć.
Aby dodać obsługę przeciągania, przeczytaj artykuł Włączanie przeciągania i upuszczania oraz post na blogu Android on ChromeOS – Implementing Drag & Drop.
Szczególne uwagi dotyczące ChromeOS
- Pamiętaj, aby poprosić o uprawnienia za pomocą
requestDragAndDropPermissions(), aby uzyskać dostęp do elementów przeciągniętych z zewnątrz aplikacji. Aby można było przeciągnąć element do innych aplikacji, musi on mieć flagę
View.DRAG_FLAG_GLOBAL.
Zaawansowana obsługa wskaźnika
Aplikacje, które zaawansowanie obsługują dane wejściowe z myszy i touchpada, powinny implementować modyfikator
View#onGenericMotionEvent() i użyj [MotionEvent.getSource()][], aby
odróżnić SOURCE_MOUSE od SOURCE_TOUCHSCREEN.
Sprawdź obiekt MotionEvent, aby zaimplementować wymagane zachowanie:
- Ruch generuje zdarzenia
ACTION_HOVER_MOVE. - Przyciski generują zdarzenia
ACTION_BUTTON_PRESSiACTION_BUTTON_RELEASE. Możesz też sprawdzić bieżący stan wszystkich przycisków myszy i trackpada za pomocągetButtonState(). - Przewijanie kółkiem myszy generuje zdarzenia
ACTION_SCROLL.
Kontrolery do gier
Niektóre urządzenia z Androidem i dużym ekranem obsługują do 4 kontrolerów do gier. Do obsługi kontrolerów do gier używaj standardowych interfejsów API kontrolerów do gier na Androida (patrz Obsługa kontrolerów do gier).
Przyciski kontrolera do gier są mapowane na typowe wartości zgodnie z typowym mapowaniem. Nie wszyscy producenci kontrolerów do gier stosują jednak te same konwencje mapowania. Możesz znacznie poprawić wygodę użytkowników, jeśli pozwolisz im wybierać różne popularne mapowania kontrolerów. Więcej informacji znajdziesz w artykule Przetwarzanie naciśnięć przycisków gamepada.
Tryb tłumaczenia danych wejściowych
ChromeOS domyślnie włącza tryb tłumaczenia danych wejściowych. W przypadku większości aplikacji na Androida ten tryb pomaga aplikacjom działać zgodnie z oczekiwaniami w środowisku komputerowym. Przykłady to automatyczne włączanie przewijania 2 palcami na touchpadzie, przewijania kółkiem myszy i mapowania surowych współrzędnych wyświetlacza na współrzędne okna. Zwykle deweloperzy aplikacji nie muszą samodzielnie implementować żadnego z tych zachowań.
Jeśli aplikacja implementuje niestandardowe zachowanie danych wejściowych, np. definiuje niestandardowe działanie uszczypnięcia 2 palcami na touchpadzie, lub te tłumaczenia danych wejściowych nie zapewniają zdarzeń wejściowych oczekiwanych przez aplikację, możesz wyłączyć tryb tłumaczenia danych wejściowych, dodając ten tag do manifestu Androida:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />