diff options
author | 2022-08-10 16:01:15 +0800 | |
---|---|---|
committer | 2022-09-07 13:54:02 +0800 | |
commit | 99604ae5442c67c0894cd53c1e109237ae713ea0 (patch) | |
tree | 7409fd8159c2a9c51f47e909ed7fb60e31af6398 | |
parent | 75d1f85bf3b4f61b592b6e65a8d79a91a2981e09 (diff) |
Add AppHeaderPreference
Add a Preference widget for pages need to show big apps icon and name in
the header of the page.
BUG: 239779252
Test: add a simialr test like AppPreference
Change-Id: I296b0ed7b9c7645f31a9080c29da490b843494b0
7 files changed, 348 insertions, 14 deletions
diff --git a/packages/SettingsLib/AppPreference/res/layout/app_header_preference.xml b/packages/SettingsLib/AppPreference/res/layout/app_header_preference.xml new file mode 100644 index 000000000000..a2389a9b83a2 --- /dev/null +++ b/packages/SettingsLib/AppPreference/res/layout/app_header_preference.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 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. + --> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="24dp" + android:paddingBottom="16dp" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:orientation="horizontal"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:gravity="center_horizontal" + android:orientation="vertical"> + + <ImageView + android:id="@android:id/icon" + android:layout_width="48dp" + android:layout_height="48dp" + android:scaleType="fitCenter" + android:antialias="true"/> + + <TextView + android:id="@android:id/title" + style="@style/TextAppearance.EntityHeaderTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="false" + android:gravity="center" + android:ellipsize="marquee" + android:textDirection="locale" + android:layout_marginTop="8dp"/> + + <TextView + android:id="@+id/install_type" + style="@style/TextAppearance.EntityHeaderSummary" + android:visibility="gone" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="2dp" + android:text="@string/install_type_instant"/> + + <TextView + android:id="@android:id/summary" + style="@style/TextAppearance.EntityHeaderSummary" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="2dp" + android:singleLine="false" + android:textAlignment="center"/> + + <TextView + android:id="@+id/second_summary" + style="@style/TextAppearance.EntityHeaderSummary" + android:singleLine="false" + android:maxLines="4" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + + </LinearLayout> + +</RelativeLayout> diff --git a/packages/SettingsLib/AppPreference/res/values/strings.xml b/packages/SettingsLib/AppPreference/res/values/strings.xml new file mode 100644 index 000000000000..ca148c00bbb5 --- /dev/null +++ b/packages/SettingsLib/AppPreference/res/values/strings.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- + ~ Copyright (C) 2022 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Added as the value of a header field indicating this is an instant app (as opposed to installed normally) --> + <string name="install_type_instant">Instant app</string> +</resources> diff --git a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppHeaderPreference.java b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppHeaderPreference.java new file mode 100644 index 000000000000..60d00da29755 --- /dev/null +++ b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppHeaderPreference.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2022 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.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +/** + * The Preference for the pages need to show big apps icon and name in the header of the page. + */ +public class AppHeaderPreference extends Preference { + + private boolean mIsInstantApp; + private CharSequence mSecondSummary; + + public AppHeaderPreference(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + public AppHeaderPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + public AppHeaderPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public AppHeaderPreference(Context context) { + super(context); + init(); + } + + private void init() { + setLayoutResource(R.layout.app_header_preference); + setSelectable(false); + setIsInstantApp(false); + } + + /** + * Returns the installation type of this preference. + * + * @return whether the app is an instant app + * @see #setIsInstantApp(boolean) + */ + public boolean getIsInstantApp() { + return mIsInstantApp; + } + + /** + * Sets the installation type for this preference with a boolean. + * + * @param isInstantApp whether the app is an instant app + */ + public void setIsInstantApp(@NonNull boolean isInstantApp) { + if (mIsInstantApp != isInstantApp) { + mIsInstantApp = isInstantApp; + notifyChanged(); + } + } + + /** + * Returns the second summary of this preference. + * + * @return The second summary + * @see #setSecondSummary(CharSequence) + */ + @Nullable + public CharSequence getSecondSummary() { + return mSecondSummary; + } + + /** + * Sets the second summary for this preference with a CharSequence. + * + * @param secondSummary The second summary for the preference + */ + public void setSecondSummary(@Nullable CharSequence secondSummary) { + if (!TextUtils.equals(mSecondSummary, secondSummary)) { + mSecondSummary = secondSummary; + notifyChanged(); + } + } + + /** + * Sets the second summary for this preference with a resource ID. + * + * @param secondSummaryResId The second summary as a resource + * @see #setSecondSummary(CharSequence) + */ + public void setSecondSummary(@StringRes int secondSummaryResId) { + setSecondSummary(getContext().getString(secondSummaryResId)); + } + + @Override + public void onBindViewHolder(@NonNull PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + final TextView installTypeView = (TextView) holder.findViewById(R.id.install_type); + if (installTypeView != null) { + if (mIsInstantApp) { + installTypeView.setVisibility(View.VISIBLE); + } else { + installTypeView.setVisibility(View.GONE); + } + } + + final TextView secondSummaryView = (TextView) holder.findViewById(R.id.second_summary); + if (secondSummaryView != null) { + if (!TextUtils.isEmpty(mSecondSummary)) { + secondSummaryView.setText(mSecondSummary); + secondSummaryView.setVisibility(View.VISIBLE); + } else { + secondSummaryView.setVisibility(View.GONE); + } + } + } +} diff --git a/packages/SettingsLib/LayoutPreference/Android.bp b/packages/SettingsLib/LayoutPreference/Android.bp index aaffdc922875..c29e1f789fd3 100644 --- a/packages/SettingsLib/LayoutPreference/Android.bp +++ b/packages/SettingsLib/LayoutPreference/Android.bp @@ -15,6 +15,7 @@ android_library { static_libs: [ "androidx.preference_preference", + "SettingsLibSettingsTheme", ], sdk_version: "system_current", diff --git a/packages/SettingsLib/LayoutPreference/res/values/styles.xml b/packages/SettingsLib/LayoutPreference/res/values/styles.xml index 2bdd6fe92e1a..f958037cfca6 100644 --- a/packages/SettingsLib/LayoutPreference/res/values/styles.xml +++ b/packages/SettingsLib/LayoutPreference/res/values/styles.xml @@ -22,20 +22,6 @@ <item name="android:paddingEnd">16dp</item> </style> - <style name="TextAppearance.EntityHeaderTitle" - parent="@android:style/TextAppearance.DeviceDefault.WindowTitle"> - <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:textSize">20sp</item> - </style> - - <style name="TextAppearance.EntityHeaderSummary" - parent="@android:style/TextAppearance.DeviceDefault"> - <item name="android:textAlignment">viewStart</item> - <item name="android:textColor">?android:attr/textColorSecondary</item> - <item name="android:singleLine">true</item> - <item name="android:ellipsize">marquee</item> - </style> - <style name="CrossProfileEntityHeaderIcon"> <item name="android:layout_width">48dp</item> <item name="android:layout_height">48dp</item> diff --git a/packages/SettingsLib/SettingsTheme/res/values/styles.xml b/packages/SettingsLib/SettingsTheme/res/values/styles.xml index 00bd14122251..328ab46ed2f9 100644 --- a/packages/SettingsLib/SettingsTheme/res/values/styles.xml +++ b/packages/SettingsLib/SettingsTheme/res/values/styles.xml @@ -33,4 +33,18 @@ <item name="android:textColor">?android:attr/textColorSecondary</item> </style> + <style name="TextAppearance.EntityHeaderTitle" + parent="@android:style/TextAppearance.DeviceDefault.WindowTitle"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textSize">20sp</item> + </style> + + <style name="TextAppearance.EntityHeaderSummary" + parent="@android:style/TextAppearance.DeviceDefault"> + <item name="android:textAlignment">viewStart</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:singleLine">true</item> + <item name="android:ellipsize">marquee</item> + </style> + </resources> diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppHeaderPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppHeaderPreferenceTest.java new file mode 100644 index 000000000000..fd181ff07222 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppHeaderPreferenceTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2021 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.view.View; +import android.widget.TextView; + +import androidx.preference.PreferenceViewHolder; + + + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class AppHeaderPreferenceTest { + + private Context mContext; + private View mRootView; + private AppHeaderPreference mPreference; + private PreferenceViewHolder mHolder; + + @Before + public void setUp() { + mContext = RuntimeEnvironment.application; + mRootView = View.inflate(mContext, R.layout.app_header_preference, /* parent */ null); + mHolder = PreferenceViewHolder.createInstanceForTests(mRootView); + mPreference = new AppHeaderPreference(mContext); + } + + @Test + public void setNonSelectable_viewShouldNotBeSelectable() { + mPreference.onBindViewHolder(mHolder); + + assertThat(mHolder.itemView.isClickable()).isFalse(); + } + + @Test + public void defaultInstallType_viewShouldNotBeVisible() { + mPreference.onBindViewHolder(mHolder); + + assertThat(mRootView.findViewById(R.id.install_type).getVisibility()) + .isEqualTo(View.GONE); + } + + @Test + public void setIsInstantApp_shouldUpdateInstallType() { + + mPreference.onBindViewHolder(mHolder); + mPreference.setIsInstantApp(true); + + assertThat(((TextView) mRootView.findViewById(R.id.install_type)).getText().toString()) + .isEqualTo(mContext.getResources().getString(R.string.install_type_instant)); + } + + @Test + public void setSecondSummary_shouldUpdateSecondSummary() { + final String defaultTestText = "Test second summary"; + + mPreference.onBindViewHolder(mHolder); + mPreference.setSecondSummary(defaultTestText); + + assertThat(((TextView) mRootView.findViewById(R.id.second_summary)).getText().toString()) + .isEqualTo(defaultTestText); + } +} |