Zgodność urządzeń wejściowych na dużych ekranach

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 wejściowych 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.
  • Testowanie zaawansowanego wsparcia klawiatury, na przykład TabEnter do nawigacji za pomocą klawiszy kursora, 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 najeżdżania kursorem oraz zdarzenia kółka myszy lub przewijania trackpada w komponentach niestandardowych.
  • Testuj urządzenia wejściowe związane z konkretną aplikacją, takie jak rysiki, kontrolery gier i kontrolery MIDI aplikacji muzycznych.
  • Rozważ zaimplementowanie zaawansowanego wsparcia dla danych wejściowych, które wyróżni Twoją aplikację na tle innych 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, którzy korzystają głównie 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 za pomocą klawiatury jest rzadko stosowana w aplikacji zorientowanej na dotyk, 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 kierunkowych i kart jest obsługiwana automatycznie przez platformę Androida. Na przykład element Button jest domyślnie aktywny, a przemieszczanie za pomocą klawiatury powinno działać bez dodatkowego kodu. Aby umożliwić nawigację za pomocą klawiatury w przypadku widoków, które nie są domyślnie zaznaczane, zaznacz je jako takie, co można zrobić programowo lub w pliku XML:

Kotlin

yourView.isFocusable = true

Java

yourView.setFocusable(true);

Możesz też ustawić atrybut focusable w pliku projektu:

android:focusable="true"

Więcej informacji znajdziesz w artykule Focus Handling.

Gdy funkcja ostrości jest włączona, platforma Android tworzy mapowanie nawigacyjne wszystkich widoków, w których można ustawić ostrość, na podstawie ich pozycji. Zwykle działa to zgodnie z oczekiwaniami i nie wymaga dalszego rozwoju. Jeśli domyślne mapowanie nie odpowiada potrzebom aplikacji, możesz 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);

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 EditText 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. Jest to szczególnie ważne w przypadku 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, sd.

Większość aplikacji zastępuje wywołanie zwrotne onKeyUp() i dodaje oczekiwane działanie dla każdego otrzymanego klucza kodu:

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);
    }
}

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ą wykrywać 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 Zarządzanie działaniami klawiatury.

Skróty

Podczas korzystania z klawiatury sprzętowej należy używać zwykłych skrótów klawiszowych, które obejmują klawisze Ctrl, Alt, ShiftMeta. 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.

Skróty można włączyć, implementując dispatchKeyShortcutEvent(), aby przechwytywać wszystkie kombinacje klawiszy (Alt, Ctrl, ShiftMeta) dla danego kodu klawisza. Aby sprawdzić konkretny klawisz modyfikujący, użyj:

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 metod obsługi naciśnięć klawiszy (takich jak onKeyUp()onKeyDown()) powoduje, że klawisze modyfikujące są domyślnie akceptowane bez konieczności ręcznego implementowania kontroli tych klawiszy w każdym przypadku. Zezwalanie na wszystkie kombinacje klawiszy modyfikujących może być też wygodniejsze dla użytkowników przyzwyczajonych do różnych układów klawiatury i systemów operacyjnych.

Możesz też zaimplementować skróty w onKeyUp(), zaznaczając KeyEvent.isCtrlPressed(), KeyEvent.isShiftPressed() lub KeyEvent.isAltPressed(). Może to być łatwiejsze do utrzymania, jeśli zmodyfikowane zachowanie klucza jest bardziej zmianą zachowania aplikacji niż skrótem. Na przykład w grach, gdy W oznacza „chodzenie do przodu”, a Shift+W – „bieganie 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ż Informacje o skrótach klawiszowych.

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.

Zdarzenie związane z rysikiem jest zgłaszane jako zdarzenie dotykowe przez View#onTouchEvent() lub View#onGenericMotionEvent() i zawiera MotionEvent#getSource() typu SOURCE_STYLUS.

Obiekt MotionEvent zawiera informacje o zdarzeniu:

Punkty historyczne

Android grupowanie zdarzeń wejściowych i przesyła je raz na ramkę. Stylus może zgłaszać zdarzenia z wielokrotnie 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

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 Androidzie 13 (poziom API 33) lub nowszym 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_CANCELFLAG_CANCELED w obiekcie zdarzenia ruchu. Jeśli inne wskaźniki są w dół, system ustawia ACTION_POINTER_UPFLAG_CANCELED.

Gdy aplikacja otrzyma zdarzenie ruchu z wartością ACTION_POINTER_UP, sprawdź, czy występuje zdarzenie FLAG_CANCELED, aby określić, czy oznacza ono odrzucenie dłoni (lub anulowanie innego zdarzenia).

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:

  1. Przejdź do trybu programisty i zezwól na zapis na urządzeniu
  2. Aby otworzyć terminal, naciśnij Ctrl+Alt+F2.
  3. Uruchom polecenie sudo vi /etc/chrome_dev.conf.
  4. Naciśnij i, aby edytować i dodać --ash-enable-palette do nowego wiersza na końcu pliku.
  5. Zapisz, naciskając Esc, a następnie wpisując :, w, q i naciskając Enter
  6. Aby wrócić do zwykłego interfejsu ChromeOS, naciśnij Ctrl+Alt+F1.
  7. 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 kursoremprzeciągnięcie i upuszczenie.

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

Kotlin

yourView.setOnContextClickListener {
    showContextMenu()
    true
}

Java

yourView.setOnContextClickListener(v -> {
    showContextMenu();
    return true;
});

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 będzie z nich korzystać, obsługując zdarzenia związane z najechaniem kursorem. Dotyczy to szczególnie 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:

  • Wskazanie użytkownikom, czy element jest interaktywny, np. czy można go kliknąć lub edytować, przez zmianę ikony kursora myszy
  • Dodawanie informacji wizualnych do elementów na dużej liście lub siatce po najechaniu na nie kursorem.

Przeciągnij i upuść

W środowisku wielookiennego użytkownicy oczekują, że będą mogli przeciągać i upuszczać elementy między aplikacjami. Dotyczy to komputerów, a także 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 Włączanie przeciągania i upuszczania oraz przeczytaj wpis na blogu Android na ChromeOS – implementacja przeciągania i upuszczania.

Ważne informacje dotyczące ChromeOS

Zaawansowana obsługa wskaźnika

Aplikacje, które obsługują zaawansowane dane wejściowe myszy i touchpada, powinny zaimplementować modyfikator View#onGenericMotionEvent() i użyj [MotionEvent.getSource()][], aby odróżnić SOURCE_MOUSE od SOURCE_TOUCHSCREEN.

Aby zaimplementować wymagane działanie, sprawdź obiekt MotionEvent:

  • Ruch powoduje generowanie zdarzeń ACTION_HOVER_MOVE.
  • Przyciski generują zdarzenia ACTION_BUTTON_PRESSACTION_BUTTON_RELEASE. Możesz też sprawdzić bieżący stan wszystkich przycisków myszy i touchpada, używając getButtonState().
  • Przewijanie kółkiem myszy generuje zdarzenia ACTION_SCROLL.

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 obejmują automatyczne włączanie przewijania dwoma 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 2 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 AndroidManifest.xml ten tag:

<uses-feature
    android:name="android.hardware.type.pc"
    android:required="false" />

Dodatkowe materiały