In the recent project, we need to implement a function similar to floating ball, which can be dragged freely. The View drag function has previously been implemented through the View’s onTouchListener, but this way, the Viwe click event (click event) needs to be handled in addition.

Today through the Android drag and drop framework to achieve the View drag function.

Android drag-and-drop framework

The drag-and-drop framework is mainly used to drag and drop views from one View to another, but with multi-window mode enabled, it is also possible to drag and drop views from one application to another. You can set the data to be passed, and the drag path is drawn during the drag process (you can customize the draw content).

StartDrag () and startDragAndDrop ()

You can tell the system to start dragging by calling view.startDrag or view.startdragandDrop () (Android N +). Both methods require passing in four parameters:

parameter type meaning
clipData ClipData Drag-and-drop operation to transfer data
shadowBuilder DragShadowBuilder Drag the shadow constructor
myLocalState Object Local data that cannot be received when across activities
flags int Flags that control drag and drop operations

DragShadowBuilder

You can use the default drag shadow via View.DragShadowBuilder(View) (the same style as the View passed in), or you can inherit view.DragShadowBuilder to implement different shadows.

OnDragListener

You can set OnDragListener to monitor drag events in real time. DragEvent can be obtained in OnDragListener, and the Action in DragEvent can know the operation type of the current DragEvent. These actions include:

Action meaning
ACTION_DRAG_STARTED After calling the view.startDragandDrop () or view.startDragandDrop () method and getting the DragShadow, the listener View registered with OnDragListener receives this event action type, indicating the start of the drag. To receive ACTION_DROP, you must return true.
ACTION_DRAG_ENTERED When DragShadow enters the listener View’s bounding box, the listener View receives this event action type. To receive subsequent ACTION_DRAG_LOCATION and ACTION_DRAG_EXITED, you must return true.
ACTION_DRAG_LOCATION The listener View receives this event action type when the DragShadow moves within the listener View’s bounding box.
ACTION_DRAG_EXITED When DragShadow leaves the listener View’s bounding box, the listener View receives this event action type.
ACTION_DROP When a DragShadow is released on the listener View, the listener View receives this event action type. Return true if the release operation was successfully processed, false otherwise
ACTION_DRAG_ENDED The listener View receives this event action type when the system finishes dragging. You can call event.getresult () to retrieve the ACTION_DROP result value.

Implement drag and drop of View

Compared to the onTouchListener method, the drag-and-drop framework has its own path drawing, no need to constantly get the coordinate Settings to the View during the drag to display the path, and no additional processing of the View click events, much more convenient.

Here’s a simple implementation I did:

val dragView = findViewById<View>(R.id.drag_view) dragView? .run { val clipDataItem = ClipData.Item("111") val clipData = ClipData("111", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN), SetOnLongClickListener {val dragShadowBuilder = view.DragShadowBuilder (it) //clipData is a test pass data, If (build.version.sdk_int >= build.version_codes.n) {it.startDragandDrop (clipData, dragShadowBuilder, Null, 0)} else {it. StartDrag (clipData, dragShadowBuilder, NULL, 0)} true}} FrameLayout = findViewById(android.R.id.content) rootView.setOnDragListener { v, Event -> when (event.action) {dragevent.action_drag_started -> {// This action is received when view.startDrag () or startDragAndDrop() is called Visibility == view.visible) {dragView?. Visibility = view.invisible}} ACTION_DRAG_ENTERED -> {dragEvent.action_drag_entered -> {dragEvent.action_drag_entered -> { ACTION_DRAG_EXITED -> {// This Action is received when a View is dragged outside the listener View boundary. Dragevent.action_drop -> {// Release // Move the View to the position where it was released and display (here should also handle the trim logic, // Set the center of the View at the current coordinate val width = (crossPromotionAdView?.width?: 0) / 2 val height = (crossPromotionAdView?.height?: 0) X = event. X-width dragView?. Y = event. Y-height // Display View dragView?. Visibility = view.visible Val clipDataItem = event.clipdata.getitemat (0).text} // Get the data passed when startDrag() or startDragAndDrop() is called Dragevent. ACTION_DRAG_ENDED -> {// drag end}} // All events return true by default, you can adjust true as needed}Copy the code