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 niektóre elementy kompozycyjne, takie jak Button lub element kompozycyjny z modyfikatorem clickable, domyślnie mogą być zaznaczane. Nawigacja za pomocą klawiatury powinna działać bez dodatkowego kodu. Aby włączyć nawigację za pomocą klawiatury w przypadku niestandardowych funkcji kompozycyjnych, których domyślnie nie można zaznaczyć, 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 sekcji Ustawianie elementu kompozycyjnego jako zaznaczalnego.
Gdy zaznaczenie jest włączone, platforma Androida tworzy mapowanie nawigacyjne dla wszystkich komponentów, które można zaznaczyć, na podstawie ich pozycji. Zwykle działa to zgodnie z oczekiwaniami i nie wymaga dalszych działań.
Compose nie zawsze jednak określa prawidłowy następny element do nawigacji za pomocą tabulatora w przypadku złożonych elementów kompozycyjnych, takich jak karty i listy, np. gdy jeden z elementów kompozycyjnych jest przewijany w poziomie i nie jest w pełni widoczny.
Aby kontrolować zachowanie fokusu, dodaj modyfikator focusGroup do funkcji kompozycyjnej nadrzędnej w kolekcji funkcji kompozycyjnych. Fokus przenosi się na grupę, a następnie przechodzi przez nią, zanim przejdzie do następnego elementu, na którym można ustawić fokus, 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 Zapewnianie spójnej nawigacji za pomocą grup fokusowych.
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
TextField
, 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.
Możesz obsługiwać poszczególne naciśnięcia klawiszy za pomocą modyfikatora onKeyEvent, który akceptuje funkcję lambda wywoływaną, gdy zmodyfikowany komponent otrzymuje zdarzenie klawisza.
Właściwość KeyEvent#type pozwala określić, czy zdarzenie jest naciśnięciem (KeyDown) czy zwolnieniem (KeyUp) klawisza:
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 kodu klawisza:
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)
}
}
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.
Obiekt KeyEvent ma te atrybuty, które wskazują, czy klawisze modyfikujące są naciśnięte:
Przykład:
Box(
Modifier.onKeyEvent {
if (it.isAltPressed && it.key == Key.A) {
println("Alt + A is pressed")
true
} else {
false
}
}
.focusable()
)
Więcej informacji:
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.
Aby uzyskać dostęp do obiektów rysika MotionEvent, dodaj modyfikator pointerInteropFilter do powierzchni rysowania. Zaimplementuj klasę ViewModel z metodą, która przetwarza zdarzenia ruchu. Przekaż metodę jako funkcję 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_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:
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 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:
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: Przeciąganie i upuszczanie 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
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 określić:
PointerType: mysz, rysik, dotyk itp. zPointerEvent#changesPointerEventType: działania wskaźnika, takie jak naciśnięcie, przesunięcie, przewinięcie i zwolnienie.
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" />