Resizable Apps & Multi-Window Support in Android

Mar 30 2021 · Kotlin 1.4, Android 11, Android Studio 4

Part 1: Resizable Apps & Multi-Window Support in Android

07. Enable Drag & Drop Support: Part 1

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 06. Launch Activities In Multi-Window Mode Next episode: 08. Enable Drag & Drop Support: Part 2

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 07. Enable Drag & Drop Support: Part 1

The last feature you’ll learn about that works well with multi-window support is the drag & drop feature.

Drag & drop, as the name states, allows you to drag and drop data between different Activities. It’s great for apps that deal with a lot of information that you want to share between different parts of the app. A great example is dragging item cards into a trash screen, to automatically delete items. Or moving items between different groups.

To showcase this feature, you’ll enable the dragging & dropping feature in the WallOfText app, but you’ll use another app called Droppey, to receive the data and show it on the UI.

In the next episode, in Droppey, you’ll enable the drop feature, to receive data from other apps. Let’s start building this feature.

Open the AddNoteActivity.kt file. Now add the following property at the top of the class:

 private val dragListener by lazy { buildDragListener() }

This will represent the dragListener, that you’ll attach to one of your UI elements. buildDragListener() doesn’t exist, but you’ll add it in a moment.

Now add the following piece of code to onCreate():

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableDragListener() // here
  }

Right after the Activity is created, you’ll enable the listener and attach it to the notes UI element. Build the enableDragListener() function next:

  private fun enableDragListener() {
    binding.notes.setOnDragListener(dragListener)
    binding.notes.setOnLongClickListener(buildLongClickListener())
  }

The function adds the dragListener to the notes element, but also attaches a longClickListener to it. This is important, as the drag listener doesn’t initiate the drag, it reacts to it. And you need a long click listener to initiate the drag, when the user performs a long click.

Now let’s build the long click listener:

private fun buildLongClickListener() = View.OnLongClickListener {


  true
}

This function will return the listener and return true, to consume the long click. Now add the following code, to prepare the data for the drag:

  val data = ClipData.Item(binding.notes.text.toString())
  val dragData = ClipData("Notes Data", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN), data)

The first statement builds an item to transfer through the drag & drop gesture. You’ll put the notes text in the drag, so you can display the note in a different app.

The second statement builds the actual piece of data. You also add a name to the data piece, so you can recognize what you’re transferring. Additionally, you add a mime type of plain text, to let the other app know it’s a text. Finally, add the last piece of code to start the drag and drop:

  it.startDragAndDrop(
    dragData,
    View.DragShadowBuilder(binding.notes),
    null,
    View.DRAG_FLAG_GLOBAL
  )

By calling startDragAndDrop(), you pass in the data you want to transfer, a shadow builder where can use the default one, by passing in the View you want to drag, null for the local state object, that you don’t need right now, but it serves to decorate the event with extra information, and finally, the drag flags.

Make sure the drag flags are GLOBAL, so you can transfer data between apps! Now that you have the drag & drop initiated on a long click, you can build the drag listener that’ll react to your drag events:

private fun buildDragListener(): View.OnDragListener = View.OnDragListener { _, event ->

  
  true
}

Just like before, you’re returning a simple listener, with true as its return value, to let the listener know you’ve consumed the event. Now add the drag start event:

  when (event.action) {
    DragEvent.ACTION_DRAG_STARTED -> {
      binding.notes.setTextColor(getColor(R.color.purple_200))
    }
  }

Using event.action you can find out which part of the drag is happening. There are many events to handle, such as moving the dragged item, stopping, starting, ending the event and more. Here you’ll change the notes text to be purple, if you decide to drag the item. And finally, add the drag end event:

    DragEvent.ACTION_DRAG_ENDED -> {
      binding.notes.setTextColor(getColor(R.color.teal_700))
    }

In the end event, you just reset the text color, to be teal. This will let the user know they’ve started or stopped dragging the item. Build and run the app and try dragging your notes!

Awesome! All that’s left to do is to listen to the drop event in another app, called Droppey. Let’s do that next!