From 3cefcc69c10ab12bd782a0b53779dbd1cc0e2aa1 Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Thu, 16 Jan 2014 11:26:46 -0800 Subject: Add drag to remove for favorites in Dialer * Add remove view in dialtacts_activity.xml, and rearrange layout slightly so that it takes up the same position in the layout as the search view container. Contacts that are dragged to this remove view will be unstarred and unpinned. * Add drag event logic to the Remove View, so that when the user hovers a contact over it, the UI will continue to respond. Previously, only the PhoneFavoritesListView would detect touch events. * Refactor DragDropController and OnDragDropListener into separate classes. DragDropController performs the work of receiving drag/drop events from multiple views, combining them, and then firing off callbacks as appropriate to OnDragDropListeners. Each OnDragDropListener can then update their UI or internal data model as necessary in response to the callbacks. OnDragDropListener <---------------------------------------- ^ | | | DialtactsActivity ---------------> RemoveView | | | | v | | callbacks PhoneFavoriteListFragment |drag events | | | | v v | PhoneFavoriteListView ------------> DragController-------- drag events | | callbacks v PhoneFavoritesTileAdapter --> OnDragDropListener * While in here, add a content description for the clear search button Change-Id: I044ad1c5aa42c7686bde6bf5074095a4fe879bde --- res/drawable-hdpi/ic_remove.png | Bin 0 -> 884 bytes res/drawable-hdpi/ic_remove_highlight.png | Bin 0 -> 717 bytes res/drawable-mdpi/ic_remove.png | Bin 0 -> 728 bytes res/drawable-mdpi/ic_remove_highlight.png | Bin 0 -> 587 bytes res/drawable-xhdpi/ic_remove.png | Bin 0 -> 1237 bytes res/drawable-xhdpi/ic_remove_highlight.png | Bin 0 -> 974 bytes res/drawable-xxhdpi/ic_remove.png | Bin 0 -> 1942 bytes res/drawable-xxhdpi/ic_remove_highlight.png | Bin 0 -> 1590 bytes res/layout/dialtacts_activity.xml | 44 ++++-- res/values/colors.xml | 16 +- res/values/dimens.xml | 20 ++- res/values/strings.xml | 5 + src/com/android/dialer/DialtactsActivity.java | 59 +++++++- .../android/dialer/list/DragDropController.java | 71 +++++++++ .../android/dialer/list/OnDragDropListener.java | 41 +++++ .../android/dialer/list/PhoneFavoriteFragment.java | 15 +- .../android/dialer/list/PhoneFavoriteListView.java | 166 ++++++++++----------- .../dialer/list/PhoneFavoritesTileAdapter.java | 26 +++- src/com/android/dialer/list/RemoveView.java | 90 +++++++++++ 19 files changed, 433 insertions(+), 120 deletions(-) create mode 100644 res/drawable-hdpi/ic_remove.png create mode 100644 res/drawable-hdpi/ic_remove_highlight.png create mode 100644 res/drawable-mdpi/ic_remove.png create mode 100644 res/drawable-mdpi/ic_remove_highlight.png create mode 100644 res/drawable-xhdpi/ic_remove.png create mode 100644 res/drawable-xhdpi/ic_remove_highlight.png create mode 100644 res/drawable-xxhdpi/ic_remove.png create mode 100644 res/drawable-xxhdpi/ic_remove_highlight.png create mode 100644 src/com/android/dialer/list/DragDropController.java create mode 100644 src/com/android/dialer/list/OnDragDropListener.java create mode 100644 src/com/android/dialer/list/RemoveView.java diff --git a/res/drawable-hdpi/ic_remove.png b/res/drawable-hdpi/ic_remove.png new file mode 100644 index 000000000..1ee6adf8d Binary files /dev/null and b/res/drawable-hdpi/ic_remove.png differ diff --git a/res/drawable-hdpi/ic_remove_highlight.png b/res/drawable-hdpi/ic_remove_highlight.png new file mode 100644 index 000000000..435ee36b0 Binary files /dev/null and b/res/drawable-hdpi/ic_remove_highlight.png differ diff --git a/res/drawable-mdpi/ic_remove.png b/res/drawable-mdpi/ic_remove.png new file mode 100644 index 000000000..2c134ea10 Binary files /dev/null and b/res/drawable-mdpi/ic_remove.png differ diff --git a/res/drawable-mdpi/ic_remove_highlight.png b/res/drawable-mdpi/ic_remove_highlight.png new file mode 100644 index 000000000..6a961cbb2 Binary files /dev/null and b/res/drawable-mdpi/ic_remove_highlight.png differ diff --git a/res/drawable-xhdpi/ic_remove.png b/res/drawable-xhdpi/ic_remove.png new file mode 100644 index 000000000..be81592ef Binary files /dev/null and b/res/drawable-xhdpi/ic_remove.png differ diff --git a/res/drawable-xhdpi/ic_remove_highlight.png b/res/drawable-xhdpi/ic_remove_highlight.png new file mode 100644 index 000000000..57949e317 Binary files /dev/null and b/res/drawable-xhdpi/ic_remove_highlight.png differ diff --git a/res/drawable-xxhdpi/ic_remove.png b/res/drawable-xxhdpi/ic_remove.png new file mode 100644 index 000000000..2722f23aa Binary files /dev/null and b/res/drawable-xxhdpi/ic_remove.png differ diff --git a/res/drawable-xxhdpi/ic_remove_highlight.png b/res/drawable-xxhdpi/ic_remove_highlight.png new file mode 100644 index 000000000..23ee8f6da Binary files /dev/null and b/res/drawable-xxhdpi/ic_remove_highlight.png differ diff --git a/res/layout/dialtacts_activity.xml b/res/layout/dialtacts_activity.xml index e2c385364..5a886e226 100644 --- a/res/layout/dialtacts_activity.xml +++ b/res/layout/dialtacts_activity.xml @@ -28,20 +28,20 @@ android:layout_height="match_parent" android:clipChildren="false" android:orientation="vertical" > - + android:gravity="center_vertical" + > - - + android:layout_height="56dp" + android:id="@+id/remove_view_container" + android:orientation="horizontal" + android:gravity="center" + android:visibility="gone"> + + + + + +--> @@ -27,8 +27,10 @@ #33b5e5 - + #cecece @@ -38,7 +40,7 @@ #660099cc - #cecece + #eeeeee #eeeeee @@ -71,6 +73,12 @@ #777777 + + #555555 + + + #FF3F3B + #555555 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 3c856d2e6..fb74e9748 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -13,7 +13,7 @@ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License - --> +--> @@ -29,9 +29,15 @@ 74dp - + 14sp + + 16dp + 32dip 48dip @@ -51,9 +57,11 @@ the main area of a call log entry and the secondary action button. --> 1dp - + ratio. + --> 15 65 @@ -63,14 +71,14 @@ 15dp 25dp 41dp - - 60dp 56dp 12dp + + 3dp 36dp 67% 6dp diff --git a/res/values/strings.xml b/res/values/strings.xml index a61e0bc4a..3f2157712 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -539,6 +539,9 @@ --> Unheard voicemail + + Clear search + Start voice search @@ -726,6 +729,8 @@ Dismiss + + Remove Speed Dial diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java index 0c0fcdafe..227cd8eca 100644 --- a/src/com/android/dialer/DialtactsActivity.java +++ b/src/com/android/dialer/DialtactsActivity.java @@ -22,7 +22,6 @@ import android.animation.AnimatorListenerAdapter; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; -import android.app.FragmentManager.BackStackEntry; import android.app.FragmentTransaction; import android.content.ActivityNotFoundException; import android.content.Context; @@ -50,8 +49,6 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnFocusChangeListener; import android.view.inputmethod.InputMethodManager; import android.widget.AbsListView.OnScrollListener; import android.widget.EditText; @@ -70,9 +67,13 @@ import com.android.dialer.dialpad.SmartDialNameMatcher; import com.android.dialer.dialpad.SmartDialPrefix; import com.android.dialer.interactions.PhoneNumberInteraction; import com.android.dialer.list.AllContactsActivity; +import com.android.dialer.list.DragDropController; +import com.android.dialer.list.OnDragDropListener; import com.android.dialer.list.OnListFragmentScrolledListener; import com.android.dialer.list.PhoneFavoriteFragment; +import com.android.dialer.list.PhoneFavoriteTileView; import com.android.dialer.list.RegularSearchFragment; +import com.android.dialer.list.RemoveView; import com.android.dialer.list.SearchFragment; import com.android.dialer.list.SmartDialSearchFragment; import com.android.dialerbind.DatabaseHelperManager; @@ -88,7 +89,9 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O DialpadFragment.OnDialpadQueryChangedListener, PopupMenu.OnMenuItemClickListener, OnListFragmentScrolledListener, DialpadFragment.OnDialpadFragmentStartedListener, - PhoneFavoriteFragment.OnShowAllContactsListener { + PhoneFavoriteFragment.OnShowAllContactsListener, + PhoneFavoriteFragment.HostInterface, + OnDragDropListener { private static final String TAG = "DialtactsActivity"; public static final boolean DEBUG = false; @@ -122,6 +125,8 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O private static final int ACTIVITY_REQUEST_CODE_VOICE_SEARCH = 1; + private static final int FADE_ANIMATION_DURATION = 200; + private String mFilterText; /** @@ -168,6 +173,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O */ private boolean mFirstLaunch; private View mSearchViewContainer; + private RemoveView mRemoveViewContainer; private View mSearchViewCloseButton; private View mVoiceSearchButton; private EditText mSearchView; @@ -312,6 +318,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O mBottomPaddingView = findViewById(R.id.dialtacts_bottom_padding); mFragmentsFrame = findViewById(R.id.dialtacts_frame); mActionBar = findViewById(R.id.fake_action_bar); + mRemoveViewContainer = (RemoveView) findViewById(R.id.remove_view_container); prepareSearchView(); if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction()) @@ -977,4 +984,48 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O PackageManager.MATCH_DEFAULT_ONLY); return resolveInfo != null && resolveInfo.size() > 0; } + + @Override + public void onDragStarted(int itemIndex, int x, int y, PhoneFavoriteTileView view) { + crossfadeViews(mRemoveViewContainer, mSearchViewContainer, FADE_ANIMATION_DURATION); + } + + @Override + public void onDragHovered(int itemIndex, int x, int y) {} + + @Override + public void onDragFinished(int x, int y) { + crossfadeViews(mSearchViewContainer, mRemoveViewContainer, FADE_ANIMATION_DURATION); + } + + @Override + public void onDroppedOnRemove() {} + + /** + * Allows the PhoneFavoriteFragment to attach the drag controller to mRemoveViewContainer + * once it has been attached to the activity. + */ + @Override + public void setDragDropController(DragDropController dragController) { + mRemoveViewContainer.setDragDropController(dragController); + } + + /** + * Crossfades two views so that the first one appears while the other one is fading + * out of view. + */ + private void crossfadeViews(final View fadeIn, final View fadeOut, int duration) { + fadeOut.animate().alpha(0).setDuration(duration) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + fadeOut.setVisibility(View.GONE); + } + }); + + fadeIn.setVisibility(View.VISIBLE); + fadeIn.setAlpha(0); + fadeIn.animate().alpha(1).setDuration(FADE_ANIMATION_DURATION) + .setListener(null); + } } diff --git a/src/com/android/dialer/list/DragDropController.java b/src/com/android/dialer/list/DragDropController.java new file mode 100644 index 000000000..399cd099b --- /dev/null +++ b/src/com/android/dialer/list/DragDropController.java @@ -0,0 +1,71 @@ +package com.android.dialer.list; + +import android.view.View; + +import com.android.dialer.list.PhoneFavoritesTileAdapter.ContactTileRow; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class that handles and combines drag events generated from multiple views, and then fires + * off events to any OnDragDropListeners that have registered for callbacks. + */ +public class DragDropController { + private List mOnDragDropListeners = new ArrayList(); + + /** + * @return True if the drag is started, false if the drag is cancelled for some reason. + */ + boolean handleDragStarted(int x, int y, ContactTileRow tileRow) { + final PhoneFavoriteTileView tileView = + (PhoneFavoriteTileView) tileRow.getViewAtPosition(x, y); + + final int itemIndex = tileRow.getItemIndex(x, y); + if (itemIndex != -1 && !mOnDragDropListeners.isEmpty()) { + for (int i = 0; i < mOnDragDropListeners.size(); i++) { + mOnDragDropListeners.get(i).onDragStarted(itemIndex, x, y, tileView); + } + } + + return true; + } + + public void handleDragHovered(int x, int y, View view) { + int itemIndex; + if (!(view instanceof ContactTileRow)) { + itemIndex = -1; + } else { + final ContactTileRow tile = (ContactTileRow) view; + itemIndex = tile.getItemIndex(x, y); + } + for (int i = 0; i < mOnDragDropListeners.size(); i++) { + mOnDragDropListeners.get(i).onDragHovered(itemIndex, x, y); + } + } + + public void handleDragFinished(int x, int y, boolean isRemoveView) { + if (isRemoveView) { + for (int i = 0; i < mOnDragDropListeners.size(); i++) { + mOnDragDropListeners.get(i).onDroppedOnRemove(); + } + } + + for (int i = 0; i < mOnDragDropListeners.size(); i++) { + mOnDragDropListeners.get(i).onDragFinished(x, y); + } + } + + public void addOnDragDropListener(OnDragDropListener listener) { + if (!mOnDragDropListeners.contains(listener)) { + mOnDragDropListeners.add(listener); + } + } + + public void removeOnDragDropListener(OnDragDropListener listener) { + if (mOnDragDropListeners.contains(listener)) { + mOnDragDropListeners.remove(listener); + } + } + +} \ No newline at end of file diff --git a/src/com/android/dialer/list/OnDragDropListener.java b/src/com/android/dialer/list/OnDragDropListener.java new file mode 100644 index 000000000..7f6d1791c --- /dev/null +++ b/src/com/android/dialer/list/OnDragDropListener.java @@ -0,0 +1,41 @@ +package com.android.dialer.list; + + +/** + * Classes that want to receive callbacks in response to drag events should implement this + * interface. + */ +public interface OnDragDropListener { + /** + * Called when a drag is started. + * @param itemIndex Index of the contact on which the drag was triggered + * @param x X-coordinate of the drag event + * @param y Y-coordinate of the drag event + * @param view The contact tile which the drag was started on + */ + public void onDragStarted(int itemIndex, int x, int y, PhoneFavoriteTileView view); + + /** + * Called when a drag is in progress and the user moves the dragged contact to a + * location. + * @param itemIndex Index of the contact in the ListView which is currently being displaced + * by the dragged contact + * @param x X-coordinate of the drag event + * @param y Y-coordinate of the drag event + */ + public void onDragHovered(int itemIndex, int x, int y); + + /** + * Called when a drag is completed (whether by dropping it somewhere or simply by dragging + * the contact off the screen) + * @param x X-coordinate of the drag event + * @param y Y-coordinate of the drag event + */ + public void onDragFinished(int x, int y); + + /** + * Called when a contact has been dropped on the remove view, indicating that the user + * wants to remove this contact. + */ + public void onDroppedOnRemove(); +} \ No newline at end of file diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java index 860f9dc2a..79dbe8c49 100644 --- a/src/com/android/dialer/list/PhoneFavoriteFragment.java +++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java @@ -107,6 +107,10 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen public void onCallNumberDirectly(String phoneNumber); } + public interface HostInterface { + public void setDragDropController(DragDropController controller); + } + private class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks { @Override @@ -279,7 +283,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); mListView.setOnItemSwipeListener(mContactTileAdapter); - mListView.setOnDragDropListener(mContactTileAdapter); + mListView.getDragDropController().addOnDragDropListener(mContactTileAdapter); final ImageView dragShadowOverlay = (ImageView) mParentView.findViewById(R.id.contact_tile_drag_shadow_overlay); @@ -347,6 +351,15 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen + " must implement OnShowAllContactsListener"); } + try { + OnDragDropListener listener = (OnDragDropListener) activity; + mListView.getDragDropController().addOnDragDropListener(listener); + ((HostInterface) activity).setDragDropController(mListView.getDragDropController()); + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnDragDropListener and HostInterface"); + } + // Use initLoader() instead of restartLoader() to refraining unnecessary reload. // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will // be called, on which we'll check if "all" contacts should be reloaded again or not. diff --git a/src/com/android/dialer/list/PhoneFavoriteListView.java b/src/com/android/dialer/list/PhoneFavoriteListView.java index 99979dd53..adda3cfd0 100644 --- a/src/com/android/dialer/list/PhoneFavoriteListView.java +++ b/src/com/android/dialer/list/PhoneFavoriteListView.java @@ -29,7 +29,6 @@ import android.view.DragEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; @@ -44,7 +43,8 @@ import com.android.dialer.list.SwipeHelper.SwipeHelperCallback; * - Swiping, which is borrowed from packages/apps/UnifiedEmail (com.android.mail.ui.Swipeable) * - Drag and drop */ -public class PhoneFavoriteListView extends ListView implements SwipeHelperCallback { +public class PhoneFavoriteListView extends ListView implements SwipeHelperCallback, + OnDragDropListener { public static final String LOG_TAG = PhoneFavoriteListView.class.getSimpleName(); @@ -52,7 +52,6 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba private boolean mEnableSwipe = true; private OnItemGestureListener mOnItemGestureListener; - private OnDragDropListener mOnDragDropListener; private float mDensityScale; private float mTouchSlop; @@ -81,6 +80,8 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba private int mDragShadowLeft; private int mDragShadowTop; + private DragDropController mDragDropController = new DragDropController(); + private final float DRAG_SHADOW_ALPHA = 0.7f; /** @@ -130,6 +131,7 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, mDensityScale, mTouchSlop); setItemsCanFocus(true); + mDragDropController.addOnDragDropListener(this); } @Override @@ -156,10 +158,10 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba mOnItemGestureListener = listener; } - public void setOnDragDropListener(OnDragDropListener listener) { - mOnDragDropListener = listener; - } - + /** + * TODO: This is all swipe to remove code (nothing to do with drag to remove). This should + * be cleaned up and removed once drag to remove becomes the only way to remove contacts. + */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { @@ -232,6 +234,10 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba requestDisallowInterceptTouchEvent(true); } + /** + * End of swipe-to-remove code + */ + @Override public boolean dispatchDragEvent(DragEvent event) { final int action = event.getAction(); @@ -239,13 +245,34 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba final int eY = (int) event.getY(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: - if (!handleDragStarted(mTouchDownForDragStartX, mTouchDownForDragStartY)) { + final int[] coordinates = new int[2]; + getLocationOnScreen(coordinates); + // Calculate the X and Y coordinates of the drag event relative to the view + final int viewX = eX - coordinates[0]; + final int viewY = eY - coordinates[1]; + final View child = getViewAtPosition(viewX, viewY); + + if (!(child instanceof ContactTileRow)) { + // Bail early. + return false; + } + + final ContactTileRow tile = (ContactTileRow) child; + + // Disable drag and drop if there is a contact that has been swiped and is currently + // in the pending remove state + if (tile.getTileAdapter().hasPotentialRemoveEntryIndex()) { + return false; + } + + if (!mDragDropController.handleDragStarted(viewX, viewY, tile)) { return false; - }; + } break; case DragEvent.ACTION_DRAG_LOCATION: mLastDragY = eY; - handleDragHovered(eX, eY); + final View view = getViewAtPosition(eX, eY); + mDragDropController.handleDragHovered(eX, eY, view); // Kick off {@link #mScrollHandler} if it's not started yet. if (!mIsDragScrollerRunning && // And if the distance traveled while dragging exceeds the touch slop @@ -268,13 +295,13 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba mIsDragScrollerRunning = false; // Either a successful drop or it's ended with out drop. if (action == DragEvent.ACTION_DROP || action == DragEvent.ACTION_DRAG_ENDED) { - handleDragFinished(eX, eY); + mDragDropController.handleDragFinished(eX, eY, false); } break; default: break; } - // This ListView will consumer the drag events on behalf of its children. + // This ListView will consume the drag events on behalf of its children. return true; } @@ -303,69 +330,48 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba } } - /** - * @return True if the drag is started. - */ - private boolean handleDragStarted(int x, int y) { - final View child = getViewAtPosition(x, y); - if (!(child instanceof ContactTileRow)) { - // Bail early. - return false; - } - - final ContactTileRow tile = (ContactTileRow) child; + public DragDropController getDragDropController() { + return mDragDropController; + } - if (tile.getTileAdapter().hasPotentialRemoveEntryIndex()) { - return false; + @Override + public void onDragStarted(int itemIndex, int x, int y, PhoneFavoriteTileView tileView) { + if (mDragShadowOverlay == null) { + return; } - final int itemIndex = tile.getItemIndex(x, y); - if (itemIndex != -1 && mOnDragDropListener != null) { - final PhoneFavoriteTileView tileView = - (PhoneFavoriteTileView) tile.getViewAtPosition(x, y); - if (mDragShadowOverlay == null) { - return false; - } - - mDragShadowOverlay.clearAnimation(); - mDragShadowBitmap = createDraggedChildBitmap(tileView); - if (mDragShadowBitmap == null) { - return false; - } - - if (tileView instanceof PhoneFavoriteRegularRowView) { - mDragShadowLeft = tile.getLeft(); - mDragShadowTop = tile.getTop(); - } else { - // Square tile is relative to the contact tile, - // and contact tile is relative to this list view. - mDragShadowLeft = tileView.getLeft() + tileView.getParentRow().getLeft(); - mDragShadowTop = tileView.getTop() + tileView.getParentRow().getTop(); - } - - mDragShadowOverlay.setImageBitmap(mDragShadowBitmap); - mDragShadowOverlay.setVisibility(VISIBLE); - mDragShadowOverlay.setAlpha(DRAG_SHADOW_ALPHA); - - mDragShadowOverlay.setX(mDragShadowLeft); - mDragShadowOverlay.setY(mDragShadowTop); + mDragShadowOverlay.clearAnimation(); + mDragShadowBitmap = createDraggedChildBitmap(tileView); + if (mDragShadowBitmap == null) { + return; + } - // x and y passed in are the coordinates of where the user has touched down, calculate - // the offset to the top left coordinate of the dragged child. This will be used for - // drawing the drag shadow. - mTouchOffsetToChildLeft = x - mDragShadowLeft; - mTouchOffsetToChildTop = y - mDragShadowTop; + if (tileView instanceof PhoneFavoriteRegularRowView) { + mDragShadowLeft = tileView.getParentRow().getLeft(); + mDragShadowTop = tileView.getParentRow().getTop(); + } else { + // Square tile is relative to the contact tile, + // and contact tile is relative to this list view. + mDragShadowLeft = tileView.getLeft() + tileView.getParentRow().getLeft(); + mDragShadowTop = tileView.getTop() + tileView.getParentRow().getTop(); + } - // invalidate to trigger a redraw of the drag shadow. - invalidate(); + mDragShadowOverlay.setImageBitmap(mDragShadowBitmap); + mDragShadowOverlay.setVisibility(VISIBLE); + mDragShadowOverlay.setAlpha(DRAG_SHADOW_ALPHA); - mOnDragDropListener.onDragStarted(itemIndex); - } + mDragShadowOverlay.setX(mDragShadowLeft); + mDragShadowOverlay.setY(mDragShadowTop); - return true; + // x and y passed in are the coordinates of where the user has touched down, + // calculate the offset to the top left coordinate of the dragged child. This + // will be used for drawing the drag shadow. + mTouchOffsetToChildLeft = x - mDragShadowLeft; + mTouchOffsetToChildTop = y - mDragShadowTop; } - private void handleDragHovered(int x, int y) { + @Override + public void onDragHovered(int itemIndex, int x, int y) { // Update the drag shadow location. mDragShadowLeft = x - mTouchOffsetToChildLeft; mDragShadowTop = y - mTouchOffsetToChildTop; @@ -374,21 +380,10 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba mDragShadowOverlay.setX(mDragShadowLeft); mDragShadowOverlay.setY(mDragShadowTop); } - - final View child = getViewAtPosition(x, y); - if (!(child instanceof ContactTileRow)) { - // Bail early. - return; - } - - final ContactTileRow tile = (ContactTileRow) child; - final int itemIndex = tile.getItemIndex(x, y); - if (itemIndex != -1 && mOnDragDropListener != null) { - mOnDragDropListener.onDragHovered(itemIndex); - } } - private void handleDragFinished(int x, int y) { + @Override + public void onDragFinished(int x, int y) { // Update the drag shadow location. mDragShadowLeft = x - mTouchOffsetToChildLeft; mDragShadowTop = y - mTouchOffsetToChildTop; @@ -400,12 +395,11 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba .setListener(mDragShadowOverAnimatorListener) .start(); } - - if (mOnDragDropListener != null) { - mOnDragDropListener.onDragFinished(); - } } + @Override + public void onDroppedOnRemove() {} + private Bitmap createDraggedChildBitmap(View view) { view.setDrawingCacheEnabled(true); final Bitmap cache = view.getDrawingCache(); @@ -425,10 +419,4 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba return bitmap; } - - public interface OnDragDropListener { - public void onDragStarted(int itemIndex); - public void onDragHovered(int itemIndex); - public void onDragFinished(); - } } diff --git a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java index dff68b2be..45cc5a371 100644 --- a/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java +++ b/src/com/android/dialer/list/PhoneFavoritesTileAdapter.java @@ -59,7 +59,7 @@ import java.util.PriorityQueue; * */ public class PhoneFavoritesTileAdapter extends BaseAdapter implements - SwipeHelper.OnItemGestureListener, PhoneFavoriteListView.OnDragDropListener { + SwipeHelper.OnItemGestureListener, OnDragDropListener { private static final String TAG = PhoneFavoritesTileAdapter.class.getSimpleName(); private static final boolean DEBUG = false; @@ -1204,24 +1204,38 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements } @Override - public void onDragStarted(int itemIndex) { + public void onDragStarted(int itemIndex, int x, int y, PhoneFavoriteTileView view) { setInDragging(true); popContactEntry(itemIndex); } @Override - public void onDragHovered(int itemIndex) { + public void onDragHovered(int itemIndex, int x, int y) { if (mInDragging && mDragEnteredEntryIndex != itemIndex && isIndexInBound(itemIndex) && - itemIndex < PIN_LIMIT) { + itemIndex < PIN_LIMIT && + itemIndex >= 0) { markDropArea(itemIndex); } } @Override - public void onDragFinished() { + public void onDragFinished(int x, int y) { setInDragging(false); - handleDrop(); + // A contact has been dragged to the RemoveView in order to be unstarred, so simply wait + // for the new contact cursor which will cause the UI to be refreshed without the unstarred + // contact. + if (!mAwaitingRemove) { + handleDrop(); + } + } + + @Override + public void onDroppedOnRemove() { + if (mDraggedEntry != null) { + unstarAndUnpinContact(mDraggedEntry.lookupKey); + mAwaitingRemove = true; + } } } diff --git a/src/com/android/dialer/list/RemoveView.java b/src/com/android/dialer/list/RemoveView.java new file mode 100644 index 000000000..16942fe96 --- /dev/null +++ b/src/com/android/dialer/list/RemoveView.java @@ -0,0 +1,90 @@ +package com.android.dialer.list; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.DragEvent; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.dialer.R; + +public class RemoveView extends LinearLayout { + + DragDropController mDragDropController; + TextView mRemoveText; + ImageView mRemoveIcon; + int mUnhighlightedColor; + int mHighlightedColor; + Drawable mRemoveDrawable; + Drawable mRemoveHighlightedDrawable; + + public RemoveView(Context context) { + super(context); + } + + public RemoveView(Context context, AttributeSet attrs) { + this(context, attrs, -1); + } + + public RemoveView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onFinishInflate() { + mRemoveText = (TextView) findViewById(R.id.remove_view_text); + mRemoveIcon = (ImageView) findViewById(R.id.remove_view_icon); + final Resources r = getResources(); + mUnhighlightedColor = r.getColor(R.color.remove_text_color); + mHighlightedColor = r.getColor(R.color.remove_highlighted_text_color); + mRemoveDrawable = r.getDrawable(R.drawable.ic_remove); + mRemoveHighlightedDrawable = r.getDrawable(R.drawable.ic_remove_highlight); + } + + public void setDragDropController(DragDropController controller) { + mDragDropController = controller; + } + + @Override + public boolean dispatchDragEvent(DragEvent event) { + final int action = event.getAction(); + switch (action) { + case DragEvent.ACTION_DRAG_ENTERED: + setAppearanceHighlighted(); + break; + case DragEvent.ACTION_DRAG_EXITED: + setAppearanceNormal(); + break; + case DragEvent.ACTION_DRAG_LOCATION: + if (mDragDropController != null) { + mDragDropController.handleDragHovered((int) event.getX(), + // the true y-coordinate of the event with respect to the listview is + // offset by the height of the remove view + (int) event.getY() - getHeight(), null); + } + break; + case DragEvent.ACTION_DROP: + if (mDragDropController != null) { + mDragDropController.handleDragFinished((int) event.getX(), (int) event.getY(), true); + } + setAppearanceNormal(); + break; + } + return true; + } + + private void setAppearanceNormal() { + mRemoveText.setTextColor(mUnhighlightedColor); + mRemoveIcon.setImageDrawable(mRemoveDrawable); + invalidate(); + } + + private void setAppearanceHighlighted() { + mRemoveText.setTextColor(mHighlightedColor); + mRemoveIcon.setImageDrawable(mRemoveHighlightedDrawable); + invalidate(); + } +} -- cgit v1.2.3