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_STARTEDdo listenera zdarzenia przeciągania wszystkich obiektówVieww 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 celuView, 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łaniaACTION_DRAG_ENDED. Zwracającfalse, 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łaniaACTION_DRAG_ENTERED– odbiorca może zareagować, podświetlając elementView.
- 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 funkcjistartDragAndDrop(), 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 ramceView, 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 zdarzenieACTION_DROPprzecią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ątruedo 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_ENTEREDcień przeciągania nadal znajduje się w ramach prostokąta ograniczającego detektora zdarzenia przeciąganiaView. | 
| 
          
            ACTION_DRAG_EXITED | Po zdarzeniu ACTION_DRAG_ENTEREDi co najmniej jednym zdarzeniuACTION_DRAG_LOCATIONcień przeciągania przesuwa się poza prostokąt ograniczający detektora zdarzenia przeciąganiaView. | 
| 
          
            ACTION_DROP | Cień przeciągania zostaje zwolniony nad detektorem zdarzenia przeciągania View. Ten typ działania jest wysyłany do detektora zdarzeniaViewobiektu tylko wtedy, gdy detektor zwraca wartość logicznątruew odpowiedzi na zdarzenie przeciąganiaACTION_DRAG_STARTED. Ten typ działania nie jest wysyłany, jeśli użytkownik puści cień przeciągania nadView, 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ą  | 
| 
          
            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 zdarzenieACTION_DROP, otrzymanie typu działaniaACTION_DRAG_ENDEDnie oznacza, że drop się powiódł. Aby uzyskać wartość zwracaną w odpowiedzi na wywołanieACTION_DROP, detektor musi wywołać funkcjęgetResult(), jak pokazano w tabeli 2. Jeśli zdarzenieACTION_DROPnie zostało wysłane, funkcjagetResult()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 - Viewaplikacji. Konstruktor przechowuje obiekt- Vieww 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.DragShadowBuilderani zastępować jej metod. Domyślnie otrzymujesz cień przeciągania o takim samym wyglądzie jak- Viewprzekazany 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.DragShadowBuildernie będzie dostępnego obiektu- View. To pole ma wartość- null. Musisz rozszerzyć klasę- View.DragShadowBuilderi 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 - OnReceiveContentListenerzuż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() i View.OnDragListener jest analogiczna do kombinacji onTouchEvent() i View.OnTouchListener stosowanej w przypadku zdarzeń dotykowych.
 
  