Na urządzeniach z dużym ekranem użytkownicy często korzystają z aplikacji za pomocą klawiatury, myszy, trackpada, rysika lub pada do gier. Aby umożliwić aplikacji akceptowanie danych wejściowych z urządzeń zewnętrznych:
- Przetestuj podstawową obsługę klawiatury, np. Ctrl+Z, aby cofnąć, Ctrl+C, aby skopiować, i Ctrl+S, aby zapisać. Listę domyślnych skrótów klawiszowych znajdziesz w artykule Obsługa działań klawiatury.
- Przetestuj zaawansowaną obsługę klawiatury, np. nawigację za pomocą klawiszy Tab i strzałek, potwierdzanie wpisywania tekstu klawiszem Enter oraz odtwarzanie i wstrzymywanie multimediów za pomocą spacji w aplikacjach do multimediów.
- Przetestuj podstawowe interakcje za pomocą myszy, w tym kliknięcie prawym przyciskiem myszy, aby otworzyć menu kontekstowe, zmiany ikon po najechaniu kursorem oraz zdarzenia przewijania kółkiem myszy lub trackpadem w przypadku komponentów niestandardowych.
- Przetestuj urządzenia wejściowe przeznaczone do konkretnych aplikacji, takie jak rysik, kontrolery do gier i kontrolery MIDI do aplikacji muzycznych.
- Rozważ zaawansowaną obsługę danych wejściowych, która może wyróżnić aplikację w środowiskach komputerowych, np. touchpad jako crossfader w aplikacjach dla DJ-ów, przechwytywanie myszy w grach i skróty klawiszowe dla użytkowników, którzy wolą korzystać z klawiatury.
Klawiatura
Sposób, w jaki aplikacja reaguje na dane wprowadzane za pomocą klawiatury, wpływa na wrażenia użytkownika na dużym ekranie. Istnieją 3 rodzaje wprowadzania danych za pomocą klawiatury: nawigacja, klawisze i skróty.
Nawigacja
Nawigacja za pomocą klawiatury jest rzadko implementowana w aplikacjach przeznaczonych na urządzenia dotykowe, 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 dla użytkowników z potrzebami związanymi z ułatwieniami dostępu.
W przypadku wielu aplikacji nawigacja za pomocą klawiszy strzałek i klawisza Tab jest obsługiwana automatycznie przez platformę Androida. Na przykład element Button domyślnie może być zaznaczony, a nawigacja za pomocą klawiatury powinna działać bez dodatkowego kodu. Aby włączyć nawigację za pomocą klawiatury w widokach, których domyślnie nie można zaznaczyć, oznacz je jako możliwe do zaznaczenia. Możesz to zrobić programowo lub w pliku 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 sekcji Obsługa zaznaczenia.
Gdy zaznaczenie jest włączone, platforma Androida 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 dalszych prac programistycznych. 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, używając tylko klawiatury. Często używane elementy powinny być dostępne bez użycia myszy lub dotykowego wprowadzania danych.
Pamiętaj, że obsługa klawiatury może być niezbędna dla użytkowników z potrzebami związanymi z ułatwieniami dostępu.
Kombinacje klawiszy
W przypadku wprowadzania tekstu, które byłoby obsługiwane przez ekranową klawiaturę wirtualną (IME), np. w przypadku
EditText
, aplikacje powinny działać zgodnie z oczekiwaniami na urządzeniach z dużym ekranem bez konieczności wykonywania dodatkowych prac programistycznych. W przypadku naciśnięć klawiszy, których platforma nie może przewidzieć, aplikacje muszą same obsługiwać zachowanie. Dotyczy to zwłaszcza aplikacji
z widokami niestandardowymi.
Przykłady to aplikacje do obsługi czatu, które używają klawisza Enter do wysyłania wiadomości, aplikacje do multimediów, które rozpoczynają i zatrzymują odtwarzanie za pomocą spacji, oraz gry, w których ruch kontroluje się za pomocą klawiszy W, A, S i D.
Większość aplikacji zastępuje wywołanie zwrotne onKeyUp() i dodaje oczekiwane działanie 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. Dzięki wywołaniu zwrotnemu aplikacje nie muszą przetwarzać wielu zdarzeń onKeyDown, gdy klawisz jest przytrzymywany lub powoli zwalniany. 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ń na klawiaturze.
Skróty
Podczas korzystania z klawiatury sprzętowej oczekiwane są typowe skróty klawiszowe, które zawierają klawisze Ctrl, Alt, Shift i Meta. Jeśli aplikacja nie obsługuje skrótów, może to być frustrujące dla użytkowników. Zaawansowani użytkownicy doceniają też skróty do często używanych zadań w aplikacji. Skróty ułatwiają korzystanie z aplikacji i odróżniają ją od aplikacji, które nie mają skrótów.
Niektóre typowe skróty to Ctrl+S (zapisz), Ctrl+Z (cofnij) i Ctrl+Shift+Z (ponów). Listę domyślnych skrótów znajdziesz w artykule o obsłudze działań klawiatury.
Skróty można włączyć, implementując dispatchKeyShortcutEvent(), aby przechwytywać wszystkie kombinacje klawiszy (Alt, Ctrl, Shift i Meta) dla danego kodu klawisza.
Aby sprawdzić konkretny 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 obsługi innych naciśnięć klawiszy (takich jak onKeyUp() i onKeyDown()) domyślnie akceptuje klawisze modyfikujące bez konieczności ręcznego implementowania sprawdzania klawiszy modyfikujących w każdym przypadku. Zezwolenie na wszystkie kombinacje 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ż jednak zaimplementować skróty w onKeyUp(), sprawdzając KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed() lub KeyEvent.isAltPressed(). Może to być łatwiejsze w utrzymaniu, jeśli zmodyfikowane działanie klawisza jest bardziej zmianą działania aplikacji niż skrótem. Na przykład w grach, w których 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ż Pomoc dotycząca 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()raportuje nacisk fizyczny wywierany na rysik (jeśli jest obsługiwany)MotionEvent#getAxisValue()zMotionEvent.AXIS_TILTiMotionEvent.AXIS_ORIENTATIONpodają fizyczne nachylenie i orientację rysika (jeśli jest obsługiwany).
Punkty historyczne
Android grupuje zdarzenia wejściowe i dostarcza je raz na klatkę. Rysik może zgłaszać zdarzenia ze znacznie 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()
Ignorowanie dotknięć dłonią
Gdy użytkownicy rysują, piszą lub korzystają z aplikacji za pomocą rysika, czasami dotykają ekranu dłonią. Zdarzenie dotknięcia (ustawione na ACTION_DOWN lub ACTION_POINTER_DOWN) może zostać zgłoszone aplikacji, zanim system rozpozna i zignoruje przypadkowe dotknięcie dłonią.
Android anuluje zdarzenia dotknięcia dłonią, wysyłając MotionEvent. Jeśli aplikacja otrzyma ACTION_CANCEL, anuluj gest. Jeśli aplikacja otrzymuje ACTION_POINTER_UP, sprawdź, czy ustawiono FLAG_CANCELED. Jeśli tak, anuluj gest.
Nie sprawdzaj tylko FLAG_CANCELED. Na Androidzie 13 (API na poziomie 33) i nowszym system ustawia FLAG_CANCELED dla zdarzeń ACTION_CANCEL, ale nie ustawia flagi na starszych wersjach Androida.
Android 12
Na Androidzie 12 (poziom interfejsu API 32) i starszych wykrywanie odrzucania dłoni jest możliwe tylko w przypadku zdarzeń dotknięcia jednym palcem. Jeśli jedynym wskaźnikiem jest dotknięcie dłonią, system anuluje zdarzenie, ustawiając ACTION_CANCEL w obiekcie zdarzenia ruchu. Jeśli inne wskaźniki są opuszczone, system ustawia wartość ACTION_POINTER_UP, która nie wystarcza do wykrywania odrzucenia dłoni.
Android 13
Na Androidzie 13 (API na poziomie 33) i nowszych, jeśli dotknięcie 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ą w dół, system ustawia ACTION_POINTER_UP i FLAG_CANCELED.
Za każdym razem, gdy aplikacja otrzyma zdarzenie ruchu z ACTION_POINTER_UP, sprawdź, czy występuje FLAG_CANCELED, aby określić, czy zdarzenie wskazuje na odrzucenie dotknięcia dłonią (lub inne anulowanie zdarzenia).
aplikacje do robienia notatek,
ChromeOS ma specjalną intencję, która wyświetla użytkownikom zarejestrowane aplikacje do robienia notatek. Aby zarejestrować aplikację jako aplikację do robienia notatek, dodaj do pliku 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 zostanie zarejestrowana w systemie, użytkownik może wybrać ją jako domyślną aplikację do robienia notatek. Gdy użytkownik chce utworzyć nową notatkę, aplikacja powinna utworzyć pustą notatkę gotową do wprowadzania danych rysikiem. Gdy użytkownik chce dodać adnotację 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 tła, i przejść do trybu, w którym użytkownik może rysować na ekranie za pomocą rysika.
Testowanie intencji robienia notatek bez rysika
Aby sprawdzić, czy aplikacja prawidłowo reaguje na intencje robienia notatek bez aktywnego rysika, użyj tej metody, aby wyświetlić opcje robienia notatek w ChromeOS:
- Przełączanie na tryb dewelopera i włączanie możliwości zapisu 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-palettew nowym wierszu 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 powinno się teraz pojawić menu rysika:
- Kliknij przycisk rysika na półce i wybierz Nowa notatka. Powinna otworzyć się pusta notatka z rysunkiem.
- Zrób zrzut ekranu. Na półce wybierz przycisk rysika > Zrób zrzut ekranu lub pobierz obraz. W powiadomieniu powinna być opcja Dodaj adnotację do obrazu. Powinno to uruchomić aplikację z obrazem gotowym do dodania adnotacji.
Obsługa myszy i touchpada
Większość aplikacji musi obsługiwać tylko 3 zdarzenia związane z dużymi ekranami: kliknięcie prawym przyciskiem myszy, najechanie kursorem oraz przeciągnięcie i upuszczenie.
Kliknięcie prawym przyciskiem
Wszelkie działania, które powodują wyświetlenie menu kontekstowego w aplikacji, np. naciśnięcie i przytrzymanie elementu listy, powinny też reagować na zdarzenia kliknięcia prawym przyciskiem myszy.
Aby obsługiwać zdarzenia kliknięcia prawym przyciskiem, 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
Możesz sprawić, że układy aplikacji będą wyglądać na dopracowane i łatwiejsze w użyciu, dzięki obsłudze zdarzeń najechania kursorem. Dotyczy to zwłaszcza niestandardowych komponentów wyświetlenia:
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:
- informowanie użytkowników, czy element ma interaktywne zachowanie, 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 siatce, gdy wskaźnik znajduje się nad nimi;
Przeciągnij i upuść
W środowisku z wieloma oknami użytkownicy oczekują możliwości przeciągania i upuszczania elementów między aplikacjami. Dotyczy to zarówno komputerów, 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 aplikacji. Na przykład edytory zdjęć powinny otrzymywać zdjęcia, odtwarzacze audio – pliki audio, a programy do rysowania – zdjęcia.
Aby dodać obsługę przeciągania i upuszczania, zapoznaj się z tymi artykułami: Włączanie przeciągania i upuszczania oraz z postem na blogu Android na ChromeOS – wdrażanie przeciągania i upuszczania.
Uwagi szczególne dotyczące ChromeOS
- Pamiętaj, aby poprosić o uprawnienia za pomocą
requestDragAndDropPermissions(), aby uzyskać dostęp do elementów przeciągniętych spoza 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 działanie:
- 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, używającgetButtonState(). - Przewijanie kółkiem myszy generuje zdarzenia
ACTION_SCROLL.
kontrolery do gier,
Niektóre urządzenia z Androidem z dużym ekranem obsługują maksymalnie 4 kontrolery 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ć wrażenia 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 na padzie do gier.
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 im działać zgodnie z oczekiwaniami w środowisku komputera. Przykłady obejmują automatyczne włączanie przewijania dwoma palcami na touchpadzie, przewijanie kółkiem myszy i mapowanie nieprzetworzonych współrzędnych wyświetlacza na współrzędne okna. Zazwyczaj deweloperzy aplikacji nie muszą samodzielnie implementować żadnego z tych zachowań.
Jeśli aplikacja implementuje niestandardowe zachowanie wejściowe, np. definiuje niestandardowe działanie uszczypnięcia na touchpadzie dwoma palcami, lub jeśli te translacje wejściowe nie zapewniają zdarzeń wejściowych oczekiwanych przez aplikację, możesz wyłączyć tryb tłumaczenia wejściowego, dodając do pliku manifestu Androida ten tag:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />