Na urządzeniach z ChromeOS wielu użytkowników korzysta z aplikacji za pomocą klawiatury, myszy, trackpada, rysika lub gamepada. Chociaż te urządzenia wejściowe są również używane na telefonach z Androidem, nie są tak popularne i często są pomijane przez deweloperów.
Deweloperzy, którzy chcą, aby ich aplikacja dobrze działała na urządzeniach z ChromeOS i innych urządzeniach z Androidem z dużym ekranem, powinni zastosować te optymalizacje:
- Dodaj i przetestuj podstawową obsługę klawiatury, np. nawigację za pomocą klawiszy strzałek i Tab, klawisz Enter do potwierdzania wpisywania tekstu oraz spację do odtwarzania i wstrzymywania w aplikacjach multimedialnych.
-
W odpowiednich miejscach dodaj standardowe skróty klawiszowe, np.
ctrl+zdla cofania ictrl+sdla zapisywania. - Sprawdź podstawowe interakcje myszy, takie jak kliknięcie prawym przyciskiem w celu wyświetlenia menu kontekstowego, zmiany ikon po najechaniu kursorem oraz zdarzenia przewijania kółkiem myszy lub trackpada w widokach niestandardowych.
- Testuj urządzenia wejściowe przeznaczone do konkretnych aplikacji, takie jak rysiki do aplikacji do rysowania, 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: touchpad jako crossfader w aplikacjach dla DJ-ów, przechwytywanie myszy w grach i rozbudowane skróty klawiszowe dla zaawansowanych użytkowników.
Klawiatura
Sposób, w jaki aplikacja reaguje na wprowadzanie danych z klawiatury, wpływa na jakość korzystania z niej na komputerze. Istnieją 3 rodzaje wprowadzania danych z klawiatury: nawigacja, naciśnięcia klawiszy i skróty.
Nawigacja
Nawigacja za pomocą klawiatury jest rzadko implementowana w aplikacjach przeznaczonych głównie do obsługi dotykowej, ale użytkownicy oczekują jej, gdy korzystają z aplikacji z klawiaturą. Może być też niezbędna dla użytkowników z niepełnosprawnościami korzystających z telefonów i komputerów.
W przypadku wielu aplikacji wystarczy nawigacja za pomocą klawiszy strzałek i klawisza Tab, która jest w większości obsługiwana automatycznie przez platformę Androida. Na przykład widok Button jest domyślnie dostępny za pomocą klawiatury i nawigacja za jej pomocą powinna działać bez dodatkowego kodu. Aby włączyć nawigację za pomocą klawiatury w przypadku widoków, których nie można domyślnie zaznaczyć, programiści powinni oznaczyć je jako możliwe do zaznaczenia. Możesz to zrobić programowo lub w formacie XML, jak opisano poniżej. Więcej informacji znajdziesz w dokumentacji Focus Handling (Obsługa ostrości).
yourView.isFocusable = true
Możesz też ustawić atrybut focusable w pliku układu:
android:focusable="true"
Po włączeniu ostrości platforma Androida utworzy mapę nawigacyjną dla wszystkich widoków, na których można ustawić ostrość, na podstawie ich pozycji. Zwykle działa to zgodnie z oczekiwaniami i nie wymaga dodatkowej pracy. Jeśli domyślne mapowanie nie odpowiada potrzebom aplikacji, można je zastąpić w ten sposób:
// 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
Przed każdą publikacją warto przetestować wszystkie funkcje aplikacji, korzystając tylko z klawiatury. Najczęstsze działania powinny być dostępne bez użycia myszy lub panelu dotykowego.
Uwaga: 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 byłoby obsługiwane przez klawiaturę ekranową (IME), np. EditText, aplikacje powinny działać w ChromeOS zgodnie z oczekiwaniami bez dodatkowej pracy dewelopera. W przypadku naciśnięć klawiszy, których platforma nie może przewidzieć, aplikacje muszą samodzielnie obsługiwać to 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 uruchamiają 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 zdarzenie onKeyUp i dodaje oczekiwane działanie dla każdego otrzymanego kodu klawisza, jak poniżej.
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) } }
Użycie onKeyUp zapobiega otrzymywaniu przez aplikacje wielu zdarzeń, jeśli klawisz jest przytrzymywany lub zwalniany powoli. Gry i aplikacje, w których użytkownicy muszą przytrzymywać klawisze, mogą wyszukiwać zdarzenie onKeyDown.
W zależności od potrzeb aplikacji zastąpienie onKeyUp w całym działaniu zwykle zapewnia wymagane zachowanie. W razie potrzeby do konkretnego widoku można dodać onKeyListener. Na przykład aplikacja może nasłuchiwać naciśnięcia klawisza Enter tylko w określonym polu EditText, a nie w aktywności, aby zaimplementować funkcję wysyłania tylko wtedy, gdy użytkownik pisze w oknie czatu.
Gdy dodajesz obsługę klawiatury, postępuj zgodnie z dokumentacją Androida dotyczącą obsługi klawiatury.
Skróty
W środowiskach komputerowych oczekiwane są typowe skróty oparte na klawiszach ctrl, alt i shift. Jeśli aplikacja nie implementuje tych funkcji, użytkownicy mogą być sfrustrowani i mieć wrażenie, że aplikacja nie działa prawidłowo. 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 ich nie mają.
Do najpopularniejszych skrótów należą zapisywanie (ctrl+s), cofanie (ctrl+z) i ponawianie (ctrl+shift+z). Przykłady bardziej zaawansowanych skrótów znajdziesz na liście skrótów klawiszowych w VLC Media Player.
Skróty można implementować za pomocą dispatchKeyShortcutEvent. Przechwytuje to wszystkie kombinacje klawiszy meta (alt, ctrl i shift) dla danego kodu klawisza. Aby sprawdzić konkretny metaklucz, użyj KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed(), KeyEvent.isAltPressed() lub KeyEvent.hasModifiers().
Oddzielenie kodu skrótu od innych metod obsługi naciśnięć klawiszy (np. onKeyUp lub onKeyDown) może ułatwić konserwację kodu i zachować domyślną akceptację klawiszy meta bez konieczności ręcznego implementowania sprawdzania klawiszy meta w każdym przypadku. Zezwolenie na wszystkie kombinacje klawiszy meta może być też wygodniejsze dla użytkowników przyzwyczajonych do różnych układów klawiatury i systemów operacyjnych.
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) } } }
Skróty możesz też wdrożyć w onKeyUp, sprawdzając w ten sam sposób KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed() lub KeyEvent.isAltPressed(). Może to być łatwiejsze w utrzymaniu, jeśli meta-zachowanie jest bardziej modyfikacją zachowania aplikacji niż skrótem. Na przykład, gdy w oznacza „idź do przodu”, a shift+w oznacza „biegnij do przodu”.
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 } } else -> super.onKeyUp(keyCode, event) } }
Obsługa myszy i touchpada
ChromeOS automatycznie obsługuje większość zdarzeń myszy i trackpada, aby działały jak zdarzenia dotknięcia na telefonie z Androidem. Obejmuje to przewijanie za pomocą 2 palców na touchpadzie lub kółka myszy. Większość aplikacji musi obsługiwać tylko 3 zdarzenia związane z komputerami: kliknięcie prawym przyciskiem myszy, najechanie kursorem i przeciąganie i upuszczanie.
Kliknięcie prawym przyciskiem
Wszelkie działania, które powodują wyświetlenie menu kontekstowego w aplikacji, np. długie naciśnięcie elementu listy, powinny też reagować na kliknięcia prawym przyciskiem myszy. Aby obsługiwać zdarzenia kliknięcia prawym przyciskiem myszy, aplikacje powinny rejestrować View.OnContextClickListener. Szczegółowe informacje o tworzeniu menu kontekstowego znajdziesz w dokumentacji menu kontekstowego na Androida.
yourView.setOnContextClickListener { view -> showContextMenu() true }
Uwaga: wszystkie widoki zarejestrowane w menu kontekstowym za pomocą Activity.registerForContextMenu() powinny automatycznie działać zarówno w przypadku długiego naciśnięcia, jak i kliknięcia prawym przyciskiem myszy bez konieczności rejestrowania odbiornika kliknięcia kontekstowego.
Najechanie
Obsługa zdarzeń najechania kursorem pozwala deweloperom dopracować układ aplikacji i ułatwić korzystanie z niej. Dotyczy to zwłaszcza widoków niestandardowych. Oto 2 najczęstsze przykłady:
- informowanie użytkowników o tym, czy element jest interaktywny, np. czy można go kliknąć lub edytować, poprzez 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.
// 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(applicationContext, PointerIcon.TYPE_HAND) false // listener did not consume the event. }
Przeciąganie i upuszczanie
W środowisku z wieloma oknami użytkownicy oczekują możliwości przeciągania i upuszczania elementów między aplikacjami. Dotyczy to zarówno urządzeń z ChromeOS, jak i tabletów, telefonów i urządzeń składanych w trybie podzielonego ekranu.
Deweloperzy powinni zastanowić się, czy użytkownicy będą przeciągać elementy do aplikacji. Przykłady: edytory zdjęć powinny otrzymywać zdjęcia, odtwarzacze audio powinny otrzymywać pliki audio, a programy do rysowania powinny otrzymywać zdjęcia.
Aby dodać obsługę przeciągania i upuszczania, postępuj zgodnie z dokumentacją przeciągania i upuszczania na Androidzie i zapoznaj się z tym postem na blogu ChromeOS.
Uwagi specjalne dotyczące ChromeOS
-
Aby obsługiwać pliki z aplikacji Pliki w ChromeOS, poszukaj typu MIME
application/x-arc-uri-list -
Pamiętaj, aby poprosić o pozwolenie za pomocą funkcji
requestDragAndDropPermissionsna 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.
Obsługa wielokrotnego wyboru
Jeśli Twoja aplikacja zawiera listy lub siatki, zastanów się, czy użytkownicy skorzystają na możliwości zaznaczania wielu elementów. Wysokiej jakości wybór wielokrotny za pomocą myszy i trackpada często obejmuje funkcje takie jak wybór zakresu. Samodzielne wdrożenie tego rozwiązania może być trudne, ale możesz skorzystać z biblioteki wyboru Recyclerview.
Zaawansowana obsługa wskaźnika
Aplikacje, które zaawansowanie obsługują dane wejściowe z myszy i touchpada, powinny postępować zgodnie z dokumentacją Androida dotyczącą View.onGenericMotionEvent() i używać MotionEvent.getSource() do rozróżniania SOURCE_MOUSE i SOURCE_TOUCHSCREEN.
Sprawdź MotionEvent, aby wdrożyć wymagane działanie:
-
Ruch generuje
ACTION_HOVER_MOVEzdarzeń -
Przyciski generują zdarzenia
ACTION_BUTTON_PRESSiACTION_BUTTON_RELEASE. Możesz też sprawdzić bieżący stan wszystkich przycisków myszy lub trackpada za pomocągetButtonState(). -
Przewijanie kółkiem myszy generuje zdarzenia
ACTION_SCROLL.
Rysik
Wiele Chromebooków jest wyposażonych w rysik, a aplikacje na Androida traktują go jako wejście dotykowe. Niektóre urządzenia mogą też mieć tablet graficzny USB lub Bluetooth, np. Wacom Intuos. Aplikacje na Androida mogą odbierać dane wejściowe przez Bluetootha, ale nie będą działać z danymi wejściowymi przez USB.
Zdarzenie rysika jest zgłaszane jako zdarzenie ekranu dotykowego za pomocą View.onTouchEvent() lub View.onGenericMotionEvent() i zawiera MotionEvent.getSource() typu SOURCE_STYLUS. MotionEvent będzie też zawierać dodatkowe dane:
-
MotionEvent.getToolType()zwróci wartośćTOOL_TYPE_FINGER,TOOL_TYPE_STYLUSlubTOOL_TYPE_ERASERw zależności od narzędzia, które zetknęło się z powierzchnią. -
MotionEvent.getPressure()– zgłasza fizyczny nacisk wywierany na rysik (jeśli jest obsługiwany). -
MotionEvent.getAxisValue()zMotionEvent.AXIS_TILTiMotionEvent.AXIS_ORIENTATION, które mogą służyć do odczytywania fizycznego nachylenia i orientacji rysika (jeśli są obsługiwane);
Punkty historyczne
Android grupuje zdarzenia wejściowe i przesyła je raz na ramkę. Rysik może zgłaszać zdarzenia z dużo większą częstotliwością niż wyświetlacz. Podczas tworzenia aplikacji do rysowania ważne jest, aby sprawdzać 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 dłoni
ChromeOS próbuje rozpoznać, kiedy dłoń użytkownika spoczywa na ekranie dotykowym. Nie zawsze jest to jednak możliwe. Czasami zdarzenie dotyku może zostać zgłoszone do aplikacji, zanim system operacyjny rozpozna je jako dotyk dłoni. W takim przypadku dotknięcia zostaną anulowane przez zgłoszenie zdarzenia ACTION_CANCEL.
To zdarzenie informuje aplikację, że niektóre dotknięcia są nieprawidłowe i powinna ona cofnąć wszystkie interakcje spowodowane przez te dotknięcia. Na przykład aplikacja do rysowania może tymczasowo rysować nowe linie od razu po ich otrzymaniu, aby zapewnić jak najmniejsze opóźnienie, ale trwale zapisywać je na płótnie dopiero po zakończeniu serii dotknięć. Jeśli w międzyczasie zdarzenia dotyku zostaną anulowane, tymczasowe linie można usunąć.
Uwaga: jednym ze sposobów na ograniczenie niepotrzebnych zdarzeń związanych z dłonią i palcami w aplikacjach do rysowania i pisania jest udostępnienie ustawienia interfejsu, które wyłącza rysowanie za pomocą dotyku i w tym trybie używa do rysowania tylko zdarzeń związanych z rysikiem.
Aplikacje do robienia notatek
ChromeOS ma specjalny zamiar, który wyświetla zarejestrowane aplikacje do robienia notatek. Aby zarejestrować aplikację jako aplikację do robienia notatek, dodaj do manifestu Androida te informacje:
<intent-filter> <action android:name="org.chromium.arc.intent.action.CREATE_NOTE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
Po zarejestrowaniu aplikacji użytkownik może wybrać ją jako domyślną aplikację do robienia notatek. Gdy użytkownik poprosi o utworzenie nowej notatki, aplikacja powinna utworzyć pustą notatkę gotową do wprowadzania tekstu za pomocą rysika. Gdy użytkownik chce dodać adnotację do obrazu (np. zrzutu ekranu lub pobranego obrazu), aplikacja uruchamia się z parametrem ClipData zawierającym co najmniej 1 element z identyfikatorami URI content://. Aplikacja powinna utworzyć notatkę, w której pierwsze załączone zdjęcie będzie obrazem tła, i przejść do trybu, w którym użytkownik może rysować na nim za pomocą rysika.
Testowanie intencji robienia notatek bez rysika
Aby sprawdzić, czy aplikacja prawidłowo reaguje na intencje związane z robieniem notatek bez aktywnego rysika, użyj tej metody wyświetlania opcji robienia notatek:
- Przejdź do trybu programisty i umożliw 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 dodać--ash-enable-palettedo nowego wiersza na końcu pliku. -
Aby zapisać, naciśnij
Esc, a potem wpisz:,w,qi naciśnijEnter. -
Naciśnij
ctrl+alt+f1, aby wrócić do zwykłego interfejsu ChromeOS.
Na półce powinno teraz pojawić się menu 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 wybierz przycisk rysika > Zrób zrzut ekranu lub pobierz obraz. W powiadomieniu powinna być dostępna opcja „Dodaj adnotację do obrazu”. Spowoduje to uruchomienie aplikacji z obrazem gotowym do dodania adnotacji.
Kontrolery do gier
Chromebooki obsługują maksymalnie 4 kontrolery do gier. Deweloperzy powinni używać standardowych interfejsów API kontrolera do gier na Androida.
Przyciski są mapowane na typowe wartości zgodnie z mapowaniem ogólnym. Niestety nie wszyscy producenci kontrolerów do gier stosują te same konwencje mapowania. Jeśli pozwolisz użytkownikom wybierać różne popularne mapowania kontrolera, możesz znacznie poprawić ich komfort.
Tryb wprowadzania translacji
ChromeOS domyślnie włącza tryb tłumaczenia wpisywanego tekstu. W przypadku większości aplikacji na Androida ten tryb pomaga im działać zgodnie z oczekiwaniami w środowisku komputerowym. Przykłady to automatyczne włączanie przewijania dwoma palcami na touchpadzie, przewijanie kółkiem myszy i mapowanie surowych współrzędnych wyświetlacza na współrzędne okna. Zwykle programiści aplikacji nie muszą sami implementować żadnego z tych zachowań.
Jeśli aplikacja implementuje niestandardowe zachowanie wejściowe, np. definiuje niestandardowe działanie uszczypnięcia dwoma 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 do manifestu Androida ten tag:
<uses-feature android:name="android.hardware.type.pc" android:required="false" />