ItemDragListener.java revision 57facaf76bc8d23b539518a342e1a126b51b64ce
1804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan/* 2804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Copyright (C) 2016 The Android Open Source Project 3804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * 4804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Licensed under the Apache License, Version 2.0 (the "License"); 5804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * you may not use this file except in compliance with the License. 6804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * You may obtain a copy of the License at 7804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * 8804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * http://www.apache.org/licenses/LICENSE-2.0 9804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * 10804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Unless required by applicable law or agreed to in writing, software 11804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * distributed under the License is distributed on an "AS IS" BASIS, 12804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * See the License for the specific language governing permissions and 14804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * limitations under the License. 15804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 16804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 17804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanpackage com.android.documentsui; 18804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 19804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport android.content.ClipData; 2057facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tanimport android.graphics.drawable.Drawable; 21804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport android.util.Log; 22804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport android.view.DragEvent; 23804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport android.view.View; 24804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport android.view.View.OnDragListener; 25804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport android.view.ViewConfiguration; 26804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 27804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport com.android.documentsui.ItemDragListener.DragHost; 28804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport com.android.internal.annotations.VisibleForTesting; 29804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 30804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport java.util.Timer; 31804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanimport java.util.TimerTask; 32804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 33804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan/** 34804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * An {@link OnDragListener} that adds support for "spring loading views". Use this when you want 35804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * items to pop-open when user hovers on them during a drag n drop. 36804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 37804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tanpublic class ItemDragListener<H extends DragHost> implements OnDragListener { 38804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 39804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan private static final String TAG = "ItemDragListener"; 40804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 41804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan @VisibleForTesting 42804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan static final int SPRING_TIMEOUT = ViewConfiguration.getLongPressTimeout(); 43804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 44804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan protected final H mDragHost; 45804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan private final Timer mHoverTimer; 46804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 47804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan public ItemDragListener(H dragHost) { 48804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan this(dragHost, new Timer()); 49804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 50804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 51804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan @VisibleForTesting 52804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan protected ItemDragListener(H dragHost, Timer timer) { 53804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mDragHost = dragHost; 54804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mHoverTimer = timer; 55804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 56804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 57804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan @Override 58804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan public boolean onDrag(final View v, DragEvent event) { 59804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan switch (event.getAction()) { 60804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan case DragEvent.ACTION_DRAG_STARTED: 61804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return true; 62804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan case DragEvent.ACTION_DRAG_ENTERED: 63804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan handleEnteredEvent(v); 64804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return true; 65804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan case DragEvent.ACTION_DRAG_LOCATION: 6657facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan handleLocationEvent(v, event.getX(), event.getY()); 67804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return true; 68804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan case DragEvent.ACTION_DRAG_EXITED: 69804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan case DragEvent.ACTION_DRAG_ENDED: 70804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan handleExitedEndedEvent(v); 71804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return true; 72804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan case DragEvent.ACTION_DROP: 73804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return handleDropEvent(v, event); 74804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 75804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 76804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return false; 77804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 78804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 79804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan private void handleEnteredEvent(View v) { 80804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mDragHost.setDropTargetHighlight(v, true); 81804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 82804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan TimerTask task = createOpenTask(v); 83804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan assert (task != null); 84804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan v.setTag(R.id.drag_hovering_tag, task); 85804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mHoverTimer.schedule(task, ViewConfiguration.getLongPressTimeout()); 86804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 87804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 8857facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan private void handleLocationEvent(View v, float x, float y) { 8957facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan Drawable background = v.getBackground(); 9057facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan if (background != null) { 9157facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan background.setHotspot(x, y); 9257facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan } 9357facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan } 9457facaf76bc8d23b539518a342e1a126b51b64ceGarfield, Tan 95804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan private void handleExitedEndedEvent(View v) { 96804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mDragHost.setDropTargetHighlight(v, false); 97804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 98804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan TimerTask task = (TimerTask) v.getTag(R.id.drag_hovering_tag); 99804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan if (task != null) { 100804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan task.cancel(); 101804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 102804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 103804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 104804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan private boolean handleDropEvent(View v, DragEvent event) { 105804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan ClipData clipData = event.getClipData(); 106804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan if (clipData == null) { 107804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan Log.w(TAG, "Received invalid drop event with null clipdata. Ignoring."); 108804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return false; 109804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 110804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 111804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return handleDropEventChecked(v, event); 112804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 113804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 114804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan @VisibleForTesting 115804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan TimerTask createOpenTask(final View v) { 116804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan TimerTask task = new TimerTask() { 117804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan @Override 118804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan public void run() { 119804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mDragHost.runOnUiThread(() -> { 120804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan mDragHost.onViewHovered(v); 121804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan }); 122804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 123804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan }; 124804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return task; 125804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 126804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 127804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan /** 128804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Handles a drop event. Override it if you want to do something on drop event. It's called when 129804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * {@link DragEvent#ACTION_DROP} happens. ClipData in DragEvent is guaranteed not null. 130804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * 131804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * @param v The view where user drops. 132804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * @param event the drag event. 133804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * @return true if this event is consumed; false otherwise 134804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 135804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan public boolean handleDropEventChecked(View v, DragEvent event) { 136804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan return false; // we didn't handle the drop 137804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 138804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 139804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan /** 140804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * An interface {@link ItemDragListener} uses to make some callbacks. 141804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 142804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan public interface DragHost { 143804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 144804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan /** 145804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Runs this runnable in main thread. 146804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 147804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan void runOnUiThread(Runnable runnable); 148804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 149804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan /** 150804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Highlights/unhighlights the view to visually indicate this view is being hovered. 151804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * @param v the view being hovered 152804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * @param highlight true if highlight the view; false if unhighlight it 153804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 154804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan void setDropTargetHighlight(View v, boolean highlight); 155804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan 156804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan /** 157804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * Notifies hovering timeout has elapsed 158804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan * @param v the view being hovered 159804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan */ 160804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan void onViewHovered(View v); 161804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan } 162804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan} 163