Bug 1525796 - Ignore close tab action if user is moving the item; r=JanH

Using an ItemTouchHelper for various motion actions means it will have a
strong reference to that item's layout and prevent it from being destroyed when
the adapter tries to remove it before the animations are finished - the item
will be removed from RecyclerView's Adapter but the item's layout will still
remain on screen.

Differential Revision: https://phabricator.services.mozilla.com/D19673

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Petru-Mugurel Lingurar 2019-02-15 08:18:33 +00:00
parent 2884ad3d7c
commit 5f459bf6b4
4 changed files with 33 additions and 8 deletions

View File

@ -26,13 +26,13 @@ abstract class TabsGridLayout extends TabsLayout {
final int dragDirections = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END;
// A TouchHelper handler for drag and drop and swipe to close.
final TabsTouchHelperCallback callback = new TabsTouchHelperCallback(this, dragDirections, this) {
tabTouchCallback = new TabsTouchHelperCallback(this, dragDirections, this) {
@Override
protected float alphaForItemSwipeDx(float dX, int distanceToAlphaMin) {
return 1f - 2f * Math.abs(dX) / distanceToAlphaMin;
}
};
final ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
final ItemTouchHelper touchHelper = new ItemTouchHelper(tabTouchCallback);
touchHelper.attachToRecyclerView(this);
}

View File

@ -33,6 +33,7 @@ public abstract class TabsLayout extends RecyclerView
private TabsPanel tabsPanel;
private final TabsLayoutAdapter tabsAdapter;
private View emptyView;
protected TabsTouchHelperCallback tabTouchCallback;
public TabsLayout(Context context, AttributeSet attrs, int itemViewLayoutResId) {
super(context, attrs);
@ -46,10 +47,14 @@ public abstract class TabsLayout extends RecyclerView
new Button.OnClickListener() {
@Override
public void onClick(View v) {
// The view here is the close button, which has a reference
// to the parent TabsLayoutItemView in its tag, hence the getTag() call.
TabsLayoutItemView itemView = (TabsLayoutItemView) v.getTag();
closeTab(itemView);
// Bug 1525796: ignore action if the user already interacts with the whole view
// with the help of an ItemTouchHelper
if (tabTouchCallback == null || !tabTouchCallback.isInteractionInProgress()) {
// The view here is the close button, which has a reference
// to the parent TabsLayoutItemView in its tag, hence the getTag() call.
TabsLayoutItemView itemView = (TabsLayoutItemView) v.getTag();
closeTab(itemView);
}
}
});
setAdapter(tabsAdapter);

View File

@ -34,14 +34,14 @@ public class TabsListLayout extends TabsLayout {
final int dragDirections = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
// A TouchHelper handler for drag and drop and swipe to close.
final TabsTouchHelperCallback callback = new TabsTouchHelperCallback(this, dragDirections, this) {
tabTouchCallback = new TabsTouchHelperCallback(this, dragDirections, this) {
@Override
protected float alphaForItemSwipeDx(float dX, int distanceToAlphaMin) {
return Math.max(0.1f,
Math.min(1f, 1f - 2f * Math.abs(dX) / distanceToAlphaMin));
}
};
final ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
final ItemTouchHelper touchHelper = new ItemTouchHelper(tabTouchCallback);
touchHelper.attachToRecyclerView(this);
setItemAnimator(new TabsListLayoutAnimator(ANIMATION_DURATION));

View File

@ -16,6 +16,7 @@ class TabsTouchHelperCallback extends ItemTouchHelper.Callback {
private final @Nullable DismissListener dismissListener;
private final @NonNull DragListener dragListener;
private final int movementFlags;
private boolean isInteractionInProgress;
interface DismissListener {
void onItemDismiss(View view);
@ -96,6 +97,25 @@ class TabsTouchHelperCallback extends ItemTouchHelper.Callback {
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1);
isInteractionInProgress = false;
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (viewHolder != null) {
isInteractionInProgress = true;
}
}
/**
* Get if user started interacting with RecyclerView's items and their animations have not yet completed.
*/
public boolean isInteractionInProgress() {
return isInteractionInProgress;
}
}