Merge changes from topic "am-a1205538-cc32-4ec0-9e68-c68e2ae82db6"
* changes:
[automerger] Support list styles for PagedListView. am: d0e9e80e8d
Support list styles for PagedListView.
diff --git a/car/build.gradle b/car/build.gradle
index 7ea0873..6aa1865 100644
--- a/car/build.gradle
+++ b/car/build.gradle
@@ -18,6 +18,10 @@
androidTestImplementation(ESPRESSO_CONTRIB, libs.exclude_support)
androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+
+ testImplementation(JUNIT)
+ testImplementation(TEST_RUNNER)
+ testImplementation(MOCKITO_CORE)
}
android {
diff --git a/car/res/layout/car_paged_list_item.xml b/car/res/drawable/car_card_background.xml
similarity index 70%
rename from car/res/layout/car_paged_list_item.xml
rename to car/res/drawable/car_card_background.xml
index c0861d9..7caa2ff 100644
--- a/car/res/layout/car_paged_list_item.xml
+++ b/car/res/drawable/car_card_background.xml
@@ -14,12 +14,6 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="@color/car_card">
-
- <include layout="@layout/car_paged_list_item_content" />
-
-</FrameLayout>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/car_card"/>
+</shape>
\ No newline at end of file
diff --git a/car/res/layout/car_paged_list_item.xml b/car/res/drawable/car_card_rounded_background.xml
similarity index 70%
copy from car/res/layout/car_paged_list_item.xml
copy to car/res/drawable/car_card_rounded_background.xml
index c0861d9..594705b 100644
--- a/car/res/layout/car_paged_list_item.xml
+++ b/car/res/drawable/car_card_rounded_background.xml
@@ -14,12 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="@color/car_card">
-
- <include layout="@layout/car_paged_list_item_content" />
-
-</FrameLayout>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/car_card"/>
+ <corners
+ android:radius="@dimen/car_radius_3"/>
+</shape>
\ No newline at end of file
diff --git a/car/res/layout/car_paged_list_item.xml b/car/res/drawable/car_card_rounded_bottom_background.xml
similarity index 70%
copy from car/res/layout/car_paged_list_item.xml
copy to car/res/drawable/car_card_rounded_bottom_background.xml
index c0861d9..35dba13 100644
--- a/car/res/layout/car_paged_list_item.xml
+++ b/car/res/drawable/car_card_rounded_bottom_background.xml
@@ -14,12 +14,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="@color/car_card">
-
- <include layout="@layout/car_paged_list_item_content" />
-
-</FrameLayout>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/car_card"/>
+ <corners
+ android:bottomRightRadius="@dimen/car_radius_3"
+ android:bottomLeftRadius="@dimen/car_radius_3"/>
+</shape>
\ No newline at end of file
diff --git a/car/res/layout/car_paged_list_item.xml b/car/res/drawable/car_card_rounded_top_background.xml
similarity index 70%
copy from car/res/layout/car_paged_list_item.xml
copy to car/res/drawable/car_card_rounded_top_background.xml
index c0861d9..dfb5622 100644
--- a/car/res/layout/car_paged_list_item.xml
+++ b/car/res/drawable/car_card_rounded_top_background.xml
@@ -14,12 +14,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:background="@color/car_card">
-
- <include layout="@layout/car_paged_list_item_content" />
-
-</FrameLayout>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/car_card"/>
+ <corners
+ android:topRightRadius="@dimen/car_radius_3"
+ android:topLeftRadius="@dimen/car_radius_3"/>
+</shape>
\ No newline at end of file
diff --git a/car/res/layout/car_paged_list_card.xml b/car/res/layout/car_paged_list_card.xml
deleted file mode 100644
index fe5de89..0000000
--- a/car/res/layout/car_paged_list_card.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2017 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.
- -->
-<android.support.v7.widget.CardView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:layout_marginBottom="@dimen/car_padding_1"
- app:cardCornerRadius="@dimen/car_radius_1"
- app:cardBackgroundColor="@color/car_card">
-
- <include layout="@layout/car_paged_list_item_content" />
-
-</android.support.v7.widget.CardView>
diff --git a/car/src/main/java/androidx/car/utils/ListItemBackgroundResolver.java b/car/src/main/java/androidx/car/utils/ListItemBackgroundResolver.java
new file mode 100644
index 0000000..406c047
--- /dev/null
+++ b/car/src/main/java/androidx/car/utils/ListItemBackgroundResolver.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2017 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 androidx.car.utils;
+
+import android.view.View;
+
+import androidx.car.R;
+
+/**
+ * A utility class that will set the current background for a View that represents an card entry
+ * in a list. The class will set the background depending on the position of the card within the
+ * list.
+ */
+public class ListItemBackgroundResolver {
+ private ListItemBackgroundResolver() {}
+
+ /**
+ * Sets the background on the given view so that the combination of all items looks like a
+ * rectangle with rounded corner. The view is assumed to have a non-rounded corner outline.
+ *
+ * <p>The view will be set with rounded backgrounds if it is the only card within the list.
+ * Or if it is the first or last view, it will have the top or bottom corners rounded
+ * respectively.
+ *
+ * @param view The view whose background to set.
+ * @param currentPosition The current position of the View within the list. This value should
+ * be 0-based.
+ * @param totalItems The total items within the list.
+ */
+ public static void setBackground(View view, int currentPosition, int totalItems) {
+ if (currentPosition < 0) {
+ throw new IllegalArgumentException("currentPosition cannot be less than zero.");
+ }
+
+ if (currentPosition >= totalItems) {
+ throw new IndexOutOfBoundsException("currentPosition: " + currentPosition + "; "
+ + "totalItems: " + totalItems);
+ }
+
+ // Set the background for each card. Only the top and last card should have rounded corners.
+ if (totalItems == 1) {
+ // One card - all corners are rounded.
+ view.setBackgroundResource(R.drawable.car_card_rounded_background);
+ } else if (currentPosition == 0) {
+ // First card gets rounded top.
+ view.setBackgroundResource(R.drawable.car_card_rounded_top_background);
+ } else if (currentPosition == totalItems - 1) {
+ // Last one has a rounded bottom.
+ view.setBackgroundResource(R.drawable.car_card_rounded_bottom_background);
+ } else {
+ // Middle has no rounded corners.
+ view.setBackgroundResource(R.drawable.car_card_background);
+ }
+ }
+}
+
diff --git a/car/src/main/java/androidx/car/widget/ListItem.java b/car/src/main/java/androidx/car/widget/ListItem.java
index 08cc48e..d292d6b 100644
--- a/car/src/main/java/androidx/car/widget/ListItem.java
+++ b/car/src/main/java/androidx/car/widget/ListItem.java
@@ -94,16 +94,6 @@
}
/**
- * Used by {@link ListItemAdapter} to choose layout to inflate for view holder.
- * New view type needs support in {@link ListItemAdapter}.
- */
- protected int getViewType() {
- return mBuilder.mIsCard
- ? ListItemAdapter.CAR_PAGED_LIST_CARD
- : ListItemAdapter.CAR_PAGED_LIST_ITEM;
- }
-
- /**
* Functional interface to provide a way to interact with views in
* {@link ListItemAdapter.ViewHolder}. {@code ViewBinder}s added to a
* {@code ListItem} will be called when {@code ListItem} {@code bind}s to
@@ -150,8 +140,6 @@
// Store custom binders separately so they will bind after binders are created in build().
private final List<ViewBinder> mCustomBinders = new ArrayList<>();
- private boolean mIsCard;
-
private View.OnClickListener mOnClickListener;
@PrimaryActionType private int mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON;
@@ -499,18 +487,6 @@
}
/**
- * Builds the item in a {@link android.support.v7.widget.CardView}.
- *
- * <p>Each item will have rounded corner, margin between items, and elevation.
- *
- * @return This Builder object to allow for chaining calls to set methods.
- */
- public Builder withCardLook() {
- mIsCard = true;
- return this;
- }
-
- /**
* Sets {@link View.OnClickListener} of {@code ListItem}.
*
* @return This Builder object to allow for chaining calls to set methods.
diff --git a/car/src/main/java/androidx/car/widget/ListItemAdapter.java b/car/src/main/java/androidx/car/widget/ListItemAdapter.java
index 2bdfae6..c9b6177 100644
--- a/car/src/main/java/androidx/car/widget/ListItemAdapter.java
+++ b/car/src/main/java/androidx/car/widget/ListItemAdapter.java
@@ -16,22 +16,20 @@
package androidx.car.widget;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
import android.content.Context;
-import android.support.annotation.IntDef;
+import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
-import java.lang.annotation.Retention;
-
import androidx.car.R;
+import androidx.car.utils.ListItemBackgroundResolver;
/**
* Adapter for {@link PagedListView} to display {@link ListItem}.
@@ -40,11 +38,30 @@
*/
public class ListItemAdapter extends
RecyclerView.Adapter<ListItemAdapter.ViewHolder> implements PagedListView.ItemCap {
- @Retention(SOURCE)
- @IntDef({CAR_PAGED_LIST_ITEM, CAR_PAGED_LIST_CARD})
- public @interface PagedListItemType {}
- public static final int CAR_PAGED_LIST_ITEM = 0;
- public static final int CAR_PAGED_LIST_CARD = 1;
+
+ /**
+ * Constant class for background style of items.
+ */
+ public static final class BackgroundStyle {
+ private BackgroundStyle() {}
+
+ /**
+ * Sets the background color of each item.
+ */
+ public static final int NONE = 0;
+ /**
+ * Sets each item in {@link CardView} with a rounded corner background and shadow.
+ */
+ public static final int CARD = 1;
+ /**
+ * Sets background of each item so the combined list looks like one elongated card, namely
+ * top and bottom item will have rounded corner at only top/bottom side respectively. If
+ * only one item exists, it will have both top and bottom rounded corner.
+ */
+ public static final int PANEL = 2;
+ }
+
+ private int mBackgroundStyle;
private final Context mContext;
private final ListItemProvider mItemProvider;
@@ -52,37 +69,66 @@
private int mMaxItems = PagedListView.ItemCap.UNLIMITED;
public ListItemAdapter(Context context, ListItemProvider itemProvider) {
+ this(context, itemProvider, BackgroundStyle.NONE);
+ }
+
+ public ListItemAdapter(Context context, ListItemProvider itemProvider,
+ int backgroundStyle) {
mContext = context;
mItemProvider = itemProvider;
+ mBackgroundStyle = backgroundStyle;
}
@Override
- public int getItemViewType(int position) {
- return mItemProvider.get(position).getViewType();
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, @PagedListItemType int viewType) {
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
- int layoutId;
- switch (viewType) {
- case CAR_PAGED_LIST_ITEM:
- layoutId = R.layout.car_paged_list_item;
+ View itemView = inflater.inflate(R.layout.car_paged_list_item_content, parent, false);
+
+ ViewGroup container = createListItemContainer();
+ container.addView(itemView);
+ return new ViewHolder(container);
+ }
+
+ private ViewGroup createListItemContainer() {
+ ViewGroup container;
+ switch (mBackgroundStyle) {
+ case BackgroundStyle.NONE:
+ case BackgroundStyle.PANEL:
+ FrameLayout frameLayout = new FrameLayout(mContext);
+ frameLayout.setLayoutParams(new RecyclerView.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ frameLayout.setBackgroundColor(mContext.getColor(R.color.car_card));
+
+ container = frameLayout;
break;
- case CAR_PAGED_LIST_CARD:
- layoutId = R.layout.car_paged_list_card;
+ case BackgroundStyle.CARD:
+ CardView card = new CardView(mContext);
+ RecyclerView.LayoutParams cardLayoutParams = new RecyclerView.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ cardLayoutParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.car_padding_3);
+ card.setLayoutParams(cardLayoutParams);
+ card.setRadius(mContext.getResources().getDimensionPixelSize(R.dimen.car_radius_1));
+ card.setCardBackgroundColor(mContext.getColor(R.color.car_card));
+
+ container = card;
break;
default:
- throw new IllegalArgumentException("Unrecognizable view type: " + viewType);
+ throw new IllegalArgumentException("Unknown background style. "
+ + "Expected constants in class ListItemAdapter.BackgroundStyle.");
}
- View itemView = inflater.inflate(layoutId, parent, false);
- return new ViewHolder(itemView);
+ return container;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
ListItem item = mItemProvider.get(position);
item.bind(holder);
+
+ if (mBackgroundStyle == BackgroundStyle.PANEL) {
+ ListItemBackgroundResolver.setBackground(
+ holder.itemView, position, mItemProvider.size());
+ }
}
@Override
diff --git a/car/src/test/java/androidx/car/utils/ListItemBackgroundResolverTest.java b/car/src/test/java/androidx/car/utils/ListItemBackgroundResolverTest.java
new file mode 100644
index 0000000..b809c79
--- /dev/null
+++ b/car/src/test/java/androidx/car/utils/ListItemBackgroundResolverTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 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 androidx.car.utils;
+
+
+import static org.mockito.Mockito.verify;
+
+import android.view.View;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import androidx.car.R;
+
+/**
+ * Tests for {@link ListItemBackgroundResolver}.
+ */
+@RunWith(JUnit4.class)
+public class ListItemBackgroundResolverTest {
+
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Mock
+ View mMockView;
+
+ @Test
+ public void testSingleItemInListHasAllRoundedCorners() {
+ ListItemBackgroundResolver.setBackground(mMockView, 0, 1);
+
+ verify(mMockView).setBackgroundResource(R.drawable.car_card_rounded_background);
+ }
+
+ @Test
+ public void testOnlyTopItemHasTopRoundedCorners() {
+ ListItemBackgroundResolver.setBackground(mMockView, 0, 2);
+
+ verify(mMockView).setBackgroundResource(R.drawable.car_card_rounded_top_background);
+ }
+
+ @Test
+ public void testOnlyBottomItemHasBottomRoundedCorners() {
+ ListItemBackgroundResolver.setBackground(mMockView, 1, 2);
+
+ verify(mMockView).setBackgroundResource(R.drawable.car_card_rounded_bottom_background);
+ }
+
+ @Test
+ public void testMiddleItemHasNoRoundedCorner() {
+ ListItemBackgroundResolver.setBackground(mMockView, 1, 3);
+
+ verify(mMockView).setBackgroundResource(R.drawable.car_card_background);
+ }
+}
diff --git a/car/tests/src/androidx/car/widget/ListItemTest.java b/car/tests/src/androidx/car/widget/ListItemTest.java
index bdf3e29..233e720 100644
--- a/car/tests/src/androidx/car/widget/ListItemTest.java
+++ b/car/tests/src/androidx/car/widget/ListItemTest.java
@@ -25,7 +25,6 @@
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.number.IsCloseTo.closeTo;
@@ -39,7 +38,6 @@
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import android.support.v7.widget.CardView;
import android.support.v7.widget.LinearLayoutManager;
import android.view.View;
import android.view.ViewGroup;
@@ -481,18 +479,6 @@
}
@Test
- public void testCardLookUsesCardView() {
- List<ListItem> items = Arrays.asList(
- new ListItem.Builder(mActivity)
- .withCardLook()
- .build());
- setupPagedListView(items);
-
- ListItemAdapter.ViewHolder viewHolder = getViewHolderAtPosition(0);
- assertThat(viewHolder.itemView, is(instanceOf(CardView.class)));
- }
-
- @Test
public void testSettingTitleOrBodyAsPrimaryText() {
// Create 2 items, one with Title as primary (default) and one with Body.
// The primary text, regardless of view, should have consistent look (as primary).
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ListItemActivity.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ListItemActivity.java
index 6aa5ba6..790f1f1 100644
--- a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ListItemActivity.java
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/ListItemActivity.java
@@ -54,7 +54,7 @@
mPagedListView = findViewById(R.id.paged_list_view);
ListItemAdapter adapter = new ListItemAdapter(this,
- new SampleProvider(this));
+ new SampleProvider(this), ListItemAdapter.BackgroundStyle.PANEL);
mPagedListView.setAdapter(adapter);
mPagedListView.setMaxPages(PagedListView.UNLIMITED_PAGES);
}