Omówienie zdarzeń wejściowych

Wypróbuj sposób tworzenia wiadomości
Jetpack Compose to zalecany zestaw narzędzi UI na Androida. Dowiedz się, jak w funkcji tworzenia wiadomości używać dotyku i wprowadzania tekstu.

Na Androidzie istnieje kilka sposobów przechwytywania zdarzeń związanych z interakcjami użytkownika z aplikacją. Podczas analizowania zdarzeń za pomocą interfejsu użytkownika celem jest przechwytywanie zdarzeń konkretny obiekt View, z którym użytkownik wchodzi w interakcję; Klasa View umożliwia wykonanie tego zadania.

W ramach różnych klas widoku danych, których użyjesz do stworzenia układu, możesz zauważyć kilka publicznych wywołań zwrotnych. które są przydatne w zdarzeniach interfejsu użytkownika. Te metody są wywoływane przez platformę Androida, gdy wykonywane na danym obiekcie odpowiednie działanie. Na przykład po dotknięciu widoku (takiego jak Przycisk) metoda onTouchEvent() jest wywoływana dla tego obiektu. Aby jednak je przechwycić, musisz rozszerzyć i zastąpić metodę. Rozszerzenie każdego obiektu widoku danych obsługi takich zdarzeń jest niepraktyczne. To dlatego klasa Widok zawiera też zbiór zagnieżdżonych interfejsów z wywołaniami zwrotnymi, które możesz znacznie łatwiej zdefiniować. Te interfejsy detektory zdarzeń to klucz do rejestrowania interakcji użytkownika z interfejsem.

Choć Częściej używa się detektorów zdarzeń do nasłuchiwania interakcji użytkownika, może gdy zechcesz rozszerzyć klasę View w celu utworzenia komponentu niestandardowego. Możesz zdecydować się na wydłużenie terminu: Button aby stworzyć coś bardziej wymyślnego. W takim przypadku można określić domyślne zachowania zdarzeń w za pomocą klasy modułów obsługi zdarzeń.

Detektory zdarzeń

Detektor zdarzeń to interfejs klasy View, który zawiera pojedynczy metody wywołania zwrotnego. Te metody będą wywoływane przez platformę Androida, gdy widok, do którego odbiornik jest wywoływane przez interakcję użytkownika z elementem w interfejsie.

Interfejsy detektora zdarzeń obejmują te metody wywołań zwrotnych:

onClick()
Od View.OnClickListener. Ta funkcja jest wywoływana, gdy użytkownik dotknie elementu. (w trybie dotykowym) albo przy użyciu klawiszy nawigacyjnych lub manipulatora kulkowego oraz naciska odpowiednie „Enter” lub naciśnij kulkę.
onLongClick()
Od View.OnLongClickListener. Ta funkcja jest wywoływana, gdy użytkownik dotknie i przytrzyma element (w trybie dotykowym). zaznacza element za pomocą klawiszy nawigacyjnych lub kulki oraz naciska i przytrzymuje odpowiedni klawisz „Enter” lub naciśnij i przytrzymaj kulkę (przez sekundę).
onFocusChange()
Od View.OnFocusChangeListener. Jest ona wywoływana, gdy użytkownik nawiguje do elementu lub z niego wychodzi, za pomocą klawiszy nawigacyjnych lub kulki.
onKey()
Od View.OnKeyListener. Ta funkcja jest wywoływana, gdy użytkownik skupia się na produkcie i naciska lub zwalnia klawisz sprzętowy na urządzeniu.
onTouch()
Od View.OnTouchListener. Jest ona wywoływana, gdy użytkownik wykona działanie sklasyfikowane jako zdarzenie dotknięcia, np. kliknięcie, lub dowolny gest ruchu na ekranie (w obrębie obiektu).
onCreateContextMenu()
Od View.OnCreateContextMenuListener. Ta funkcja jest wywoływana podczas tworzenia menu kontekstowego (w wyniku długotrwałego „długiego kliknięcia”). Zobacz dyskusję w menu kontekstowym w sekcji Menu przewodnik dla programistów.

Korzystanie z tych metod jest jedynym elementem ich interfejsu. Aby zdefiniować jedną z tych metod i obsługiwać zdarzenia, zaimplementuj zagnieżdżony interfejs w sekcji Aktywność lub zdefiniuj ją jako anonimową klasę. Następnie przekaż instancję implementacji do odpowiedniej metody View.set...Listener(). (Na przykład wywołaj setOnClickListener() i przekaż mu swoją implementację tagu OnClickListener).

Przykład poniżej pokazuje, jak zarejestrować detektor kliknięcia przycisku.

Kotlin

protected void onCreate(savedValues: Bundle) {
    ...
    val button: Button = findViewById(R.id.corky)
    // Register the onClick listener with the implementation above
    button.setOnClickListener { view ->
        // do something when the button is clicked
    }
    ...
}

Java

// Create an anonymous implementation of OnClickListener
private OnClickListener corkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(corkyListener);
    ...
}

Być może łatwiej będzie zaimplementować OnClickListener w ramach aktywności. Pozwoli to uniknąć dodatkowego obciążenia klas i przydziału obiektów. Na przykład:

Kotlin

class ExampleActivity : Activity(), OnClickListener {
  
    protected fun onCreate(savedValues: Bundle) {
        val button: Button = findViewById(R.id.corky)
        button.setOnClickListener(this)
    }

    // Implement the OnClickListener callback
    fun onClick(v: View) {
        // do something when the button is clicked
    }
}

Java

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

Zwróć uwagę, że wywołanie zwrotne onClick() w przykładzie powyżej nie zwraca żadnej wartości, ale niektóre inne metody detektora zdarzeń muszą zwracać wartość logiczną. Powód zależy od zdarzenia. Oto kilka powodów, dla których:

  • onLongClick() – Zwraca wartość logiczną wskazującą, czy zdarzenie zostało wykorzystane i nie powinno się ono dalej przenosić. Oznacza to, że zwróć wartość true, aby wskazać, że zdarzenie zostało już przez Ciebie obsługiwane i powinno ono kończyć się na tym etapie. zwróci wartość false, jeśli nie było obsługiwane i/lub zdarzenie powinno przejść do innego detektorów kliknięć.
  • onKey() – Zwraca wartość logiczną wskazującą, czy zdarzenie zostało wykorzystane i nie powinno się ono dalej przenosić. Oznacza to, że zwróć wartość true, aby wskazać, że zdarzenie zostało już przez Ciebie obsługiwane i powinno ono kończyć się na tym etapie. zwróci wartość false, jeśli nie było obsługiwane i/lub zdarzenie powinno przejść do innego na detektorach klawiszy.
  • onTouch() – Zwraca wartość logiczną wskazującą, czy detektor przetwarza to zdarzenie. Ważne jest to, to zdarzenie może zawierać wiele działań, które następują po sobie. Jeśli więc zwrócisz wartość false, gdy gdy użytkownik zrezygnuje ze zdarzenia, oznacza to, że nie został on wykorzystany ani nie są zainteresowani dalszymi działaniami w ramach tego wydarzenia. Oznacza to, że nie będziemy Cię wezwać do żadnych innych działań. w ramach zdarzenia, na przykład gestu palca lub wywołanego przez niego działania.

Pamiętaj, że kluczowe zdarzenia sprzętowe są zawsze wyświetlane w aktualnie widocznym widoku. Są wysyłane, zaczynając od góry hierarchii widoków, a później w dół, aż dotrzesz do odpowiedniego miejsca docelowego. Jeśli Twój widok danych (lub jego element podrzędny) jest obecnie zaznaczony, możesz wyświetlić podróż zdarzenia za pomocą metody dispatchKeyEvent(). Zamiast rejestrować kluczowe zdarzenia w widoku danych, możesz też przesyłać wszystkie zdarzenia w ramach Twojej aktywności z onKeyDown() i onKeyUp().

Jeśli chodzi o wprowadzanie tekstu w aplikacji, pamiętaj, że wiele urządzeń ma tylko interfejs programowy . Takie metody nie muszą być oparte na kluczu. niektóre mogą używać rozpoznawania mowy, pisma odręcznego itd. Nawet jeśli jeśli metoda wprowadzania ma interfejs podobny do klawiatury, zasadniczo nie wywoła Rodzina zdarzeń: onKeyDown(). Nigdy nie stworzyć interfejs użytkownika, który wymaga kontrolowania naciśnięć klawiszy, chyba że chcesz ograniczyć dostęp do aplikacji tylko na urządzeniach. dzięki klawiaturze sprzętowej. W szczególności nie używaj tych metod do weryfikowania danych wejściowych, gdy użytkownik naciśnie Return key (klucz zwrotny); użyj działań takich jak IME_ACTION_DONE, aby zasygnalizować jak aplikacja ma zareagować, może więc istotnie zmienić swój interfejs użytkownika. Unikaj założeń jak powinna działać oprogramowana metoda wprowadzania danych, i ufaj, że dostarcza do aplikacji sformatowany tekst.

Uwaga: Android wywoła najpierw moduły obsługi zdarzeń, a następnie odpowiednie domyślne modułów obsługi z definicji klasy. W związku z tym zwracanie wartości true przez te detektory zdarzeń zostanie zatrzymane propagacji zdarzenia do innych detektorów zdarzeń i zablokuje wywołanie zwrotne do domyślny moduł obsługi zdarzeń w widoku danych. Upewnij się więc, że chcesz zakończyć wydarzenie, kiedy zwrócisz wartość true.

Moduły obsługi zdarzeń

Jeśli tworzysz komponent niestandardowy z poziomu widoku, możesz zdefiniować kilka metod wywołania zwrotnego są używane jako domyślne moduły obsługi zdarzeń. W dokumencie na temat opcji Niestandardowe wyświetl komponenty, poznasz niektóre typowe wywołania zwrotne do obsługi zdarzeń, w tym:

Istnieją też inne metody, o których warto wiedzieć, które nie należą do klasy widoku danych, ale też mieć bezpośredni wpływ na sposób obsługi zdarzeń. Podczas zarządzania złożonymi wydarzeniami w układzie graficznym, możesz zastosować następujące metody:

Tryb dotykowy

Gdy użytkownik porusza się po interfejsie za pomocą klawiszy kierunkowych lub kulki, jest niezbędny do wyróżnienia aktywnych elementów (takich jak przyciski), tak aby użytkownik widział co akceptuje dane wejściowe. Jeśli urządzenie ma funkcje dotykowe, rozpoczyna interakcję z interfejsem przez dotknięcie go, nie trzeba już możesz wyróżnić elementy lub wybrać konkretny widok. Umożliwia to w przypadku interakcji o nazwie „tryb dotykowy”.

W przypadku urządzenia dotykowego, gdy użytkownik dotknie ekranu, przejdzie w tryb dotykowy. Od tej pory tylko widoki, dla których isFocusableInTouchMode() ma wartość Prawda, co umożliwia zaznaczanie, tak jak widżety do edycji tekstu. Inne Widoki, które są dotykowe, np. przyciski, nie zabierają ostrości po dotknięciu. będą po prostu uruchamiają detektory aktywne po kliknięciu.

Po każdym naciśnięciu klawisza kierunkowego lub przewijaniu kulki urządzenie wyjdź z trybu dotykowego i znajdź widok, na którym chcesz się skupić. Teraz użytkownik może wznowić interakcję za pomocą interfejsu użytkownika bez dotykania ekranu.

Stan trybu dotykowego jest utrzymywany w całym systemie (we wszystkich oknach i czynnościach). Aby przesłać zapytanie o bieżący stan, wywołaj isInTouchMode(), by sprawdzić, czy urządzenie jest obecnie w trybie dotykowym.

Koncentracja na radzeniu sobie z problemem

Platforma obsługuje rutynowe ruchy skupione w odpowiedzi na dane wejściowe użytkownika. Obejmuje to zmienianie zaznaczenia po usunięciu lub ukryciu albo gdy wyświetlenia są nowe. Widoki staną się dostępne. Wyświetlenia świadczą o chęci skupienia się na skupieniu za pomocą metody isFocusable(). Aby określić, czy Widok może skupienie, wywołaj setFocusable(). W trybie dotykowym możesz zapytać, czy widok umożliwia zaznaczanie za pomocą funkcji isFocusableInTouchMode(). Możesz to zmienić w setFocusableInTouchMode().

Na urządzeniach z Androidem 9 (poziom interfejsu API 28) lub nowszym działania nie powodują przypisania i pierwszy punkt skupienia. Zamiast tego w razie potrzeby musisz wyraźnie poprosić o początkowe zaznaczenie.

Ruch skupienia opiera się na algorytmie, który znajduje najbliższego sąsiada w w wybranym kierunku. W rzadkich przypadkach domyślny algorytm może nie odpowiadać zamierzone działanie dewelopera. W takiej sytuacji możesz podać jawne zastąpienia z tymi atrybutami XML w pliku układu: nextFocusDown, nextFocusLeft, nextFocusRight i nextFocusUp Dodaj do widoku z tych atrybutów, i staje się w centrum uwagi. Określ wartość atrybutu, która będzie identyfikatorem widoku. do którego elementu należy się skupić. Na przykład:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

W układzie pionowym przechodzenie od pierwszego przycisku nie byłoby możliwe. ani przejście z drugiego przycisku. Teraz, gdy górny przycisk tę dolną zdefiniowano jako nextFocusUp (i na odwrót), zaznaczenie zostanie przeniesione od góry do dołu i od dołu do góry.

Jeśli chcesz zadeklarować widok w interfejsie jako możliwy do zaznaczenia (gdy tradycyjnie nie jest to możliwe): dodaj atrybut XML android:focusable do widoku w deklaracji układu. Ustaw wartość true. Możesz też zadeklarować widok, można zaznaczyć w trybie dotykowym z urządzeniem android:focusableInTouchMode.

Aby poprosić o konkretny widok danych, zadzwoń pod numer requestFocus().

Aby wykrywać zdarzenia skupienia (otrzymywać powiadomienia, gdy widok danych stanie się lub przestanie być fokus), użyj onFocusChange(), jak omówiono w sekcji Detektory zdarzeń.