From 355945078995f7b313e3554328a9f67d2bb626b1 Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Thu, 20 Dec 2018 00:04:14 +0800 Subject: [PATCH] Implement slice half card To display slice in half width form needs to bind slice, extract the title and the icon from slice, and finally put the title and the icon into half card layout. Bug: 119655434 Test: visual, robotests Change-Id: Ib390f9a45f0ee609eb9e3499bff74136c7616ac3 --- .../slices/SliceHalfCardRendererHelper.java | 41 +++++- .../SliceHalfCardRendererHelperTest.java | 119 ++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java index 2986dbc8fe7..24d654d885c 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java @@ -16,13 +16,24 @@ package com.android.settings.homepage.contextualcards.slices; +import android.app.PendingIntent; import android.content.Context; +import android.util.Log; import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import androidx.slice.Slice; +import androidx.slice.SliceMetadata; +import androidx.slice.core.SliceAction; +import androidx.slice.widget.EventInfo; +import com.android.settings.R; import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; +import com.android.settings.overlay.FeatureFactory; /** * Card renderer helper for {@link ContextualCard} built as slice half card. @@ -37,10 +48,38 @@ class SliceHalfCardRendererHelper { } RecyclerView.ViewHolder createViewHolder(View view) { - return null; + return new HalfCardViewHolder(view); } void bindView(RecyclerView.ViewHolder holder, ContextualCard card, Slice slice) { + final HalfCardViewHolder view = (HalfCardViewHolder) holder; + final SliceMetadata sliceMetadata = SliceMetadata.from(mContext, slice); + final SliceAction primaryAction = sliceMetadata.getPrimaryAction(); + view.icon.setImageDrawable(primaryAction.getIcon().loadDrawable(mContext)); + view.title.setText(primaryAction.getTitle()); + view.content.setOnClickListener(v -> { + try { + primaryAction.getAction().send(); + } catch (PendingIntent.CanceledException e) { + Log.w(TAG, "Failed to start intent " + primaryAction.getTitle()); + } + final ContextualCardFeatureProvider contextualCardFeatureProvider = + FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext); + contextualCardFeatureProvider.logContextualCardClick(card, 0 /* row */, + EventInfo.ACTION_TYPE_CONTENT); + }); + } + static class HalfCardViewHolder extends RecyclerView.ViewHolder { + public final LinearLayout content; + public final ImageView icon; + public final TextView title; + + public HalfCardViewHolder(View itemView) { + super(itemView); + content = itemView.findViewById(R.id.content); + icon = itemView.findViewById(android.R.id.icon); + title = itemView.findViewById(android.R.id.title); + } } } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java new file mode 100644 index 00000000000..c38697e16f1 --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 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.settings.homepage.contextualcards.slices; + +import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH; + +import static com.google.common.truth.Truth.assertThat; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Intent; +import android.net.Uri; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.core.graphics.drawable.IconCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.slice.Slice; +import androidx.slice.SliceProvider; +import androidx.slice.builders.ListBuilder; +import androidx.slice.builders.SliceAction; +import androidx.slice.widget.SliceLiveData; + +import com.android.settings.R; +import com.android.settings.homepage.contextualcards.ContextualCard; +import com.android.settings.homepage.contextualcards.slices.SliceHalfCardRendererHelper.HalfCardViewHolder; +import com.android.settings.intelligence.ContextualCardProto; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class SliceHalfCardRendererHelperTest { + + private static final Uri TEST_SLICE_URI = Uri.parse("content://test/test"); + + private Activity mActivity; + private SliceHalfCardRendererHelper mHelper; + + @Before + public void setUp() { + // Set-up specs for SliceMetadata. + SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + mActivity = Robolectric.buildActivity(Activity.class).create().get(); + mActivity.setTheme(R.style.Theme_Settings_Home); + mHelper = new SliceHalfCardRendererHelper(mActivity); + } + + @Test + public void createViewHolder_shouldAlwaysReturnCustomViewHolder() { + final RecyclerView.ViewHolder viewHolder = getHalfCardViewHolder(); + + assertThat(viewHolder).isInstanceOf(HalfCardViewHolder.class); + } + + @Test + public void bindView_shouldSetTitle() { + final RecyclerView.ViewHolder viewHolder = getHalfCardViewHolder(); + + mHelper.bindView(viewHolder, buildContextualCard(), buildSlice()); + + assertThat(((HalfCardViewHolder) viewHolder).title.getText()).isEqualTo("test_title"); + } + + private RecyclerView.ViewHolder getHalfCardViewHolder() { + final RecyclerView recyclerView = new RecyclerView(mActivity); + recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + final View view = LayoutInflater.from(mActivity).inflate(VIEW_TYPE_HALF_WIDTH, recyclerView, + false); + + return mHelper.createViewHolder(view); + } + + private ContextualCard buildContextualCard() { + return new ContextualCard.Builder() + .setName("test_name") + .setCategory(ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE) + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(TEST_SLICE_URI) + .setIsHalfWidth(false /* isHalfWidth */) + .build(); + } + + private Slice buildSlice() { + final String title = "test_title"; + final IconCompat icon = IconCompat.createWithResource(mActivity, R.drawable.empty_icon); + final PendingIntent pendingIntent = PendingIntent.getActivity( + mActivity, + title.hashCode() /* requestCode */, + new Intent("test action"), + 0 /* flags */); + final SliceAction action + = SliceAction.createDeeplink(pendingIntent, icon, ListBuilder.SMALL_IMAGE, title); + return new ListBuilder(mActivity, TEST_SLICE_URI, ListBuilder.INFINITY) + .addRow(new ListBuilder.RowBuilder() + .addEndItem(icon, ListBuilder.ICON_IMAGE) + .setTitle(title) + .setPrimaryAction(action)) + .build(); + } +}