diff options
author | yueg <yueg@google.com> | 2018-06-19 16:54:38 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-06-19 16:55:54 -0700 |
commit | 406de13ab4326bbedae0262709a004da2211d04c (patch) | |
tree | 5e9f525d8dc782b1ba778b191184d0960617bcc9 | |
parent | acfab4ed674bb7b0154373c626ce494f37629509 (diff) |
Drag favorite to remove
Test: RemoveViewHolderTest, SpeedDialAdapterTest
PiperOrigin-RevId: 201266033
Change-Id: Ie7ed9bac8ad9c7bbc35c351409b629e3fbad3de8
10 files changed, 381 insertions, 84 deletions
diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml index b47806ece..5cb457ec9 100644 --- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml +++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml @@ -19,7 +19,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/root_layout" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:clipChildren="false" + android:clipToPadding="false"> <!-- MainToolbar --> <include @@ -33,13 +35,17 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/toolbar" - android:layout_above="@+id/bottom_nav_bar"> + android:layout_above="@+id/bottom_nav_bar" + android:clipChildren="false" + android:clipToPadding="false"> <!-- Holds SpeedDial, Call Log, Contacts, Voicemail and Search fragments --> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" - android:layout_height="match_parent"/> + android:layout_height="match_parent" + android:clipChildren="false" + android:clipToPadding="false"/> <FrameLayout android:id="@+id/search_fragment_container" diff --git a/java/com/android/dialer/speeddial/FavoritesViewHolder.java b/java/com/android/dialer/speeddial/FavoritesViewHolder.java index f06672d8d..600c8c734 100644 --- a/java/com/android/dialer/speeddial/FavoritesViewHolder.java +++ b/java/com/android/dialer/speeddial/FavoritesViewHolder.java @@ -46,6 +46,8 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder private final TextView phoneType; private final FrameLayout videoCallIcon; + private final FrameLayout avatarContainer; + private SpeedDialUiItem speedDialUiItem; public FavoritesViewHolder(View view, ItemTouchHelper helper, FavoriteContactsListener listener) { @@ -54,6 +56,7 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder nameView = view.findViewById(R.id.name); phoneType = view.findViewById(R.id.phone_type); videoCallIcon = view.findViewById(R.id.video_call_container); + avatarContainer = view.findViewById(R.id.avatar_container); view.setOnClickListener(this); view.setOnLongClickListener(this); view.setOnTouchListener( @@ -117,6 +120,15 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder listener.onTouchFinished(closeContextMenu); } + FrameLayout getAvatarContainer() { + return avatarContainer; + } + + void onSelectedChanged(boolean selected) { + nameView.setVisibility(selected ? View.GONE : View.VISIBLE); + phoneType.setVisibility(selected ? View.GONE : View.VISIBLE); + } + /** Listener/callback for {@link FavoritesViewHolder} actions. */ public interface FavoriteContactsListener { @@ -131,5 +143,8 @@ public class FavoritesViewHolder extends RecyclerView.ViewHolder /** Called when the user is no longer touching the favorite contact. */ void onTouchFinished(boolean closeContextMenu); + + /** Called when the user drag the favorite to remove. */ + void onRequestRemove(SpeedDialUiItem speedDialUiItem); } } diff --git a/java/com/android/dialer/speeddial/RemoveViewHolder.java b/java/com/android/dialer/speeddial/RemoveViewHolder.java new file mode 100644 index 000000000..998e1ae2f --- /dev/null +++ b/java/com/android/dialer/speeddial/RemoveViewHolder.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * 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. + */ + +package com.android.dialer.speeddial; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.View.OnClickListener; + +/** ViewHolder for headers in {@link SpeedDialFragment}. */ +public class RemoveViewHolder extends RecyclerView.ViewHolder implements OnClickListener { + + private final View removeViewContent; + + RemoveViewHolder(View view) { + super(view); + removeViewContent = view; + } + + void show() { + removeViewContent.setVisibility(View.VISIBLE); + removeViewContent.setAlpha(0); + removeViewContent.animate().alpha(1).start(); + } + + void hide() { + removeViewContent.setVisibility(View.INVISIBLE); + removeViewContent.setAlpha(1); + removeViewContent.animate().alpha(0).start(); + } + + @Override + public void onClick(View v) { + // Not clickable + } +} diff --git a/java/com/android/dialer/speeddial/SpeedDialAdapter.java b/java/com/android/dialer/speeddial/SpeedDialAdapter.java index a382b1a6b..ff52a0745 100644 --- a/java/com/android/dialer/speeddial/SpeedDialAdapter.java +++ b/java/com/android/dialer/speeddial/SpeedDialAdapter.java @@ -21,6 +21,7 @@ import android.content.Context; import android.os.Build.VERSION_CODES; import android.support.annotation.IntDef; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.GridLayoutManager.SpanSizeLookup; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; @@ -28,6 +29,8 @@ import android.support.v7.widget.helper.ItemTouchHelper; import android.util.ArrayMap; import android.view.LayoutInflater; import android.view.ViewGroup; +import android.view.animation.AnticipateInterpolator; +import android.widget.FrameLayout; import com.android.dialer.common.Assert; import com.android.dialer.speeddial.FavoritesViewHolder.FavoriteContactsListener; import com.android.dialer.speeddial.HeaderViewHolder.SpeedDialHeaderListener; @@ -58,13 +61,20 @@ import java.util.Map; public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ItemTouchHelperAdapter { + private static final int NON_CONTACT_ITEM_NUMBER_BEFORE_FAVORITES = 2; + private static final int NON_CONTACT_ITEM_NUMBER_BEFORE_SUGGESTION = 3; + + private static final float IN_REMOVE_VIEW_SCALE = 0.5f; + private static final float IN_REMOVE_VIEW_ALPHA = 0.5f; + @Retention(RetentionPolicy.SOURCE) @IntDef({RowType.STARRED_HEADER, RowType.SUGGESTION_HEADER, RowType.STARRED, RowType.SUGGESTION}) @interface RowType { - int STARRED_HEADER = 0; - int SUGGESTION_HEADER = 1; - int STARRED = 2; - int SUGGESTION = 3; + int REMOVE_VIEW = 0; + int STARRED_HEADER = 1; + int SUGGESTION_HEADER = 2; + int STARRED = 3; + int SUGGESTION = 4; } private final Context context; @@ -78,6 +88,9 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi // Needed for FavoriteViewHolder private ItemTouchHelper itemTouchHelper; + private RemoveViewHolder removeViewHolder; + private FavoritesViewHolder draggingFavoritesViewHolder; + public SpeedDialAdapter( Context context, FavoriteContactsListener favoritesListener, @@ -111,6 +124,11 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi case RowType.SUGGESTION_HEADER: return new HeaderViewHolder( inflater.inflate(R.layout.speed_dial_header_layout, parent, false), headerListener); + case RowType.REMOVE_VIEW: + removeViewHolder = + new RemoveViewHolder( + inflater.inflate(R.layout.favorite_remove_view_layout, parent, false)); + return removeViewHolder; default: throw Assert.createIllegalStateFailException("Invalid viewType: " + viewType); } @@ -128,10 +146,17 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi ((HeaderViewHolder) holder).showAddButton(false); return; case RowType.STARRED: - ((FavoritesViewHolder) holder).bind(context, speedDialUiItems.get(position - 1)); + ((FavoritesViewHolder) holder).bind(context, speedDialUiItems.get(position - 2)); + // Removed item might come back + FrameLayout avatarContainer = ((FavoritesViewHolder) holder).getAvatarContainer(); + avatarContainer.setScaleX(1); + avatarContainer.setScaleY(1); + avatarContainer.setAlpha(1); break; case RowType.SUGGESTION: - ((SuggestionViewHolder) holder).bind(context, speedDialUiItems.get(position - 2)); + ((SuggestionViewHolder) holder).bind(context, speedDialUiItems.get(position - 3)); + break; + case RowType.REMOVE_VIEW: break; default: throw Assert.createIllegalStateFailException("Invalid view holder: " + holder); @@ -153,20 +178,25 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi } return Boolean.compare(o2.isStarred(), o1.isStarred()); }); + updatePositionToRowTypeMap(); + } + + private void updatePositionToRowTypeMap() { positionToRowTypeMap.clear(); if (speedDialUiItems.isEmpty()) { return; } + positionToRowTypeMap.put(0, RowType.REMOVE_VIEW); // Show the add favorites even if there are no favorite contacts - positionToRowTypeMap.put(0, RowType.STARRED_HEADER); - int positionOfSuggestionHeader = 1; + positionToRowTypeMap.put(1, RowType.STARRED_HEADER); + int positionOfSuggestionHeader = NON_CONTACT_ITEM_NUMBER_BEFORE_FAVORITES; for (int i = 0; i < speedDialUiItems.size(); i++) { if (speedDialUiItems.get(i).isStarred()) { - positionToRowTypeMap.put(i + 1, RowType.STARRED); // +1 for the header + positionToRowTypeMap.put(i + NON_CONTACT_ITEM_NUMBER_BEFORE_FAVORITES, RowType.STARRED); positionOfSuggestionHeader++; } else { - positionToRowTypeMap.put(i + 2, RowType.SUGGESTION); // +2 for both headers + positionToRowTypeMap.put(i + NON_CONTACT_ITEM_NUMBER_BEFORE_SUGGESTION, RowType.SUGGESTION); } } if (!speedDialUiItems.get(speedDialUiItems.size() - 1).isStarred()) { @@ -189,6 +219,7 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi case RowType.SUGGESTION: case RowType.STARRED_HEADER: case RowType.SUGGESTION_HEADER: + case RowType.REMOVE_VIEW: return 3; // span the whole screen case RowType.STARRED: return 1; // span 1/3 of the screen @@ -202,15 +233,88 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi @Override public void onItemMove(int fromPosition, int toPosition) { + if (toPosition == 0) { + // drop to removeView + return; + } // fromPosition/toPosition correspond to adapter position, which is off by 1 from the list // position b/c of the favorites header. So subtract 1 here. - speedDialUiItems.add(toPosition - 1, speedDialUiItems.remove(fromPosition - 1)); + speedDialUiItems.add(toPosition - 2, speedDialUiItems.remove(fromPosition - 2)); notifyItemMoved(fromPosition, toPosition); } @Override public boolean canDropOver(ViewHolder target) { - return target instanceof FavoritesViewHolder; + return target instanceof FavoritesViewHolder || target instanceof RemoveViewHolder; + } + + @Override + public void onSelectedChanged(@Nullable ViewHolder viewHolder, int actionState) { + switch (actionState) { + case ItemTouchHelper.ACTION_STATE_DRAG: + if (viewHolder != null) { + draggingFavoritesViewHolder = (FavoritesViewHolder) viewHolder; + draggingFavoritesViewHolder.onSelectedChanged(true); + removeViewHolder.show(); + } + break; + case ItemTouchHelper.ACTION_STATE_IDLE: + // viewHolder is null in this case + if (draggingFavoritesViewHolder != null) { + draggingFavoritesViewHolder.onSelectedChanged(false); + draggingFavoritesViewHolder = null; + removeViewHolder.hide(); + } + break; + default: + break; + } + } + + @Override + public void enterRemoveView() { + if (draggingFavoritesViewHolder != null) { + draggingFavoritesViewHolder + .getAvatarContainer() + .animate() + .scaleX(IN_REMOVE_VIEW_SCALE) + .scaleY(IN_REMOVE_VIEW_SCALE) + .alpha(IN_REMOVE_VIEW_ALPHA) + .start(); + } + } + + @Override + public void leaveRemoveView() { + if (draggingFavoritesViewHolder != null) { + draggingFavoritesViewHolder + .getAvatarContainer() + .animate() + .scaleX(1) + .scaleY(1) + .alpha(1) + .start(); + } + } + + @Override + public void dropOnRemoveView(ViewHolder fromViewHolder) { + if (!(fromViewHolder instanceof FavoritesViewHolder)) { + return; + } + int fromPosition = fromViewHolder.getAdapterPosition(); + + SpeedDialUiItem removedItem = speedDialUiItems.remove(fromPosition - 2); + favoritesListener.onRequestRemove(removedItem); + ((FavoritesViewHolder) fromViewHolder) + .getAvatarContainer() + .animate() + .scaleX(0) + .scaleY(0) + .alpha(0) + .setInterpolator(new AnticipateInterpolator()) + .start(); + updatePositionToRowTypeMap(); } public void setItemTouchHelper(ItemTouchHelper itemTouchHelper) { diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index c48eb8d68..aabf28bcb 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -151,9 +151,9 @@ public class SpeedDialFragment extends Fragment { new SpeedDialFavoritesListener( getActivity(), getChildFragmentManager(), - new SpeedDialContextMenuItemListener( - getActivity(), new UpdateSpeedDialAdapterListener(), speedDialLoaderListener), - layoutManager); + layoutManager, + new UpdateSpeedDialAdapterListener(), + speedDialLoaderListener); adapter = new SpeedDialAdapter(getContext(), favoritesListener, suggestedListener, headerListener); layoutManager.setSpanSizeLookup(adapter.getSpanSizeLookup()); @@ -339,20 +339,26 @@ public class SpeedDialFragment extends Fragment { private final FragmentActivity activity; private final FragmentManager childFragmentManager; - private final ContextMenuItemListener contextMenuListener; private final SpeedDialLayoutManager layoutManager; + private final UpdateSpeedDialAdapterListener updateAdapterListener; + private final SupportUiListener<ImmutableList<SpeedDialUiItem>> speedDialLoaderListener; + + private final SpeedDialContextMenuItemListener speedDialContextMenuItemListener = + new SpeedDialContextMenuItemListener(); private ContextMenu contextMenu; SpeedDialFavoritesListener( FragmentActivity activity, FragmentManager childFragmentManager, - ContextMenuItemListener contextMenuListener, - SpeedDialLayoutManager layoutManager) { + SpeedDialLayoutManager layoutManager, + UpdateSpeedDialAdapterListener updateAdapterListener, + SupportUiListener<ImmutableList<SpeedDialUiItem>> speedDialLoaderListener) { this.activity = activity; this.childFragmentManager = childFragmentManager; - this.contextMenuListener = contextMenuListener; this.layoutManager = layoutManager; + this.updateAdapterListener = updateAdapterListener; + this.speedDialLoaderListener = speedDialLoaderListener; } @Override @@ -384,7 +390,8 @@ public class SpeedDialFragment extends Fragment { @Override public void showContextMenu(View view, SpeedDialUiItem speedDialUiItem) { layoutManager.setScrollEnabled(false); - contextMenu = ContextMenu.show(activity, view, contextMenuListener, speedDialUiItem); + contextMenu = + ContextMenu.show(activity, view, speedDialContextMenuItemListener, speedDialUiItem); } @Override @@ -397,12 +404,66 @@ public class SpeedDialFragment extends Fragment { } } - public void hideMenu() { + @Override + public void onRequestRemove(SpeedDialUiItem speedDialUiItem) { + speedDialContextMenuItemListener.removeFavoriteContact(speedDialUiItem); + } + + void hideMenu() { if (contextMenu != null) { contextMenu.hide(); contextMenu = null; } } + + public SpeedDialContextMenuItemListener getSpeedDialContextMenuItemListener() { + return speedDialContextMenuItemListener; + } + + class SpeedDialContextMenuItemListener implements ContextMenuItemListener { + + @Override + public void placeCall(Channel channel) { + if (channel.technology() == Channel.DUO) { + Logger.get(activity) + .logImpression( + DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT); + } + PreCall.start( + activity, + new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) + .setAllowAssistedDial(true) + .setIsVideoCall(channel.isVideoTechnology()) + .setIsDuoCall(channel.technology() == Channel.DUO)); + } + + @Override + public void openSmsConversation(String number) { + activity.startActivity(IntentUtil.getSendSmsIntent(number)); + } + + @Override + public void removeFavoriteContact(SpeedDialUiItem speedDialUiItem) { + speedDialLoaderListener.listen( + activity, + UiItemLoaderComponent.get(activity) + .speedDialUiItemMutator() + .removeSpeedDialUiItem(speedDialUiItem), + updateAdapterListener::updateAdapter, + throwable -> { + throw new RuntimeException(throwable); + }); + } + + @Override + public void openContactInfo(SpeedDialUiItem speedDialUiItem) { + activity.startActivity( + new Intent( + Intent.ACTION_VIEW, + Uri.withAppendedPath( + Contacts.CONTENT_URI, String.valueOf(speedDialUiItem.contactId())))); + } + } } private final class SpeedDialSuggestedListener implements SuggestedContactsListener { @@ -530,63 +591,6 @@ public class SpeedDialFragment extends Fragment { } } - private static final class SpeedDialContextMenuItemListener implements ContextMenuItemListener { - - private final FragmentActivity activity; - private final SupportUiListener<ImmutableList<SpeedDialUiItem>> speedDialLoaderListener; - private final UpdateSpeedDialAdapterListener updateAdapterListener; - - SpeedDialContextMenuItemListener( - FragmentActivity activity, - UpdateSpeedDialAdapterListener updateAdapterListener, - SupportUiListener<ImmutableList<SpeedDialUiItem>> speedDialLoaderListener) { - this.activity = activity; - this.updateAdapterListener = updateAdapterListener; - this.speedDialLoaderListener = speedDialLoaderListener; - } - - @Override - public void placeCall(Channel channel) { - if (channel.technology() == Channel.DUO) { - Logger.get(activity) - .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT); - } - PreCall.start( - activity, - new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) - .setAllowAssistedDial(true) - .setIsVideoCall(channel.isVideoTechnology()) - .setIsDuoCall(channel.technology() == Channel.DUO)); - } - - @Override - public void openSmsConversation(String number) { - activity.startActivity(IntentUtil.getSendSmsIntent(number)); - } - - @Override - public void removeFavoriteContact(SpeedDialUiItem speedDialUiItem) { - speedDialLoaderListener.listen( - activity, - UiItemLoaderComponent.get(activity) - .speedDialUiItemMutator() - .removeSpeedDialUiItem(speedDialUiItem), - updateAdapterListener::updateAdapter, - throwable -> { - throw new RuntimeException(throwable); - }); - } - - @Override - public void openContactInfo(SpeedDialUiItem speedDialUiItem) { - activity.startActivity( - new Intent( - Intent.ACTION_VIEW, - Uri.withAppendedPath( - Contacts.CONTENT_URI, String.valueOf(speedDialUiItem.contactId())))); - } - } - private static final class SpeedDialContactPermissionEmptyViewListener implements OnEmptyViewActionButtonClickedListener { @@ -628,7 +632,7 @@ public class SpeedDialFragment extends Fragment { } /** Listener for when a SpeedDialUiItem is updated. */ - private class UpdateSpeedDialAdapterListener { + class UpdateSpeedDialAdapterListener { void updateAdapter(ImmutableList<SpeedDialUiItem> speedDialUiItems) { onSpeedDialUiItemListLoaded(speedDialUiItems); diff --git a/java/com/android/dialer/speeddial/draghelper/SpeedDialItemTouchHelperCallback.java b/java/com/android/dialer/speeddial/draghelper/SpeedDialItemTouchHelperCallback.java index d1d9f478b..fc963a1a3 100644 --- a/java/com/android/dialer/speeddial/draghelper/SpeedDialItemTouchHelperCallback.java +++ b/java/com/android/dialer/speeddial/draghelper/SpeedDialItemTouchHelperCallback.java @@ -16,7 +16,9 @@ package com.android.dialer.speeddial.draghelper; +import android.graphics.Canvas; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.support.v7.widget.helper.ItemTouchHelper; @@ -26,6 +28,12 @@ public class SpeedDialItemTouchHelperCallback extends ItemTouchHelper.Callback { private final ItemTouchHelperAdapter adapter; + // When dragged item is in removeView, onMove() and onChildDraw() are called in turn. This + // behavior changes when dragged item entering/leaving removeView. The boolean field + // movedOverRemoveView is for onMove() and onChildDraw() to flip. + private boolean movedOverRemoveView; + private boolean inRemoveView; + public SpeedDialItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { this.adapter = adapter; } @@ -64,11 +72,57 @@ public class SpeedDialItemTouchHelperCallback extends ItemTouchHelper.Callback { @NonNull RecyclerView recyclerView, @NonNull ViewHolder viewHolder, @NonNull ViewHolder target) { + if (target.getItemViewType() == 0) { // 0 for RowType.REMOVE_VIEW + movedOverRemoveView = true; + if (!inRemoveView) { + // onMove() first called + adapter.enterRemoveView(); + inRemoveView = true; + } + return false; + } else if (inRemoveView) { + // Move out of removeView fast + inRemoveView = false; + movedOverRemoveView = false; + adapter.leaveRemoveView(); + } adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override + public void onChildDraw( + @NonNull Canvas canvas, + @NonNull RecyclerView recyclerView, + @NonNull ViewHolder viewHolder, + float dx, + float dy, + int i, + boolean isCurrentlyActive) { + if (inRemoveView) { + if (!isCurrentlyActive) { + // View animating back to its original state, which means drop in this case + inRemoveView = false; + adapter.dropOnRemoveView(viewHolder); + } + if (!movedOverRemoveView) { + // when the view is over a droppable target, onMove() will be called before onChildDraw() + // thus if onMove() is not called, it is not over a droppable target. + inRemoveView = false; + adapter.leaveRemoveView(); + } + } + movedOverRemoveView = false; + super.onChildDraw(canvas, recyclerView, viewHolder, dx, dy, i, isCurrentlyActive); + } + + @Override + public void onSelectedChanged(@Nullable ViewHolder viewHolder, int actionState) { + super.onSelectedChanged(viewHolder, actionState); + adapter.onSelectedChanged(viewHolder, actionState); + } + + @Override public void onSwiped(@NonNull ViewHolder viewHolder, int direction) { // No-op since we don't support swiping } @@ -79,5 +133,13 @@ public class SpeedDialItemTouchHelperCallback extends ItemTouchHelper.Callback { void onItemMove(int fromPosition, int toPosition); boolean canDropOver(ViewHolder target); + + void onSelectedChanged(@Nullable ViewHolder viewHolder, int actionState); + + void enterRemoveView(); + + void leaveRemoveView(); + + void dropOnRemoveView(ViewHolder fromViewHolder); } } diff --git a/java/com/android/dialer/speeddial/res/layout/favorite_remove_view_layout.xml b/java/com/android/dialer/speeddial/res/layout/favorite_remove_view_layout.xml new file mode 100644 index 000000000..825658c37 --- /dev/null +++ b/java/com/android/dialer/speeddial/res/layout/favorite_remove_view_layout.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ 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 + --> + +<!-- Sets android:importantForAccessibility="no" to avoid being announced when navigating with + talkback enabled. It will still be announced when user drag or drop contact onto it. + This is required since drag and drop event is only sent to views are visible when drag + starts. --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/favorite_remove_view" + android:layout_width="match_parent" + android:layout_height="@dimen/expanded_search_bar_height" + android:background="?android:attr/colorPrimary" + android:gravity="center" + android:orientation="horizontal" + android:visibility="invisible" + android:contentDescription="@string/speed_dial_remove_favorites" + android:importantForAccessibility="no"> + + <ImageView + android:id="@+id/remove_view_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" + android:src="@drawable/quantum_ic_close_vd_theme_24" + android:tint="?colorIconOnUnthemedDarkBackground"/> + + <TextView + android:id="@+id/remove_view_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/speed_dial_remove_favorites" + android:textColor="?colorTextOnUnthemedDarkBackground" + android:textSize="16sp"/> +</LinearLayout>
\ No newline at end of file diff --git a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml index e289bb794..472f9e951 100644 --- a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml +++ b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml @@ -17,14 +17,17 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/speed_dial_root" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:clipChildren="false" + android:clipToPadding="false"> <android.support.v7.widget.RecyclerView android:id="@+id/speed_dial_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" + android:layout_marginTop="@dimen/expanded_search_bar_height_minus" android:clipToPadding="false" - android:background="?android:attr/colorBackground" + android:background="@android:color/transparent" android:paddingBottom="@dimen/floating_action_button_list_bottom_padding"/> <com.android.dialer.widget.EmptyContentView diff --git a/java/com/android/dialer/speeddial/res/values/dimens.xml b/java/com/android/dialer/speeddial/res/values/dimens.xml index a4cf16c17..624c60dd3 100644 --- a/java/com/android/dialer/speeddial/res/values/dimens.xml +++ b/java/com/android/dialer/speeddial/res/values/dimens.xml @@ -32,4 +32,6 @@ <dimen name="speed_dial_context_menu_x_offset">-24dp</dimen> <dimen name="speed_dial_context_menu_corner_radius">16dp</dimen> <dimen name="disambig_dialog_width">280dp</dimen> + <dimen name="expanded_search_bar_height">64dp</dimen> + <dimen name="expanded_search_bar_height_minus">-64dp</dimen> </resources>
\ No newline at end of file diff --git a/java/com/android/dialer/speeddial/res/values/strings.xml b/java/com/android/dialer/speeddial/res/values/strings.xml index 7f8fed51f..397ec8f5e 100644 --- a/java/com/android/dialer/speeddial/res/values/strings.xml +++ b/java/com/android/dialer/speeddial/res/values/strings.xml @@ -71,4 +71,7 @@ <!-- [CHAR LIMIT=NONE] Shown as an action when the all contacts list is empty --> <string name="speed_dial_no_contacts_action_text">Add favorite</string> + + <!-- Text shown on a dragging target that removes the contact from favorites --> + <string name="speed_dial_remove_favorites">Remove from favorites</string> </resources>
\ No newline at end of file |