Category: Blog, Android, Development

Multi-Window Simple Examples: Part 2 – Drag and Drop

Multi-Window Simple Examples: Part 2 - Drag and Drop

Introduction

Drag and drop are a little bit more difficult than handling screen changes (Part 1). Why is that? Mainly because we don’t want to just trigger the drop action to another application but also to send something (i.e. some text, resource or something else).

This time, I’ll present a simple example of how to handle drag and drop without worrying about permissions for now. For this reason, I’ve created two applications.

Catch’em all!

The first application, MultiWindowCatch, you should know from Part 1. You can find the app on the bottom of this article.

multi_window_catch

This app simply shows first nine Pokémons – each evolution of bulbasaur, charmander and squirtle. And that’s it. If we want to catch more Pokémons, first of all, we have to install the MultiWindowDropAndAdjacent app.

multi_window_drop

After that we have to make only 5 moves to get new Pokémon:

  1. Click on pokéball icon on the toolbar.
  2. Long click on Overview button.
  3. Select MultiWindowDropAndAdjacent app with other Pokémons (now we should see two apps at once).
  4. By clicking left and right arrow chose which Pokémon we want to catch.
  5. Drag pokéball and drop it on chosen Pokémon.

Start drag and drop

In PokeballActivity we want to start drag and drop by long press on pokéball image.

As you can see I use ButterKnife (@BindView, @OnLongClick) – it is very handy.

Firstly I check if we have at least Android N and then I run View.startDragAndDrop() method. We have to pass a couple of parameters to this method:

1. ClipData – an object with data that we pass to other application. This should be a simple example, right? So we should create that object in a very basic way.

We just pass the ClipData.An item with text “POKEBALL” and base on this in other application (MultiWindowDropAndAdjacent) we will be able to know that some application wants to catch current Pokémon on the screen.

2. View.DragShadowBuilder – an object that will draw a shadow during dragging.

3. Local data Object – we don’t need this.

4. Flag View.DRAG_FLAG_GLOBAL. The documentation says “To enable cross-activity drag and drop, pass the new flag View.DRAG_FLAG_GLOBAL“, so I passed it (and as I said, in this example, we don’t worry about permissions).

Basically View.startDragAndDrop() method is a new implementation for View.startDrag() (from N is deprecated). You can read more about drag and drop process in Drag and Drop chapter in API Guides. Implementation of View.startDrag() method you will find in section Designing a Drag and Drop Operation.

Drop in different app

Ok, so now let’s move from MultiWindowCatch app to MultiWindowDropAndAdjacent and drop the pokéball.

What we want to do is to drop pokéball on selected new pokéball and trigger that action, so we have to implement drag listener on Pokémon image on which we will drop pokéball.

I used retrolambda in listener, but if you don’t like it, here you have:

I pass DragEvent do sendPokemonIdIfDrop() method and simply check if user dropped something. We can also listen for more events than DragEvent.ACTION_DROP like DragEvent.ACTION_DRAG_STARTED or DragEvent.ACTION_DRAG_ENDED. The most interesting part is when we start dragging something in another app, as all the drag events reach also to our listener in our app.

Then I get ClipData.Item from ClipData and paste the text from it to Presenter.

As you can see if dropped text is “POKEBALL” it means that some app tries to catch Pokémon. The appropriate link with the image is created and sent to Android system.

We could end it here – Android system will search which app will be able to open that link and it should find at least Chrome. We can also register one of our Activity from the previous app with pokéball to save caught Pokémon.

Save caught Pokémon

We have to go back to MultiWindowCatch app, register URL and save Pokémon.

Now after the drop, in-app chooser, our app also will be visible. The last step is to save Pokémon image URL and id.

Checking if extras are from deep link simply comes down to checking if both image URL and id were sent. I used Realm to save them – Realm is very fast and the object is plain, so I do it in the main thread. List of Pokémon is displayed in onStart() with the new one on the beginning of the list.

Summary

Implementing drag and drop functionality during Multi-Window mode is very similar to what we had previously. In one app we have to start dragging and in another get the dropped data. This example is very simple and it clarifies few important points like permissions (what if I don’t want to get dropped data from another app?) or a way of sending data between two apps.

<< Part 1 – Screen changes

Part 3 – Launching another app >>