Create an AppEntitiesHeader widget
- Create a library named EntityHeaderWidgets, it can contains
other entity header wdigets in the future.
- Create a controller of AppEntitiesHeader,
then user can initialize its view easily.
Test: visual, robotest
Change-Id: If11b3eba75334f66b72472b2139e0e7d93984dce
Fixes: 117621156
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index cc17b25..0126e7e5 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -18,6 +18,7 @@
"SettingsLibSettingsSpinner",
"SettingsLayoutPreference",
"ActionButtonsPreference",
+ "SettingsLibEntityHeaderWidgets",
],
// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
diff --git a/packages/SettingsLib/EntityHeaderWidgets/Android.bp b/packages/SettingsLib/EntityHeaderWidgets/Android.bp
new file mode 100644
index 0000000..3ca4ecd
--- /dev/null
+++ b/packages/SettingsLib/EntityHeaderWidgets/Android.bp
@@ -0,0 +1,14 @@
+android_library {
+ name: "SettingsLibEntityHeaderWidgets",
+
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+
+ static_libs: [
+ "androidx.annotation_annotation",
+ "SettingsLibAppPreference"
+ ],
+
+ sdk_version: "system_current",
+ min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/EntityHeaderWidgets/AndroidManifest.xml b/packages/SettingsLib/EntityHeaderWidgets/AndroidManifest.xml
new file mode 100644
index 0000000..4b9f1ab
--- /dev/null
+++ b/packages/SettingsLib/EntityHeaderWidgets/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.widget">
+
+ <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_entities_header.xml b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_entities_header.xml
new file mode 100644
index 0000000..9f30eda
--- /dev/null
+++ b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_entities_header.xml
@@ -0,0 +1,64 @@
+<?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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/app_entities_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="24dp"
+ android:paddingEnd="8dp"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/header_title"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:gravity="center"
+ android:textAppearance="@style/AppEntitiesHeader.Text.HeaderTitle"/>
+
+ <LinearLayout
+ android:id="@+id/all_apps_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp"
+ android:gravity="center">
+
+ <include
+ android:id="@+id/app1_view"
+ layout="@layout/app_view"/>
+
+ <include
+ android:id="@+id/app2_view"
+ layout="@layout/app_view"/>
+
+ <include
+ android:id="@+id/app3_view"
+ layout="@layout/app_view"/>
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/header_details"
+ style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:gravity="center"/>
+
+</LinearLayout>
diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml
new file mode 100644
index 0000000..fcafa31
--- /dev/null
+++ b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml
@@ -0,0 +1,50 @@
+<?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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginEnd="16dp"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/app_icon"
+ android:layout_width="@dimen/secondary_app_icon_size"
+ android:layout_height="@dimen/secondary_app_icon_size"
+ android:layout_marginBottom="12dp"/>
+
+ <TextView
+ android:id="@+id/app_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="2dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@style/AppEntitiesHeader.Text.Title"/>
+
+ <TextView
+ android:id="@+id/app_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="@style/AppEntitiesHeader.Text.Summary"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml b/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml
new file mode 100644
index 0000000..0eefd4b
--- /dev/null
+++ b/packages/SettingsLib/EntityHeaderWidgets/res/values/styles.xml
@@ -0,0 +1,38 @@
+<?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.
+ -->
+
+<resources>
+ <style name="AppEntitiesHeader.Text"
+ parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="AppEntitiesHeader.Text.HeaderTitle">
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="AppEntitiesHeader.Text.Title">
+ <item name="android:textSize">16sp</item>
+ </style>
+
+ <style name="AppEntitiesHeader.Text.Summary"
+ parent="@android:style/TextAppearance.Material.Body1">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java
new file mode 100644
index 0000000..8ccf89f
--- /dev/null
+++ b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java
@@ -0,0 +1,267 @@
+/*
+ * 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.settingslib.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * This is used to initialize view which was inflated
+ * from {@link R.xml.app_entities_header.xml}.
+ *
+ * <p>The view looks like below.
+ *
+ * <pre>
+ * --------------------------------------------------------------
+ * | Header title |
+ * --------------------------------------------------------------
+ * | App1 icon | App2 icon | App3 icon |
+ * | App1 title | App2 title | App3 title |
+ * | App1 summary | App2 summary | App3 summary |
+ * |-------------------------------------------------------------
+ * | Header details |
+ * --------------------------------------------------------------
+ * </pre>
+ *
+ * <p>How to use AppEntitiesHeaderController?
+ *
+ * <p>1. Add a {@link LayoutPreference} in layout XML file.
+ * <pre>
+ * <com.android.settingslib.widget.LayoutPreference
+ * android:key="app_entities_header"
+ * android:layout="@layout/app_entities_header"/>
+ * </pre>
+ *
+ * <p>2. Use AppEntitiesHeaderController to call below methods, then you can initialize
+ * view of <code>app_entities_header</code>.
+ *
+ * <pre>
+ *
+ * View headerView = ((LayoutPreference) screen.findPreference("app_entities_header"))
+ * .findViewById(R.id.app_entities_header);
+ *
+ * AppEntitiesHeaderController.newInstance(context, headerView)
+ * .setHeaderTitleRes(R.string.xxxxx)
+ * .setHeaderDetailsRes(R.string.xxxxx)
+ * .setHeaderDetailsClickListener(onClickListener)
+ * .setAppEntity(0, icon, "app title", "app summary")
+ * .setAppEntity(1, icon, "app title", "app summary")
+ * .setAppEntity(2, icon, "app title", "app summary")
+ * .apply();
+ * </pre>
+ */
+public class AppEntitiesHeaderController {
+
+ private static final String TAG = "AppEntitiesHeaderCtl";
+
+ @VisibleForTesting
+ static final int MAXIMUM_APPS = 3;
+
+ private final Context mContext;
+ private final TextView mHeaderTitleView;
+ private final Button mHeaderDetailsView;
+
+ private final AppEntity[] mAppEntities;
+ private final View[] mAppEntityViews;
+ private final ImageView[] mAppIconViews;
+ private final TextView[] mAppTitleViews;
+ private final TextView[] mAppSummaryViews;
+
+ private int mHeaderTitleRes;
+ private int mHeaderDetailsRes;
+ private View.OnClickListener mDetailsOnClickListener;
+
+ /**
+ * Creates a new instance of the controller.
+ *
+ * @param context the Context the view is running in
+ * @param appEntitiesHeaderView view was inflated from <code>app_entities_header</code>
+ */
+ public static AppEntitiesHeaderController newInstance(@NonNull Context context,
+ @NonNull View appEntitiesHeaderView) {
+ return new AppEntitiesHeaderController(context, appEntitiesHeaderView);
+ }
+
+ private AppEntitiesHeaderController(Context context, View appEntitiesHeaderView) {
+ mContext = context;
+ mHeaderTitleView = appEntitiesHeaderView.findViewById(R.id.header_title);
+ mHeaderDetailsView = appEntitiesHeaderView.findViewById(R.id.header_details);
+
+ mAppEntities = new AppEntity[MAXIMUM_APPS];
+ mAppIconViews = new ImageView[MAXIMUM_APPS];
+ mAppTitleViews = new TextView[MAXIMUM_APPS];
+ mAppSummaryViews = new TextView[MAXIMUM_APPS];
+
+ mAppEntityViews = new View[]{
+ appEntitiesHeaderView.findViewById(R.id.app1_view),
+ appEntitiesHeaderView.findViewById(R.id.app2_view),
+ appEntitiesHeaderView.findViewById(R.id.app3_view)
+ };
+
+ // Initialize view in advance, so we won't take too much time to do it when controller is
+ // binding view.
+ for (int index = 0; index < MAXIMUM_APPS; index++) {
+ final View appView = mAppEntityViews[index];
+ mAppIconViews[index] = (ImageView) appView.findViewById(R.id.app_icon);
+ mAppTitleViews[index] = (TextView) appView.findViewById(R.id.app_title);
+ mAppSummaryViews[index] = (TextView) appView.findViewById(R.id.app_summary);
+ }
+ }
+
+ /**
+ * Set the text resource for app entities header title.
+ */
+ public AppEntitiesHeaderController setHeaderTitleRes(@StringRes int titleRes) {
+ mHeaderTitleRes = titleRes;
+ return this;
+ }
+
+ /**
+ * Set the text resource for app entities header details.
+ */
+ public AppEntitiesHeaderController setHeaderDetailsRes(@StringRes int detailsRes) {
+ mHeaderDetailsRes = detailsRes;
+ return this;
+ }
+
+ /**
+ * Register a callback to be invoked when header details view is clicked.
+ */
+ public AppEntitiesHeaderController setHeaderDetailsClickListener(
+ @Nullable View.OnClickListener clickListener) {
+ mDetailsOnClickListener = clickListener;
+ return this;
+ }
+
+ /**
+ * Set an app entity at a specified position view.
+ *
+ * @param index the index at which the specified view is to be inserted
+ * @param icon the icon of app entity
+ * @param titleRes the title of app entity
+ * @param summaryRes the summary of app entity
+ * @return this {@code AppEntitiesHeaderController} object
+ */
+ public AppEntitiesHeaderController setAppEntity(int index, @NonNull Drawable icon,
+ @Nullable CharSequence titleRes, @Nullable CharSequence summaryRes) {
+ final AppEntity appEntity = new AppEntity(icon, titleRes, summaryRes);
+ mAppEntities[index] = appEntity;
+ return this;
+ }
+
+ /**
+ * Remove an app entity at a specified position view.
+ *
+ * @param index the index at which the specified view is to be removed
+ * @return this {@code AppEntitiesHeaderController} object
+ */
+ public AppEntitiesHeaderController removeAppEntity(int index) {
+ mAppEntities[index] = null;
+ return this;
+ }
+
+ /**
+ * Clear all app entities in app entities header.
+ *
+ * @return this {@code AppEntitiesHeaderController} object
+ */
+ public AppEntitiesHeaderController clearAllAppEntities() {
+ for (int index = 0; index < MAXIMUM_APPS; index++) {
+ removeAppEntity(index);
+ }
+ return this;
+ }
+
+ /**
+ * Done mutating app entities header, rebinds everything.
+ */
+ public void apply() {
+ bindHeaderTitleView();
+ bindHeaderDetailsView();
+
+ // Rebind all apps view
+ for (int index = 0; index < MAXIMUM_APPS; index++) {
+ bindAppEntityView(index);
+ }
+ }
+
+ private void bindHeaderTitleView() {
+ CharSequence titleText = "";
+ try {
+ titleText = mContext.getText(mHeaderTitleRes);
+ } catch (Resources.NotFoundException e) {
+ Log.e(TAG, "Resource of header title can't not be found!", e);
+ }
+ mHeaderTitleView.setText(titleText);
+ mHeaderTitleView.setVisibility(
+ TextUtils.isEmpty(titleText) ? View.GONE : View.VISIBLE);
+ }
+
+ private void bindHeaderDetailsView() {
+ CharSequence detailsText = "";
+ try {
+ detailsText = mContext.getText(mHeaderDetailsRes);
+ } catch (Resources.NotFoundException e) {
+ Log.e(TAG, "Resource of header details can't not be found!", e);
+ }
+ mHeaderDetailsView.setText(detailsText);
+ mHeaderDetailsView.setVisibility(
+ TextUtils.isEmpty(detailsText) ? View.GONE : View.VISIBLE);
+ mHeaderDetailsView.setOnClickListener(mDetailsOnClickListener);
+ }
+
+ private void bindAppEntityView(int index) {
+ final AppEntity appEntity = mAppEntities[index];
+ mAppEntityViews[index].setVisibility(appEntity != null ? View.VISIBLE : View.GONE);
+
+ if (appEntity != null) {
+ mAppIconViews[index].setImageDrawable(appEntity.icon);
+
+ mAppTitleViews[index].setVisibility(
+ TextUtils.isEmpty(appEntity.title) ? View.INVISIBLE : View.VISIBLE);
+ mAppTitleViews[index].setText(appEntity.title);
+
+ mAppSummaryViews[index].setVisibility(
+ TextUtils.isEmpty(appEntity.summary) ? View.INVISIBLE : View.VISIBLE);
+ mAppSummaryViews[index].setText(appEntity.summary);
+ }
+ }
+
+ private static class AppEntity {
+ public final Drawable icon;
+ public final CharSequence title;
+ public final CharSequence summary;
+
+ AppEntity(Drawable appIcon, CharSequence appTitle, CharSequence appSummary) {
+ icon = appIcon;
+ title = appTitle;
+ summary = appSummary;
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
new file mode 100644
index 0000000..c3bc8da
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.settingslib.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class AppEntitiesHeaderControllerTest {
+
+ private static final CharSequence TITLE = "APP_TITLE";
+ private static final CharSequence SUMMARY = "APP_SUMMARY";
+
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
+ private Context mContext;
+ private Drawable mIcon;
+ private View mAppEntitiesHeaderView;
+ private AppEntitiesHeaderController mController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mAppEntitiesHeaderView = LayoutInflater.from(mContext).inflate(
+ R.layout.app_entities_header, null /* root */);
+ mIcon = mContext.getDrawable(R.drawable.ic_menu);
+ mController = AppEntitiesHeaderController.newInstance(mContext,
+ mAppEntitiesHeaderView);
+ }
+
+ @Test
+ public void assert_amountOfMaximumAppsAreThree() {
+ assertThat(AppEntitiesHeaderController.MAXIMUM_APPS).isEqualTo(3);
+ }
+
+ @Test
+ public void setHeaderTitleRes_setTextRes_shouldSetToTitleView() {
+ mController.setHeaderTitleRes(R.string.expand_button_title).apply();
+ final TextView view = mAppEntitiesHeaderView.findViewById(R.id.header_title);
+
+ assertThat(view.getText()).isEqualTo(mContext.getText(R.string.expand_button_title));
+ }
+
+ @Test
+ public void setHeaderDetailsRes_setTextRes_shouldSetToDetailsView() {
+ mController.setHeaderDetailsRes(R.string.expand_button_title).apply();
+ final TextView view = mAppEntitiesHeaderView.findViewById(R.id.header_details);
+
+ assertThat(view.getText()).isEqualTo(mContext.getText(R.string.expand_button_title));
+ }
+
+ @Test
+ public void setHeaderDetailsClickListener_setClickListener_detailsViewAttachClickListener() {
+ mController.setHeaderDetailsClickListener(v -> {
+ }).apply();
+ final TextView view = mAppEntitiesHeaderView.findViewById(R.id.header_details);
+
+ assertThat(view.hasOnClickListeners()).isTrue();
+ }
+
+ @Test
+ public void setAppEntity_indexLessThanZero_shouldThrowArrayIndexOutOfBoundsException() {
+ thrown.expect(ArrayIndexOutOfBoundsException.class);
+
+ mController.setAppEntity(-1, mIcon, TITLE, SUMMARY);
+ }
+
+ @Test
+ public void asetAppEntity_indexGreaterThanMaximum_shouldThrowArrayIndexOutOfBoundsException() {
+ thrown.expect(ArrayIndexOutOfBoundsException.class);
+
+ mController.setAppEntity(AppEntitiesHeaderController.MAXIMUM_APPS + 1, mIcon, TITLE,
+ SUMMARY);
+ }
+
+ @Test
+ public void setAppEntity_addAppToIndex0_shouldShowAppView1() {
+ mController.setAppEntity(0, mIcon, TITLE, SUMMARY).apply();
+ final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view);
+ final ImageView appIconView = app1View.findViewById(R.id.app_icon);
+ final TextView appTitle = app1View.findViewById(R.id.app_title);
+ final TextView appSummary = app1View.findViewById(R.id.app_summary);
+
+ assertThat(app1View.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(appIconView.getDrawable()).isNotNull();
+ assertThat(appTitle.getText()).isEqualTo(TITLE);
+ assertThat(appSummary.getText()).isEqualTo(SUMMARY);
+ }
+
+ @Test
+ public void setAppEntity_addAppToIndex1_shouldShowAppView2() {
+ mController.setAppEntity(1, mIcon, TITLE, SUMMARY).apply();
+ final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view);
+ final ImageView appIconView = app2View.findViewById(R.id.app_icon);
+ final TextView appTitle = app2View.findViewById(R.id.app_title);
+ final TextView appSummary = app2View.findViewById(R.id.app_summary);
+
+ assertThat(app2View.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(appIconView.getDrawable()).isNotNull();
+ assertThat(appTitle.getText()).isEqualTo(TITLE);
+ assertThat(appSummary.getText()).isEqualTo(SUMMARY);
+ }
+
+ @Test
+ public void setAppEntity_addAppToIndex2_shouldShowAppView3() {
+ mController.setAppEntity(2, mIcon, TITLE, SUMMARY).apply();
+ final View app3View = mAppEntitiesHeaderView.findViewById(R.id.app3_view);
+ final ImageView appIconView = app3View.findViewById(R.id.app_icon);
+ final TextView appTitle = app3View.findViewById(R.id.app_title);
+ final TextView appSummary = app3View.findViewById(R.id.app_summary);
+
+ assertThat(app3View.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(appIconView.getDrawable()).isNotNull();
+ assertThat(appTitle.getText()).isEqualTo(TITLE);
+ assertThat(appSummary.getText()).isEqualTo(SUMMARY);
+ }
+
+ @Test
+ public void removeAppEntity_removeIndex0_shouldNotShowAppView1() {
+ mController.setAppEntity(0, mIcon, TITLE, SUMMARY)
+ .setAppEntity(1, mIcon, TITLE, SUMMARY).apply();
+ final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view);
+ final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view);
+
+ assertThat(app1View.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(app2View.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mController.removeAppEntity(0).apply();
+
+ assertThat(app1View.getVisibility()).isEqualTo(View.GONE);
+ assertThat(app2View.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void clearAllAppEntities_shouldNotShowAllAppViews() {
+ mController.setAppEntity(0, mIcon, TITLE, SUMMARY)
+ .setAppEntity(1, mIcon, TITLE, SUMMARY)
+ .setAppEntity(2, mIcon, TITLE, SUMMARY).apply();
+ final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view);
+ final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view);
+ final View app3View = mAppEntitiesHeaderView.findViewById(R.id.app3_view);
+
+ assertThat(app1View.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(app2View.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(app3View.getVisibility()).isEqualTo(View.VISIBLE);
+
+ mController.clearAllAppEntities().apply();
+ assertThat(app1View.getVisibility()).isEqualTo(View.GONE);
+ assertThat(app2View.getVisibility()).isEqualTo(View.GONE);
+ assertThat(app3View.getVisibility()).isEqualTo(View.GONE);
+ }
+}