Najważniejsze pojęcia

Wypróbuj tworzenie wiadomości
Jetpack Compose to zalecany zestaw narzędzi interfejsu na Androida. Dowiedz się, jak korzystać z przeciągania i upuszczania w Compose.

W poniższych sekcjach znajdziesz kilka kluczowych pojęć dotyczących procesu przeciągania i upuszczania.

Proces przeciągania i upuszczania

Proces przeciągania i upuszczania obejmuje 4 etapy lub stany: rozpoczęcie, kontynuowanie, upuszczenie i zakończenie.

Rozpoczęto

W odpowiedzi na gest przeciągania użytkownika aplikacja wywołuje funkcję startDragAndDrop(), aby zlecić systemowi rozpoczęcie operacji przeciągania i upuszczania. Argumenty metody:

  • Dane, które mają być przeciągane.
  • Callback do rysowania cienia przeciągania.
  • metadane opisujące przeciągnięte dane;
  • System odpowiada, wywołując Twoją aplikację, aby uzyskać informacje o przeciągniętym obiekcie. System wyświetli na urządzeniu cień przeciągania.
  • Następnie system wysyła zdarzenie przeciągania z typem działania ACTION_DRAG_STARTED do listenera zdarzenia przeciągania wszystkich obiektów View w bieżącym układzie. Aby nadal otrzymywać zdarzenia przeciągania (w tym zdarzenie upuszczenia), detektor zdarzeń przeciągania musi zwracać wartość true. Spowoduje to zarejestrowanie detektora w systemie. Tylko zarejestrowani słuchacze będą nadal otrzymywać zdarzenia przeciągania. W tym momencie detektory mogą też zmienić wygląd obiektu celu View, aby pokazać, że widok może obsłużyć zdarzenie drop.
  • Jeśli detektor zdarzenia przeciągania zwraca wartość false, nie otrzymuje zdarzeń przeciągania dotyczących bieżącej operacji, dopóki system nie wyśle zdarzenia przeciągania z typem działania ACTION_DRAG_ENDED. Zwracając false, listener informuje system, że nie jest zainteresowany operacją przeciągania i nie chce akceptować przeciąganych danych.
Kontynuuję
Użytkownik kontynuuje przeciąganie. Gdy cień przeciągania przecina ogranicznik celu przeciągania, system wysyła co najmniej 1 zdarzenie przeciągania do detektora zdarzenia przeciągania celu. W odpowiedzi na to zdarzenie detektor może zmienić wygląd celu View. Jeśli na przykład zdarzenie wskazuje, że cień przeciągania wchodzi w ramy obszaru docelowego – typ działania ACTION_DRAG_ENTERED – odbiorca może zareagować, podświetlając element View.
Usunięto
Użytkownik puszcza cień przeciągania w ramce obszaru docelowego. System wysyła do detektora celu upuszczenia zdarzenie przeciągania z typem działania ACTION_DROP. Obiekt zdarzenia przeciągania zawiera dane przekazywane do systemu w wywołaniu funkcji startDragAndDrop(), która inicjuje operację. Wyświetlacz powinien zwrócić do systemu wartość logiczną true, jeśli przetworzy dane. : Ten krok występuje tylko wtedy, gdy użytkownik upuści cień przeciągania w ramce View, którego odbiornik jest zarejestrowany do odbierania zdarzeń przeciągania (cel upuszczenia). Jeśli użytkownik zwolnił cień przeciągania w dowolnej innej sytuacji, nie zostanie wysłane żadne zdarzenie ACTION_DROP przeciągania.
Zakończona

Gdy użytkownik puści cień przeciągania, a system wyśle

Jeśli to konieczne, system wysyła zdarzenie przeciągania o typie działania ACTION_DROP, a potem zdarzenie przeciągania o typie działania ACTION_DRAG_ENDED, aby wskazać, że operacja przeciągania i upuszczania została zakończona. Dzieje się tak niezależnie od tego, gdzie użytkownik puści cień. Zdarzenie jest wysyłane do każdego detektora zarejestrowanego do odbierania zdarzeń przeciągania, nawet jeśli detektor otrzymuje też zdarzenie ACTION_DROP.

Każdy z tych kroków jest opisany bardziej szczegółowo w sekcji Operacja przeciągania i upuszczania.

Zdarzenia przeciągania

System wysyła zdarzenie przeciągania w postaci obiektu DragEvent, który zawiera typ działania opisujący, co dzieje się podczas procesu przeciągania i upuszczania. W zależności od typu działania obiekt może też zawierać inne dane.

Detektory zdarzeń przeciągnięcia otrzymują obiekt DragEvent. Aby uzyskać typ działania, słuchacze wywołują funkcję DragEvent.getAction(). W klasie DragEvent zdefiniowano 6 możliwych wartości stałych, które są opisane w tabeli 1:

Tabela 1. Typy zdarzeń DragEvent

Typ działania Znaczenie
ACTION_DRAG_STARTED Aplikacja wywołuje startDragAndDrop() i uzyskiwanie cienia przeciągania. Jeśli odbiorca chce nadal otrzymywać zdarzenia przeciągania w ramach tej operacji, musi zwrócić wartość logiczną true do systemu.
ACTION_DRAG_ENTERED Cień przeciągania wchodzi w ramy kontenera detektora zdarzeń przeciągania (View). Jest to pierwszy typ działania zdarzenia, które detektor otrzymuje, gdy cień przeciągania wejdzie w obszar ograniczający.
ACTION_DRAG_LOCATION Po zdarzeniu ACTION_DRAG_ENTERED cień przeciągania nadal znajduje się w ramach prostokąta ograniczającego detektora zdarzenia przeciągania View.
ACTION_DRAG_EXITED Po zdarzeniu ACTION_DRAG_ENTERED i co najmniej jednym zdarzeniu ACTION_DRAG_LOCATION cień przeciągania przesuwa się poza prostokąt ograniczający detektora zdarzenia przeciągania View.
ACTION_DROP Cień przeciągania zostaje zwolniony nad detektorem zdarzenia przeciągania View. Ten typ działania jest wysyłany do detektora zdarzenia View obiektu tylko wtedy, gdy detektor zwraca wartość logiczną true w odpowiedzi na zdarzenie przeciągania ACTION_DRAG_STARTED. Ten typ działania nie jest wysyłany, jeśli użytkownik puści cień przeciągania nad View, którego słuchacz nie jest zarejestrowany, lub jeśli użytkownik puści cień przeciągania nad elementem, który nie jest częścią bieżącego układu.

Listener zwraca wartość logiczną true, jeśli udało mu się przetworzyć drop. W przeciwnym razie musi zwracaćfalse.

ACTION_DRAG_ENDED System kończy operację przeciągania i upuszczania. Ten typ działania nie musi być poprzedzony zdarzeniem ACTION_DROP. Jeśli system wysyła zdarzenie ACTION_DROP, otrzymanie typu działania ACTION_DRAG_ENDED nie oznacza, że drop się powiódł. Aby uzyskać wartość zwracaną w odpowiedzi na wywołanie ACTION_DROP, detektor musi wywołać funkcję getResult(), jak pokazano w tabeli 2. Jeśli zdarzenie ACTION_DROP nie zostało wysłane, funkcja getResult() zwraca wartość false.

Obiekt DragEvent zawiera też dane i metadane, które aplikacja przekazuje do systemu w wywołaniu funkcji startDragAndDrop(). Niektóre dane są ważne tylko w przypadku określonych typów działań, jak podano w tabeli 2. Więcej informacji o zdarzeniach i powiązanych z nimi danych znajdziesz w sekcji Operacja przeciągania i upuszczania.

Tabela 2. Dane zdarzenia Valid DragEvent według typu działania

getAction()
wartość
getClipDescription()
wartość
getLocalState()
wartość
getX()
wartość
getY()
wartość
getClipData()
wartość
getResult()
wartość
ACTION_DRAG_STARTED ✓ ✓        
ACTION_DRAG_ENTERED ✓ ✓        
ACTION_DRAG_LOCATION ✓ ✓ ✓ ✓    
ACTION_DRAG_EXITED ✓ ✓        
ACTION_DROP ✓ ✓ ✓ ✓ ✓  
ACTION_DRAG_ENDED   ✓       ✓

Metody DragEvent getAction(), describeContents(), writeToParcel() i toString() zawsze zwracają prawidłowe dane.

Jeśli metoda nie zawiera prawidłowych danych dla określonego typu działania, zwraca null lub 0, w zależności od typu wyniku.

Przeciąganie cienia

Podczas przeciągania i upuszczania system wyświetla obraz przeciągany przez użytkownika. W przypadku przenoszenia danych obraz ten przedstawia przeciągane dane. W przypadku innych operacji obraz przedstawia pewien aspekt operacji przeciągania.

Obraz nazywa się przeciąganym cieniem. Tworzysz go za pomocą metod zadeklarowanych dla obiektu View.DragShadowBuilder. Gdy rozpoczynasz operację przeciągania i upuszczania za pomocą startDragAndDrop(), przekazujesz kreator do systemu. W ramach odpowiedzi na startDragAndDrop() system wywołuje metody wywołania zwrotnego zdefiniowane w View.DragShadowBuilder, aby uzyskać cień przeciągania.

Klasa View.DragShadowBuilder ma 2 konstruktory:

View.DragShadowBuilder(View)

Ten konstruktor akceptuje dowolne obiekty View aplikacji. Konstruktor przechowuje obiekt View w obiekcie View.DragShadowBuilder, aby funkcje zwracane mogły z niego korzystać podczas tworzenia cienia przeciągania. Widok nie musi być widokiem View, który użytkownik wybiera, aby rozpocząć przeciąganie.

Jeśli używasz tej metody konstruktora, nie musisz rozszerzać klasy View.DragShadowBuilder ani zastępować jej metod. Domyślnie otrzymujesz cień przeciągania o takim samym wyglądzie jak View przekazany jako argument, który jest wyśrodkowany pod miejscem, w którym użytkownik dotyka ekranu.

View.DragShadowBuilder()

Jeśli użyjesz tej metody konstruktora, w obiekcie View.DragShadowBuilder nie będzie dostępnego obiektu View. To pole ma wartość null. Musisz rozszerzyć klasę View.DragShadowBuilder i zastąpić jej metody, w przeciwnym razie będziesz mieć niewidoczną cieniowaną ramkę. System nie zwraca błędu.

Klasa View.DragShadowBuilder ma 2 metody, które razem tworzą cień przeciągania:

onProvideShadowMetrics()

System wywołuje tę metodę natychmiast po wywołaniu startDragAndDrop(). Użyj tej metody, aby wysłać wymiary i punkt dotykowy cienia przeciągania do systemu. Metoda ma 2 parametry:

outShadowSize: obiekt Point. Szerokość cienia przeciągania jest podawana w x, a wysokość – w y.

outShadowTouchPoint: obiekt Point. Punkt styczności to lokalizacja w cieniu przeciągania, która musi znajdować się pod palcem użytkownika podczas przeciągania. Jego pozycja X znajduje się w miejscu x, a pozycja Y – w miejscu y.

onDrawShadow()

Natychmiast po wywołaniu funkcji onProvideShadowMetrics() system wywołuje funkcję onDrawShadow(), aby utworzyć cień przeciągania. Metoda ma 1 argument, obiekt Canvas, który system tworzy na podstawie parametrów podanych w onProvideShadowMetrics(). Metoda rysuje cień przeciągania na podanym obiekcie Canvas.

Aby zwiększyć wydajność, zmniejsz rozmiar cienia przeciągania. W przypadku pojedynczego elementu możesz użyć ikony. W przypadku wielu elementów możesz użyć ikon w grupie, a nie pełnych obrazów rozłożonych na ekranie.

Przeciąganie detektorów zdarzeń i metod wywołania

Obiekt View odbiera zdarzenia przeciągania za pomocą detektora zdarzeń przeciągania, który implementuje funkcję View.OnDragListener, lub za pomocą metody wywołania onDragEvent() widoku. Gdy system wywołuje metodę lub interfejs Listener, przekazuje argument DragEvent.

W większości przypadków lepszym rozwiązaniem jest użycie listenera niż metody callback. Podczas projektowania interfejsu użytkownika zwykle nie tworzysz podklas klas View, ale korzystanie z metody wywołania zwrotnego wymusza tworzenie podklas, aby zastąpić metodę. W porównaniu z tym możesz zaimplementować jedną klasę listenera, a potem używać jej z wielu różnych obiektów View. Możesz też zaimplementować go jako anonimową klasę wbudowaną lub wyrażenie lambda. Aby ustawić detektor dla obiektu View, wywołaj funkcję setOnDragListener().

Możesz też zmodyfikować domyślną implementację funkcji onDragEvent() bez zastępowania metody. Ustaw OnReceiveContentListener w widoku. Więcej informacji znajdziesz w sekcji setOnReceiveContentListener(). Metoda onDragEvent() wykonuje wtedy domyślnie te czynności:

  • Zwraca wartość „PRAWDA” w odpowiedzi na wywołanie funkcji startDragAndDrop().
  • Połączeń performReceiveContent() jeśli dane przeciągane i upuszczane są w widoku. Dane są przekazywane metodzie jako obiekt ContentInfo. Metoda wywołuje funkcję OnReceiveContentListener.

  • Zwraca wartość „prawda”, jeśli dane przeciągane i upuszczane są umieszczane w widoku, a element OnReceiveContentListener zużywa jakąś zawartość.

Zdefiniuj OnReceiveContentListener, aby przetwarzać dane tylko w przypadku Twojej aplikacji. Aby zapewnić zgodność wsteczną z poziomem interfejsu API 24, użyj wersji OnReceiveContentListener z Jetpacka.

Możesz mieć detektor zdarzeń przeciągnięcia i metodę wywołania zwrotnego dla obiektu View. W takim przypadku system najpierw wywołuje detektor. System nie wywołuje metody callback, chyba że listener zwróci false.

Kombinacja metody onDragEvent()View.OnDragListener jest analogiczna do kombinacji onTouchEvent()View.OnTouchListener stosowanej w przypadku zdarzeń dotykowych.