diff options
author | 2019-01-13 17:33:01 +0800 | |
---|---|---|
committer | 2019-01-17 14:13:15 +0800 | |
commit | 00a97b4c003568b0ef5c892dbae9567b69000c82 (patch) | |
tree | 97c33d1f9acaeeb673926c19a2954fd7f06bac8a | |
parent | 14a4f42bba8b9b5d6e8c349c363ee0cc5b1eb87e (diff) |
Allow each AppEntity to handle click events individually.
- Add a listener for each app entity view. So, they
can handle click events individually.
- Since the parameters of setAppEntity are increasing,
I create a builder class which save some information of
app entity.
- Clean up AppEntitiesHeaderController.
Test: visual, robotest
Bug: 121271387
Change-Id: I781773d566a87a30271b0d5b2dfc9fc1bd6b225e
4 files changed, 185 insertions, 66 deletions
diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml index fcafa3140955..96045120fec4 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml +++ b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml @@ -22,6 +22,8 @@ android:layout_weight="1" android:layout_marginEnd="16dp" android:gravity="center" + android:clickable="true" + android:background="?android:attr/selectableItemBackground" android:orientation="vertical"> <ImageView diff --git a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java index 8ccf89fc38b0..73cb8db136b5 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java +++ b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java @@ -18,7 +18,6 @@ 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; @@ -32,23 +31,9 @@ import androidx.annotation.StringRes; import androidx.annotation.VisibleForTesting; /** - * This is used to initialize view which was inflated + * This class 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. @@ -66,13 +51,20 @@ import androidx.annotation.VisibleForTesting; * View headerView = ((LayoutPreference) screen.findPreference("app_entities_header")) * .findViewById(R.id.app_entities_header); * + * final AppEntityInfo appEntityInfo = new AppEntityInfo.Builder() + * .setIcon(icon) + * .setTitle(title) + * .setSummary(summary) + * .setOnClickListener(view -> doSomething()) + * .build(); + * * 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") + * .setAppEntity(0, appEntityInfo) + * .setAppEntity(1, appEntityInfo) + * .setAppEntity(2, appEntityInfo) * .apply(); * </pre> */ @@ -81,13 +73,13 @@ public class AppEntitiesHeaderController { private static final String TAG = "AppEntitiesHeaderCtl"; @VisibleForTesting - static final int MAXIMUM_APPS = 3; + public static final int MAXIMUM_APPS = 3; private final Context mContext; private final TextView mHeaderTitleView; private final Button mHeaderDetailsView; - private final AppEntity[] mAppEntities; + private final AppEntityInfo[] mAppEntityInfos; private final View[] mAppEntityViews; private final ImageView[] mAppIconViews; private final TextView[] mAppTitleViews; @@ -100,7 +92,7 @@ public class AppEntitiesHeaderController { /** * Creates a new instance of the controller. * - * @param context the Context the view is running in + * @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, @@ -113,7 +105,7 @@ public class AppEntitiesHeaderController { mHeaderTitleView = appEntitiesHeaderView.findViewById(R.id.header_title); mHeaderDetailsView = appEntitiesHeaderView.findViewById(R.id.header_details); - mAppEntities = new AppEntity[MAXIMUM_APPS]; + mAppEntityInfos = new AppEntityInfo[MAXIMUM_APPS]; mAppIconViews = new ImageView[MAXIMUM_APPS]; mAppTitleViews = new TextView[MAXIMUM_APPS]; mAppSummaryViews = new TextView[MAXIMUM_APPS]; @@ -162,16 +154,13 @@ public class AppEntitiesHeaderController { /** * 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 + * @param index the index at which the specified view is to be inserted + * @param appEntityInfo the information of an 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; + public AppEntitiesHeaderController setAppEntity(int index, + @NonNull AppEntityInfo appEntityInfo) { + mAppEntityInfos[index] = appEntityInfo; return this; } @@ -182,7 +171,7 @@ public class AppEntitiesHeaderController { * @return this {@code AppEntitiesHeaderController} object */ public AppEntitiesHeaderController removeAppEntity(int index) { - mAppEntities[index] = null; + mAppEntityInfos[index] = null; return this; } @@ -237,31 +226,23 @@ public class AppEntitiesHeaderController { } private void bindAppEntityView(int index) { - final AppEntity appEntity = mAppEntities[index]; - mAppEntityViews[index].setVisibility(appEntity != null ? View.VISIBLE : View.GONE); + final AppEntityInfo appEntityInfo = mAppEntityInfos[index]; + mAppEntityViews[index].setVisibility(appEntityInfo != null ? View.VISIBLE : View.GONE); - if (appEntity != null) { - mAppIconViews[index].setImageDrawable(appEntity.icon); + if (appEntityInfo != null) { + mAppEntityViews[index].setOnClickListener(appEntityInfo.getClickListener()); + mAppIconViews[index].setImageDrawable(appEntityInfo.getIcon()); + + final CharSequence title = appEntityInfo.getTitle(); mAppTitleViews[index].setVisibility( - TextUtils.isEmpty(appEntity.title) ? View.INVISIBLE : View.VISIBLE); - mAppTitleViews[index].setText(appEntity.title); + TextUtils.isEmpty(title) ? View.INVISIBLE : View.VISIBLE); + mAppTitleViews[index].setText(title); + final CharSequence summary = appEntityInfo.getSummary(); 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; + TextUtils.isEmpty(summary) ? View.INVISIBLE : View.VISIBLE); + mAppSummaryViews[index].setText(summary); } } } diff --git a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntityInfo.java b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntityInfo.java new file mode 100644 index 000000000000..1e55f2e99bfc --- /dev/null +++ b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntityInfo.java @@ -0,0 +1,129 @@ +/* + * 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.settingslib.widget; + +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * AppEntityInfo is responsible for storing app information shown in {@link R.xml.app_view.xml}. + */ +public class AppEntityInfo { + + private final Drawable mIcon; + private final CharSequence mTitle; + private final CharSequence mSummary; + private final View.OnClickListener mClickListener; + + /** + * Gets the drawable for the icon of app entity. + * + * @return the drawable for the icon of app entity. + */ + public Drawable getIcon() { + return mIcon; + } + + /** + * Gets the text for the title of app enitity. + * + * @return the text for the title of app enitity. + */ + public CharSequence getTitle() { + return mTitle; + } + + /** + * Gets the text for the summary of app enitity. + * + * @return the text for the summary of app enitity. + */ + public CharSequence getSummary() { + return mSummary; + } + + /** + * Gets the click listener for the app entity view. + * + * @return click listener for the app entity view. + */ + public View.OnClickListener getClickListener() { + return mClickListener; + } + + private AppEntityInfo(Builder builder) { + mIcon = builder.mIcon; + mTitle = builder.mTitle; + mSummary = builder.mSummary; + mClickListener = builder.mClickListener; + } + + /** + * Builder class for {@link AppEntityInfo} + */ + public static class Builder { + + private Drawable mIcon; + private CharSequence mTitle; + private CharSequence mSummary; + private View.OnClickListener mClickListener; + + /** + * Creates an instance of a {@link AppEntityInfo} based on the current builder settings. + * + * @return The {@link AppEntityInfo}. + */ + public AppEntityInfo build() { + return new AppEntityInfo(this); + } + + /** + * Sets the drawable for the icon. + */ + public Builder setIcon(@NonNull Drawable icon) { + mIcon = icon; + return this; + } + + /** + * Sets the text for the title. + */ + public Builder setTitle(@Nullable CharSequence title) { + mTitle = title; + return this; + } + + /** + * Sets the text for the summary. + */ + public Builder setSummary(@Nullable CharSequence summary) { + mSummary = summary; + return this; + } + + /** + * Sets the click listener for app entity view. + */ + public Builder setOnClickListener(@Nullable View.OnClickListener clickListener) { + mClickListener = clickListener; + return this; + } + } +} 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 index c3bc8da89685..8c18c356159e 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java @@ -19,7 +19,6 @@ 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; @@ -43,18 +42,24 @@ public class AppEntitiesHeaderControllerTest { public final ExpectedException thrown = ExpectedException.none(); private Context mContext; - private Drawable mIcon; private View mAppEntitiesHeaderView; private AppEntitiesHeaderController mController; + private AppEntityInfo mAppEntityInfo; @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); + mAppEntityInfo = new AppEntityInfo.Builder() + .setIcon(mContext.getDrawable(R.drawable.ic_menu)) + .setTitle(TITLE) + .setSummary(SUMMARY) + .setOnClickListener(v -> { + }) + .build(); } @Test @@ -91,26 +96,26 @@ public class AppEntitiesHeaderControllerTest { public void setAppEntity_indexLessThanZero_shouldThrowArrayIndexOutOfBoundsException() { thrown.expect(ArrayIndexOutOfBoundsException.class); - mController.setAppEntity(-1, mIcon, TITLE, SUMMARY); + mController.setAppEntity(-1, mAppEntityInfo); } @Test public void asetAppEntity_indexGreaterThanMaximum_shouldThrowArrayIndexOutOfBoundsException() { thrown.expect(ArrayIndexOutOfBoundsException.class); - mController.setAppEntity(AppEntitiesHeaderController.MAXIMUM_APPS + 1, mIcon, TITLE, - SUMMARY); + mController.setAppEntity(AppEntitiesHeaderController.MAXIMUM_APPS + 1, mAppEntityInfo); } @Test public void setAppEntity_addAppToIndex0_shouldShowAppView1() { - mController.setAppEntity(0, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(0, mAppEntityInfo).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(app1View.hasOnClickListeners()).isTrue(); assertThat(appIconView.getDrawable()).isNotNull(); assertThat(appTitle.getText()).isEqualTo(TITLE); assertThat(appSummary.getText()).isEqualTo(SUMMARY); @@ -118,13 +123,14 @@ public class AppEntitiesHeaderControllerTest { @Test public void setAppEntity_addAppToIndex1_shouldShowAppView2() { - mController.setAppEntity(1, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(1, mAppEntityInfo).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(app2View.hasOnClickListeners()).isTrue(); assertThat(appIconView.getDrawable()).isNotNull(); assertThat(appTitle.getText()).isEqualTo(TITLE); assertThat(appSummary.getText()).isEqualTo(SUMMARY); @@ -132,13 +138,14 @@ public class AppEntitiesHeaderControllerTest { @Test public void setAppEntity_addAppToIndex2_shouldShowAppView3() { - mController.setAppEntity(2, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(2, mAppEntityInfo).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(app3View.hasOnClickListeners()).isTrue(); assertThat(appIconView.getDrawable()).isNotNull(); assertThat(appTitle.getText()).isEqualTo(TITLE); assertThat(appSummary.getText()).isEqualTo(SUMMARY); @@ -146,8 +153,8 @@ public class AppEntitiesHeaderControllerTest { @Test public void removeAppEntity_removeIndex0_shouldNotShowAppView1() { - mController.setAppEntity(0, mIcon, TITLE, SUMMARY) - .setAppEntity(1, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(0, mAppEntityInfo) + .setAppEntity(1, mAppEntityInfo).apply(); final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view); final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view); @@ -162,9 +169,9 @@ public class AppEntitiesHeaderControllerTest { @Test public void clearAllAppEntities_shouldNotShowAllAppViews() { - mController.setAppEntity(0, mIcon, TITLE, SUMMARY) - .setAppEntity(1, mIcon, TITLE, SUMMARY) - .setAppEntity(2, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(0, mAppEntityInfo) + .setAppEntity(1, mAppEntityInfo) + .setAppEntity(2, mAppEntityInfo).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); |