Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f7eada8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add implementation of homepage swipe to dismiss."

parents d54c74eb eeea6676
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ public class ContextualCard {
    private final Drawable mIconDrawable;
    @LayoutRes
    private final int mViewType;
    private final boolean mIsPendingDismiss;

    public String getName() {
        return mName;
@@ -156,6 +157,10 @@ public class ContextualCard {
        return mViewType;
    }

    public boolean isPendingDismiss() {
        return mIsPendingDismiss;
    }

    public Builder mutate() {
        return mBuilder;
    }
@@ -181,6 +186,7 @@ public class ContextualCard {
        mIconDrawable = builder.mIconDrawable;
        mIsLargeCard = builder.mIsLargeCard;
        mViewType = builder.mViewType;
        mIsPendingDismiss = builder.mIsPendingDismiss;
    }

    ContextualCard(Cursor c) {
@@ -226,6 +232,8 @@ public class ContextualCard {
        mBuilder.setIconDrawable(mIconDrawable);
        mViewType = getViewTypeByCardType(mCardType);
        mBuilder.setViewType(mViewType);
        mIsPendingDismiss = false;
        mBuilder.setIsPendingDismiss(mIsPendingDismiss);
    }

    @Override
@@ -277,6 +285,7 @@ public class ContextualCard {
        private boolean mIsLargeCard;
        @LayoutRes
        private int mViewType;
        private boolean mIsPendingDismiss;

        public Builder setName(String name) {
            mName = name;
@@ -373,6 +382,11 @@ public class ContextualCard {
            return this;
        }

        public Builder setIsPendingDismiss(boolean isPendingDismiss) {
            mIsPendingDismiss = isPendingDismiss;
            return this;
        }

        public ContextualCard build() {
            return new ContextualCard(this);
        }
+6 −3
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate.DismissalItemTouchHelperListener;
import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;

import java.util.ArrayList;
@@ -36,7 +36,7 @@ import java.util.List;
import java.util.Map;

public class ContextualCardsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
        implements ContextualCardUpdateListener, DismissalItemTouchHelperListener {
        implements ContextualCardUpdateListener, SwipeDismissalDelegate.Listener {
    static final int SPAN_COUNT = 2;

    private static final String TAG = "ContextualCardsAdapter";
@@ -140,6 +140,9 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter<RecyclerView.Vi

    @Override
    public void onSwiped(int position) {

        final ContextualCard card = mContextualCards.get(position).mutate()
                .setIsPendingDismiss(true).build();
        mContextualCards.set(position, card);
        notifyItemChanged(position);
    }
}
+6 −10
Original line number Diff line number Diff line
@@ -135,23 +135,19 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
                // Deferred setup is never dismissible.
                break;
            case VIEW_TYPE_HALF_WIDTH:
                initDismissalActions(holder, card, R.id.content);
                initDismissalActions(holder, card);
                break;
            default:
                initDismissalActions(holder, card, R.id.slice_view);
        }
                initDismissalActions(holder, card);
        }

    private void initDismissalActions(RecyclerView.ViewHolder holder, ContextualCard card,
            int initialViewId) {
        // initialView is the first view in the ViewFlipper.
        final View initialView = holder.itemView.findViewById(initialViewId);
        initialView.setOnLongClickListener(v -> {
        if (card.isPendingDismiss()) {
            flipCardToDismissalView(holder);
            mFlippedCardSet.add(holder);
            return true;
        });
        }
    }

    private void initDismissalActions(RecyclerView.ViewHolder holder, ContextualCard card) {
        final Button btnKeep = holder.itemView.findViewById(R.id.keep);
        btnKeep.setOnClickListener(v -> {
            mFlippedCardSet.remove(holder);
+42 −4
Original line number Diff line number Diff line
@@ -18,32 +18,63 @@ package com.android.settings.homepage.contextualcards.slices;

import android.content.Context;
import android.graphics.Canvas;
import android.widget.ViewFlipper;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.android.settings.R;
import com.android.settings.homepage.contextualcards.ContextualCard;

public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {

    private static final String TAG = "DismissItemTouchHelper";

    public interface DismissalItemTouchHelperListener {
    public interface Listener {
        void onSwiped(int position);
    }

    private final Context mContext;
    private final DismissalItemTouchHelperListener mListener;
    private final SwipeDismissalDelegate.Listener mListener;

    public SwipeDismissalDelegate(Context context, DismissalItemTouchHelperListener listener) {
    public SwipeDismissalDelegate(Context context, SwipeDismissalDelegate.Listener listener) {
        mContext = context;
        mListener = listener;
    }

    /**
     * Determine whether the ability to drag or swipe should be enabled or not.
     *
     * Only allow swipe on {@link ContextualCard} built with view type
     * {@link SliceContextualCardRenderer#VIEW_TYPE_FULL_WIDTH} or
     * {@link SliceContextualCardRenderer#VIEW_TYPE_HALF_WIDTH}.
     *
     * When the dismissal view is displayed, the swipe will also be disabled.
     */
    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView,
            @NonNull RecyclerView.ViewHolder viewHolder) {
        switch (viewHolder.getItemViewType()) {
            case SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH:
            case SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH:
                //TODO(b/129438972): Convert this to a regular view.
                final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);

                // As we are using ViewFlipper to switch between the initial view and
                // dismissal view, here we are making sure the current displayed view is the
                // initial view of either slice full card or half card, and only allow swipe on
                // these two types.
                if (viewFlipper.getCurrentView().getId() != getInitialViewId(viewHolder)) {
                    // Disable swiping when we are in the dismissal view
                    return 0;
                }
                return makeMovementFlags(0 /*dragFlags*/,
                        ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT /*swipeFlags*/);
            default:
                return 0;
        }
    }

    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView,
@@ -63,4 +94,11 @@ public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
            boolean isCurrentlyActive) {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }

    private int getInitialViewId(RecyclerView.ViewHolder viewHolder) {
        if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
            return R.id.content;
        }
        return R.id.slice_view;
    }
}
 No newline at end of file
+8 −31
Original line number Diff line number Diff line
@@ -16,13 +16,11 @@

package com.android.settings.homepage.contextualcards.slices;

import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import android.app.Activity;
@@ -118,34 +116,25 @@ public class SliceContextualCardRendererTest {
    }

    @Test
    public void longClick_shouldFlipCard() {
    public void bindView_isPendingDismiss_shouldFlipToDismissalView() {
        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
        final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
        final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
        final ContextualCard card = buildContextualCard(
                TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();

        card.performLongClick();
        mRenderer.bindView(viewHolder, card);

        assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
    }

    @Test
    public void longClick_deferredSetupCard_shouldNotBeClickable() {
        final RecyclerView.ViewHolder viewHolder = getDeferredSetupViewHolder();
        final View contentView = viewHolder.itemView.findViewById(R.id.content);
        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));

        assertThat(contentView.isLongClickable()).isFalse();
    }

    @Test
    public void longClick_shouldAddViewHolderToSet() {
    public void bindView_isPendingDismiss_shouldAddViewHolderToSet() {
        final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
        final View card = viewHolder.itemView.findViewById(R.id.slice_view);
        mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
        final ContextualCard card = buildContextualCard(
                TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();

        card.performLongClick();
        mRenderer.bindView(viewHolder, card);

        assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
    }
@@ -232,18 +221,6 @@ public class SliceContextualCardRendererTest {
        return mRenderer.createViewHolder(view, VIEW_TYPE_FULL_WIDTH);
    }

    private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
        final RecyclerView recyclerView = new RecyclerView(mActivity);
        recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
        final View view = LayoutInflater.from(mActivity).inflate(VIEW_TYPE_DEFERRED_SETUP,
                recyclerView, false);
        final RecyclerView.ViewHolder viewHolder = spy(
                mRenderer.createViewHolder(view, VIEW_TYPE_DEFERRED_SETUP));
        doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();

        return viewHolder;
    }

    private ContextualCard buildContextualCard(Uri sliceUri) {
        return new ContextualCard.Builder()
                .setName("test_name")
Loading