254
CHAPTER 9: User Interface
While the dragging is in progress, the dragged target gets visually
represented by a moving
shadow
object. You are free to define it. It
could be a star, a box, or any kind of graphics resembling the drag
source. You only have to tell the system how to paint it.
The positioning
during the drag operation gets automatically handled by the Android
OS. Because the drag source stays in place during the drag operation,
the layout remains static all the time, and the dragging does not thwart
layout operations by the layout manager.
When the drag shadow enters the area of a possible drop target, the
listener gets informed about that,
and you can react by, for example,
changing the visual appearance of the drop candidate.
Because all drag sources and possible drop targets get informed about
the various dragging states, you are free to visually express that by
using different view appearances.
Once a drop happens, the listener gets informed and you can freely
react on such drop events.
It is also possible to not use a dedicated drag-and-drop listener but instead overwrite some
specific methods of the views taking part in drag-and-drop operations. The downside of
that is you have to use the customized views
inside the layout description, which makes
it somewhat less readable. Also, from an architectural point of view, the views then know
too much of what is happening
to
them, which is an external concern and as such is better
handled from outside objects. We therefore follow the listener approach and in the following
sections describe what exactly to do for this methodology.
Defining
Drag Data
If your drag-and-drop operation defines some kind of data transfer from one object
represented by a view to another, you define a
ClipData
object, for example, as follows:
val item = ClipData.Item(myView.tag.toString())
val dragData = ClipData(myView.tag.toString(),
arrayOf(MIMETYPE_TEXT_PLAIN), item)
The first argument to the constructor is a user-readable label for the clip datum, the second
describes the type of the contents by assigning
appropriate MIME types, and the
item
argument
represents the datum to be transported, which here is the string given by the
tag
attribute of the
view. Other item types are intents and URIs, to be specified in the constructor of
ClipData.Item
.
Defining
a Drag Shadow
The drag shadow is the visible element painted underneath your finger while the dragging is
in progress. You define the shadow in an object as follows:
class DragShadow(val resources: Resources, val resId:Int,
view: ImageView) : View.DragShadowBuilder(view) {
val rect = Rect()