Na urządzeniach z dużym ekranem użytkownicy często korzystają z aplikacji za pomocą klawiatury, myszy, trackpada, rysika lub kontrolera. Aby umożliwić aplikacji przyjmowanie danych z zewnętrznych urządzeń:
- Sprawdź podstawowe funkcje obsługi klawiatury, takie jak Ctrl+Z, aby cofnąć, Ctrl+C, aby kopiować, i Ctrl+S, aby zapisać. Aby zobaczyć listę domyślnych skrótów klawiszowych, przeczytaj artykuł Obsługa działań na klawiaturze.
- Sprawdź zaawansowane funkcje klawiatury, na przykład Tab i klawisze strzałek do nawigacji po klawiaturze, Enter do potwierdzenia wpisywania tekstu oraz spacja do odtwarzania i wstrzymywania w aplikacjach multimedialnych.
- Sprawdź podstawowe interakcje z myszą, w tym kliknięcie prawym przyciskiem myszy, aby otworzyć menu kontekstowe, zmiany ikony podczas najechania kursorem i zdarzenia przewijania kółka myszy lub gestu nawigacyjnego na elementach niestandardowych.
- Testuj urządzenia wejściowe związane z konkretną aplikacją, takie jak rysiki, kontrolery do gier i kontrolery MIDI do aplikacji muzycznych.
- Rozważ zaimplementowanie zaawansowanego wsparcia dla danych wejściowych, które wyróżni Twoją aplikację na komputerach. Może to być np. obsługa touchpada jako cross-fadera w aplikacjach do miksowania, przechwytywanie myszy w przypadku gier czy skróty klawiszowe dla użytkowników korzystających z klawiatury.
Klawiatura
Sposób, w jaki aplikacja reaguje na dane wejściowe z klawiatury, wpływa na wrażenia użytkownika na dużym ekranie. Istnieją 3 rodzaje danych wprowadzanych za pomocą klawiatury: nawigacja, klawisze i skróty.
Nawigacja
Nawigacja za pomocą klawiatury jest rzadko stosowana w aplikacjach dotykowych, ale użytkownicy oczekują jej, gdy korzystają z aplikacji i mają dostęp do klawiatury. Nawigacja za pomocą klawiatury może być niezbędna na telefonach, tabletach, składanych urządzeniach i komputerach stacjonarnych dla użytkowników, którzy potrzebują ułatwień 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 niektóre komponenty są domyślnie możliwe do skupienia, np. Button
lub komponent z modyfikatorem clickable
. Nawigacja za pomocą klawiatury powinna działać bez dodatkowego kodu. Aby umożliwić nawigację za pomocą klawiatury w przypadku niestandardowych komponentów, które domyślnie nie są możliwe do zaznaczenia, dodaj modyfikator focusable
:
var color by remember { mutableStateOf(Green) } Box( Modifier .background(color) .onFocusChanged { color = if (it.isFocused) Blue else Green } .focusable() ) { Text("Focusable 1") }
Więcej informacji znajdziesz w artykule Ustawianie komponentu w stanie fokusowania.
Gdy funkcja focus jest włączona, platforma Android tworzy mapowanie nawigacyjne wszystkich elementów, na których można się skupić, na podstawie ich pozycji. Wszystko działa zwykle zgodnie z oczekiwaniami i nie wymaga dalszego rozwoju.
Jednak Compose nie zawsze określa prawidłowe następne miejsce w przypadku nawigacji za pomocą kart w przypadku złożonych komponentów, takich jak karty czy listy, gdy jeden z tych komponentów jest elementem poziomym, który nie jest w pełni widoczny.
Aby kontrolować zachowanie fokusa, dodaj modyfikator focusGroup
do nadrzędnego komponentu kolekcji komponentów. Wyróżnienie przenosi się na grupę, a potem przez grupę, zanim przejdzie do następnego elementu, na którym można ustawić wyróżnienie, na przykład:
Row {
Column(Modifier.focusGroup()) {
Button({}) { Text("Row1 Col1") }
Button({}) { Text("Row2 Col1") }
Button({}) { Text("Row3 Col1") }
}
Column(Modifier.focusGroup()) {
Button({}) { Text("Row1 Col2") }
Button({}) { Text("Row2 Col2") }
Button({}) { Text("Row3 Col2") }
}
}
Więcej informacji znajdziesz w artykule Zapewnienie spójnej nawigacji w przypadku grup fokusowych.
Sprawdź dostęp do każdego elementu interfejsu aplikacji tylko za pomocą klawiatury. Elementy używane często powinny być dostępne bez myszy lub ekranu dotykowego.
Pamiętaj, że obsługa klawiatury może być niezbędna dla użytkowników z potrzebami w zakresie ułatwień dostępu.
Kombinacje klawiszy
W przypadku wprowadzania tekstu, które jest obsługiwane przez klawiaturę ekranową (IME), na przykład:
TextField
aplikacje powinny działać zgodnie z oczekiwaniami na urządzeniach z dużym ekranem bez konieczności dodatkowej pracy programistów. W przypadku naciśnięć klawiszy, których nie można przewidzieć w ramach frameworku, aplikacje muszą samodzielnie obsługiwać takie działanie. Dotyczy to w szczególności aplikacji z widokami niestandardowymi.
Przykładami są aplikacje do czatu, które używają klawisza Enter do wysyłania wiadomości, aplikacje multimedialne, które uruchamiają i zawieszają odtwarzanie za pomocą klawisza spacji, oraz gry, w których ruchem kieruje się za pomocą klawiszy w, a, s i d.
Poszczególne naciśnięcia klawiszy możesz obsługiwać za pomocą modyfikatora onKeyEvent
, który przyjmuje funkcję lambda wywoływaną, gdy zmodyfikowany komponent otrzyma kluczowe zdarzenie.
Właściwość KeyEvent#type
umożliwia określenie, czy zdarzenie to naciśnięcie klawisza (KeyDown
) czy zwolnienie klawisza (KeyUp
):
Box(
modifier = Modifier.focusable().onKeyEvent {
if(
it.type == KeyEventType.KeyUp &&
it.key == Key.S
) {
doSomething()
true
} else {
false
}
}
) {
Text("Press S key")
}
Możesz też zastąpić wywołanie zwrotne onKeyUp()
i dodać oczekiwane działanie dla każdego otrzymanego klucza kodu:
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) } }
Gdy klucz zostanie zwolniony, nastąpi zdarzenie onKeyUp
. Dzięki wywołaniu zwrotnemu aplikacje nie muszą przetwarzać wielu zdarzeń onKeyDown
, jeśli przycisk jest przytrzymywany lub zwalniany powoli. Gry i aplikacje, które muszą wykryć moment naciśnięcia klawisza lub czy użytkownik przytrzymuje przycisk, mogą nasłuchiwać zdarzenia onKeyDown
i same obsługiwać powtarzające się zdarzenia onKeyDown
.
Więcej informacji znajdziesz w artykule Obsługa działań związanych z klawiaturą.
Skróty
Podczas korzystania z klawiatury sprzętowej należy używać zwykłych skrótów klawiszowych, które obejmują klawisze Ctrl, Alt, Shift i Meta. Jeśli aplikacja nie obsługuje skrótów, może to być dla użytkowników frustrujące. Zaawansowani użytkownicy doceniają też skróty do często używanych zadań w poszczególnych aplikacjach. Skróty ułatwiają korzystanie z aplikacji i odróżniają ją od aplikacji, które nie mają skrótów.
Do najpopularniejszych skrótów należą Ctrl+S (zapisz), Ctrl+Z (cofnij) i Ctrl+Shift+Z (ponów). Listę domyślnych skrótów znajdziesz w artykule Obsługa działań na klawiaturze.
Obiekt KeyEvent
ma te atrybuty, które wskazują, czy wciśnięto klawisze modyfikujące:
Przykład:
Box(
Modifier.onKeyEvent {
if (it.isAltPressed && it.key == Key.A) {
println("Alt + A is pressed")
true
} else {
false
}
}
.focusable()
)
Więcej informacji znajdziesz w tych dokumentach:
Rysik
Wiele urządzeń z dużym ekranem jest wyposażonych w rysik. Aplikacje na Androida obsługują rysiki jako dane z ekranu dotykowego. Niektóre urządzenia mogą mieć też tablet do rysowania z podłączeniem USB lub Bluetooth, np. Wacom Intuos. Aplikacje na Androida mogą odbierać dane z Bluetooth, ale nie z USB.
Aby uzyskać dostęp do obiektów rysika MotionEvent
, dodaj modyfikator pointerInteropFilter
do powierzchni do rysowania. Zaimplementuj klasę ViewModel
z metodą, która przetwarza zdarzenia związane z ruchu. Przekaż tę metodę jako lambda onTouchEvent
modyfikatora pointerInteropFilter
:
@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
Canvas(modifier = modifier
.clipToBounds()
.pointerInteropFilter {
viewModel.processMotionEvent(it)
}
) {
// Drawing code here.
}
}
Obiekt MotionEvent
zawiera informacje o zdarzeniu:
MotionEvent#getToolType()
zwracaTOOL_TYPE_FINGER
,TOOL_TYPE_STYLUS
lubTOOL_TYPE_ERASER
w zależności od narzędzia, które nawiązało kontakt z wyświetlaczem.MotionEvent#getPressure()
zwraca informacje o fizycznym nacisku na rysik (jeśli jest obsługiwany).MotionEvent#getAxisValue()
zMotionEvent.AXIS_TILT
iMotionEvent.AXIS_ORIENTATION
zapewniają fizyczne pochylenie i orientację rysika (jeśli jest obsługiwana).
Punkty historyczne
Android grupowanie zdarzeń wejściowych i przesyła je raz na ramkę. Stylus może zgłaszać zdarzenia z znacznie większą częstotliwością niż wyświetlacz. Podczas tworzenia aplikacji do rysowania sprawdź, czy nie doszło do żadnych zdarzeń w ostatnim czasie, korzystając z interfejsów API:getHistorical
MotionEvent#getHistoricalX()
MotionEvent#getHistoricalY()
MotionEvent#getHistoricalPressure()
MotionEvent#getHistoricalAxisValue()
Odrzucenie palmy
Gdy użytkownicy rysują, piszą lub wchodzą w interakcję z aplikacją za pomocą rysika, czasami dotykają ekranu dłonią. Zdarzenie dotyku (ustawione na ACTION_DOWN
lub ACTION_POINTER_DOWN
) może być zgłaszane do aplikacji, zanim system wykryje i ignoruje przypadkowe dotknięcie dłonią.
Android anuluje zdarzenia dotyku dłoni, wysyłając MotionEvent
. Jeśli aplikacja otrzyma sygnał ACTION_CANCEL
, anuluj gest. Jeśli Twoja aplikacja otrzymuje odpowiedź ACTION_POINTER_UP
, sprawdź, czy ustawiona jest wartość FLAG_CANCELED
. Jeśli tak, anuluj gest.
Nie sprawdzaj tylko FLAG_CANCELED
. W przypadku Androida 13 (poziom API 33) lub nowszego system ustawia flagę FLAG_CANCELED
dla zdarzeń ACTION_CANCEL
, ale nie ustawia jej w starszych wersjach Androida.
Android 12
W przypadku Androida 12 (poziom interfejsu API 32) lub starszego wykrywanie odrzucenia dłoni jest możliwe tylko w przypadku zdarzeń dotykowych z pojedynczym wskaźnikiem. Jeśli dotykowe polecenie palcem jest jedynym wskaźnikiem, system anuluje zdarzenie, ustawiając wartość ACTION_CANCEL
w obiekcie zdarzenia ruchu. Jeśli inne wskaźniki są w pozycji w dół, system ustawia ACTION_POINTER_UP
, co jest niewystarczające do wykrywania odrzucenia dłoni.
Android 13
W Androidzie 13 (poziom API 33) lub nowszym, jeśli dotyk dłoni jest jedynym wskaźnikiem, system anuluje zdarzenie, ustawiając wartości 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
.
Gdy aplikacja otrzyma zdarzenie ruchu z wartością ACTION_POINTER_UP
, sprawdź, czy występuje zdarzenie FLAG_CANCELED
, aby określić, czy odrzucono dłoń (lub inne zdarzenie anulowania).
Aplikacje do notatek
ChromeOS ma specjalny zamiar, który wyświetla zarejestrowane aplikacje do robienia notatek. Aby zarejestrować aplikację jako aplikację do tworzenia 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 ją wybrać jako domyślną aplikację do tworzenia notatek. Gdy użytkownik poprosi o utworzenie nowej notatki, aplikacja powinna utworzyć pustą notatkę gotową do wprowadzania danych za pomocą rysika. 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 identyfikatorem URI content://
. Aplikacja powinna utworzyć notatkę, która używa pierwszego załączonego obrazu jako obrazu tła, i wejść w tryb, w którym użytkownik może rysować na ekranie za pomocą rysika.
Testowanie intencji dotyczących robienia notatek bez rysika
[TBD remove section.]
Aby sprawdzić, czy aplikacja reaguje prawidłowo na intencje dotyczące tworzenia notatek bez aktywnego rysika, wyświetl opcje tworzenia notatek w ChromeOS w ten sposób:
- Przejdź do trybu programisty i zezwól na zapis na urządzeniu
- Aby otworzyć terminal, naciśnij Ctrl+Alt+F2.
- Uruchom polecenie
sudo vi /etc/chrome_dev.conf
. - Naciśnij
i
, aby edytować i dodać--ash-enable-palette
do nowego wiersza na końcu pliku. - Zapisz, naciskając Esc, a następnie wpisując :, w, q i naciskając Enter
- Aby wrócić do zwykłego interfejsu ChromeOS, naciśnij Ctrl+Alt+F1.
- Wyloguj się, a potem zaloguj ponownie.
Na półce powinno teraz pojawić się menu rysika:
- Kliknij przycisk rysika na półce i wybierz Nowa notatka. Powinien otworzyć się pusty notatnik do rysowania.
- Zrób zrzut ekranu. Na półce wybierz przycisk rysika > Zrób zrzut ekranu lub pobierz obraz. W powiadomieniu powinna być opcja Adnotacja obrazu. Powinien się uruchomić obraz w aplikacji z możliwością dodania adnotacji.
Obsługa myszy i touchpada
Większość aplikacji musi obsługiwać tylko 3 duże zdarzenia związane z ekranem: kliknięcie prawym przyciskiem myszy, najechanie kursorem i przeciąganie i upuszczanie.
Kliknięcie prawym przyciskiem
Wszystkie działania, które powodują wyświetlenie menu kontekstowego w aplikacji, np. dotknięcie i przytrzymanie elementu na liście, powinny również reagować na zdarzenia związane z kliknięciem prawym przyciskiem myszy.
Aby obsługiwać zdarzenia kliknięcia prawym przyciskiem myszy, aplikacje powinny zarejestrować:
View.OnContextClickListener
Box(modifier = Modifier.fillMaxSize()) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
val rootView = FrameLayout(context)
val onContextClickListener =
View.OnContextClickListener { view ->
showContextMenu()
true
}
rootView.setOnContextClickListener(onContextClickListener)
rootView
},
)
}
Szczegółowe informacje o tworzeniu menu kontekstowych znajdziesz w artykule Tworzenie menu kontekstowych.
Najechanie
Możesz sprawić, że układy aplikacji będą wyglądać bardziej profesjonalnie i łatwiej się z nich korzystać, obsługując zdarzenia związane z najechaniem kursorem. Dotyczy to szczególnie niestandardowych komponentów:
Oto 2 najczęstsze przykłady:
- Wskazanie użytkownikom, czy element jest interaktywny, np. czy można go kliknąć lub edytować, przez zmianę ikony kursora myszy
- dodawanie wizualnego potwierdzenia do elementów na dużej liście lub siatce po najechaniu na nie kursorem.
Przeciągnij i upuść
W środowisku wielooknowym użytkownicy oczekują, że będą mogli przeciągać i upuszczać elementy między aplikacjami. Dotyczy to komputerów, 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 oczekiwać zdjęć, odtwarzacze dźwięku powinny oczekiwać plików audio, a programy do rysowania powinny oczekiwać zdjęć.
Aby dodać obsługę przeciągania i upuszczania, zapoznaj się z artykułem Przeciąganie i upuszczanie oraz przeczytaj ten post na blogu Android na ChromeOS – implementacja przeciągania i upuszczania.
Specjalne uwagi dotyczące ChromeOS
- Pamiętaj, aby poprosić o dostęp do elementów przeciąganych z zewnątrz aplikacji z urządzenia
requestDragAndDropPermissions()
. Aby można było przeciągać element do innych aplikacji, musi on mieć flagę
View.DRAG_FLAG_GLOBAL
.
Zaawansowane obsługiwanie wskaźnika
Aplikacje, które obsługują zaawansowane funkcje myszy i touchpada, powinny zaimplementować modyfikator
pointerInput
, aby uzyskać PointerEvent
:
@Composable private fun LogPointerEvents(filter: PointerEventType? = null) { var log by remember { mutableStateOf("") } Column { Text(log) Box( Modifier .size(100.dp) .background(Color.Red) .pointerInput(filter) { awaitPointerEventScope { while (true) { val event = awaitPointerEvent() // handle pointer event if (filter == null || event.type == filter) { log = "${event.type}, ${event.changes.first().position}" } } } } ) } }
Sprawdź obiekt PointerEvent
, aby ustalić:
PointerType
: mysz, rysik, ekran dotykowy itp. zPointerEvent#changes
PointerEventType
: działania kursora, takie jak naciśnięcie, przesunięcie, przewijanie i zwolnienie
Kontrolery do gier
Niektóre urządzenia z Androidem o dużym ekranie obsługują do 4 kontrolerów gier. Do obsługi kontrolerów gier używaj standardowych interfejsów API kontrolerów gier na Androida (patrz Obsługa kontrolerów gier).
Przyciski kontrolera są mapowane na wspólne wartości zgodnie ze wspólnym mapowaniem. Nie wszyscy producenci kontrolerów do gier stosują jednak te same konwencje mapowania. Możesz zapewnić użytkownikom znacznie lepsze wrażenia, jeśli zezwolisz im na wybór różnych popularnych mapowań kontrolerów. Więcej informacji znajdziesz w artykule Przetwarzanie naciśnięć przycisków na padzie do gier.
Tryb translacji podczas wprowadzania
ChromeOS domyślnie włącza tryb translacji danych wejściowych. W przypadku większości aplikacji na Androida ten tryb pomaga aplikacjom działać zgodnie z oczekiwaniami w środowisku komputera. Przykłady takich funkcji to automatyczne włączanie przewijania 2 palcami na touchpadzie, przewijanie kółkiem myszy oraz mapowanie surowych współrzędnych wyświetlacza na współrzędne okna. Zazwyczaj deweloperzy aplikacji nie muszą sami wdrażać tych zachowań.
Jeśli aplikacja implementuje niestandardowe działanie wprowadzania danych, np. definiuje niestandardowe działanie ściśnięcia dwoma palcami na touchpadzie, lub jeśli te tłumaczenia wprowadzania danych nie zapewniają zdarzeń wprowadzania danych oczekiwanych przez aplikację, możesz wyłączyć tryb tłumaczenia wprowadzania danych, dodając do pliku manifestu Androida ten tag:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />