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łaniaACTION_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ż zdarzenieACTION_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ą |
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
Viewaplikacji. Konstruktor przechowuje obiektVieww obiekcieView.DragShadowBuilder, aby funkcje zwracane mogły z niego korzystać podczas tworzenia cienia przeciągania. Widok nie musi być widokiemView, 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 jakViewprzekazany 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 obiektuView. 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: obiektPoint. Szerokość cienia przeciągania jest podawana wx, a wysokość – wy.outShadowTouchPoint: obiektPoint. 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 miejscux, a pozycja Y – w miejscuy.onDrawShadow()Natychmiast po wywołaniu funkcji
onProvideShadowMetrics()system wywołuje funkcjęonDrawShadow(), aby utworzyć cień przeciągania. Metoda ma 1 argument, obiektCanvas, który system tworzy na podstawie parametrów podanych wonProvideShadowMetrics(). Metoda rysuje cień przeciągania na podanym obiekcieCanvas.
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 obiektContentInfo. 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.