diff --git a/res/drawable/homepage_highlighted_item_background.xml b/res/drawable/homepage_highlighted_item_background.xml index b7b24e991a1..d54ff601643 100644 --- a/res/drawable/homepage_highlighted_item_background.xml +++ b/res/drawable/homepage_highlighted_item_background.xml @@ -14,13 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - - \ No newline at end of file + + + + \ No newline at end of file diff --git a/res/drawable/homepage_selectable_item_background.xml b/res/drawable/homepage_selectable_item_background.xml new file mode 100644 index 00000000000..f5e17ea69b7 --- /dev/null +++ b/res/drawable/homepage_selectable_item_background.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/res/layout/homepage_preference.xml b/res/layout/homepage_preference.xml index 62f6457d27f..59dc7c4b176 100644 --- a/res/layout/homepage_preference.xml +++ b/res/layout/homepage_preference.xml @@ -20,10 +20,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:minHeight="@dimen/homepage_preference_min_height" android:gravity="center_vertical" - android:paddingStart="@dimen/homepage_menu_entry_padding_horizontal" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:background="?android:attr/selectableItemBackground" android:clipToPadding="false" android:baselineAligned="false"> @@ -32,11 +30,10 @@ android:id="@+id/icon_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:minWidth="56dp" - android:gravity="center" + android:minWidth="48dp" + android:gravity="end|center_vertical" android:orientation="horizontal" - android:paddingStart="8dp" - android:paddingEnd="8dp" + android:paddingStart="@dimen/homepage_preference_icon_padding_start" android:paddingTop="4dp" android:paddingBottom="4dp"> @@ -44,18 +41,20 @@ android:id="@android:id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:maxWidth="40dp" - app:maxHeight="40dp"/> + app:maxWidth="48dp" + app:maxHeight="48dp"/> + android:paddingStart="@dimen/homepage_preference_text_padding_start" + android:paddingEnd="24dp"> - \ No newline at end of file + diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml index 7cdf04dbd14..dfc9596d9fc 100644 --- a/res/layout/search_bar.xml +++ b/res/layout/search_bar.xml @@ -31,7 +31,8 @@ android:id="@+id/search_action_bar" android:layout_width="match_parent" android:layout_height="@dimen/search_bar_height" - android:paddingStart="4dp" + android:paddingStart="@dimen/search_bar_padding_start" + android:paddingEnd="@dimen/search_bar_padding_end" android:background="@drawable/search_bar_selected_background" android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset" android:navigationIcon="@drawable/ic_homepage_search"> @@ -40,7 +41,7 @@ style="@style/TextAppearance.SearchBar" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingStart="-4dp" + android:paddingStart="@dimen/search_bar_title_padding_start" android:layout_gravity="start" android:text="@string/search_menu"/> diff --git a/res/layout/search_bar_two_pane_version.xml b/res/layout/search_bar_two_pane_version.xml index a869853d4bc..ede57226699 100644 --- a/res/layout/search_bar_two_pane_version.xml +++ b/res/layout/search_bar_two_pane_version.xml @@ -21,20 +21,23 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:layout_margin="@dimen/search_bar_margin"> + android:layout_marginEnd="@dimen/search_bar_margin" + android:layout_marginVertical="@dimen/search_bar_margin"> diff --git a/res/layout/settings_homepage_app_bar_two_pane_layout.xml b/res/layout/settings_homepage_app_bar_two_pane_layout.xml index 4178632603a..4db2e652501 100644 --- a/res/layout/settings_homepage_app_bar_two_pane_layout.xml +++ b/res/layout/settings_homepage_app_bar_two_pane_layout.xml @@ -20,7 +20,6 @@ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="16dp" android:background="?androidprv:attr/colorSurface" android:orientation="vertical"> @@ -41,7 +40,6 @@ android:layout_width="@dimen/avatar_length" android:layout_height="@dimen/avatar_length" android:layout_gravity="center" - android:layout_marginEnd="16dp" android:contentDescription="@string/search_bar_account_avatar_content_description"/> diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml index db1fbbc9be8..2e821e011e6 100755 --- a/res/values-sw600dp/dimens.xml +++ b/res/values-sw600dp/dimens.xml @@ -35,9 +35,6 @@ 80dp - 64dp - 32dp - 24dp 24dp diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 8a59da2844b..2e4d8be77f7 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -129,6 +129,12 @@ 20sp 28dp 56dp + 4dp + 8dp + 16dp + 24dp + -4dp + 8dp 48dp @@ -136,13 +142,16 @@ 24dp 20dp - + 8dp 24dp - - - 16dp - 28dp + 24dp + 28dp + 88sp + 32dp + 8dp + 16dp + 24dp 16dp diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java index 38af8d679cf..fdf13142cb8 100644 --- a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java @@ -16,6 +16,7 @@ package com.android.settings.activityembedding; +import android.app.Activity; import android.content.Context; import android.util.DisplayMetrics; import android.util.FeatureFlagUtils; @@ -33,6 +34,8 @@ public class ActivityEmbeddingUtils { // The smallest value of the smallest-width (sw) of the window in any rotation when // the split should be used. private static final float MIN_SMALLEST_SCREEN_SPLIT_WIDTH_DP = 600f; + // The minimum width of the activity to show the regular homepage layout. + private static final float MIN_REGULAR_HOMEPAGE_LAYOUT_WIDTH_DP = 380f; private static final String TAG = "ActivityEmbeddingUtils"; /** Get the smallest pixel value of width of the window when the split should be used. */ @@ -71,4 +74,11 @@ public class ActivityEmbeddingUtils { return isFlagEnabled && isSplitSupported; } + + /** Whether to show the regular or simplified homepage layout. */ + public static boolean isRegularHomepageLayout(Activity activity) { + DisplayMetrics dm = activity.getResources().getDisplayMetrics(); + return dm.widthPixels >= (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, MIN_REGULAR_HOMEPAGE_LAYOUT_WIDTH_DP, dm); + } } diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 7aeea114c39..038f6727c64 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -86,6 +86,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements private TopLevelSettings mMainFragment; private View mHomepageView; + private View mAppBar; private View mSuggestionView; private View mTwoPaneSuggestionView; private CategoryMixin mCategoryMixin; @@ -93,6 +94,8 @@ public class SettingsHomepageActivity extends FragmentActivity implements private SplitController mSplitController; private boolean mIsEmbeddingActivityEnabled; private boolean mIsTwoPane; + // A regular layout shows icons on homepage, whereas a simplified layout doesn't. + private boolean mIsRegularLayout = true; /** A listener receiving homepage loaded events. */ public interface HomepageLoadedListener { @@ -100,8 +103,11 @@ public class SettingsHomepageActivity extends FragmentActivity implements void onHomepageLoaded(); } - private interface FragmentBuilder { - T build(); + private interface FragmentCreator { + T create(); + + /** To initialize after {@link #create} */ + default void init(Fragment fragment) {} } /** @@ -145,6 +151,11 @@ public class SettingsHomepageActivity extends FragmentActivity implements return mMainFragment; } + /** Whether the activity is showing in two-pane */ + public boolean isTwoPane() { + return mIsTwoPane; + } + @Override public CategoryMixin getCategoryMixin() { return mCategoryMixin; @@ -160,8 +171,8 @@ public class SettingsHomepageActivity extends FragmentActivity implements mSplitController = SplitController.getInstance(); mIsTwoPane = mSplitController.isActivityEmbedded(this); - final View appBar = findViewById(R.id.app_bar_container); - appBar.setMinimumHeight(getSearchBoxHeight()); + mAppBar = findViewById(R.id.app_bar_container); + mAppBar.setMinimumHeight(getSearchBoxHeight()); initHomepageContainer(); updateHomepageAppBar(); updateHomepageBackground(); @@ -195,6 +206,8 @@ public class SettingsHomepageActivity extends FragmentActivity implements // Launch the intent from deep link for large screen devices. launchDeepLinkIntentToRight(); + updateHomepagePaddings(); + updateSplitLayout(); } @Override @@ -226,7 +239,42 @@ public class SettingsHomepageActivity extends FragmentActivity implements mIsTwoPane = newTwoPaneState; updateHomepageAppBar(); updateHomepageBackground(); + updateHomepagePaddings(); } + updateSplitLayout(); + } + + private void updateSplitLayout() { + if (!mIsEmbeddingActivityEnabled) { + return; + } + + if (mIsTwoPane) { + if (mIsRegularLayout == ActivityEmbeddingUtils.isRegularHomepageLayout(this)) { + // Layout unchanged + return; + } + } else if (mIsRegularLayout) { + // One pane mode with the regular layout, not needed to change + return; + } + mIsRegularLayout = !mIsRegularLayout; + + // Update search title padding + View searchTitle = findViewById(R.id.search_bar_title); + if (searchTitle != null) { + int paddingStart = getResources().getDimensionPixelSize( + mIsRegularLayout + ? R.dimen.search_bar_title_padding_start_regular_two_pane + : R.dimen.search_bar_title_padding_start); + searchTitle.setPaddingRelative(paddingStart, 0, 0, 0); + } + // Notify fragments + getSupportFragmentManager().getFragments().forEach(fragment -> { + if (fragment instanceof SplitLayoutListener) { + ((SplitLayoutListener) fragment).onSplitLayoutChanged(mIsRegularLayout); + } + }); } private void setupEdgeToEdge() { @@ -303,29 +351,25 @@ public class SettingsHomepageActivity extends FragmentActivity implements // Schedule a timer to show the homepage and hide the suggestion on timeout. mHomepageView.postDelayed(() -> showHomepageWithSuggestion(false), HOMEPAGE_LOADING_TIMEOUT_MS); - final FragmentBuilder fragmentBuilder = () -> { - try { - return fragmentClass.getConstructor().newInstance(); - } catch (Exception e) { - Log.w(TAG, "Cannot show fragment", e); - } - return null; - }; - showFragment(fragmentBuilder, R.id.suggestion_content); + showFragment(new SuggestionFragCreator(fragmentClass, /* isTwoPaneLayout= */ false), + R.id.suggestion_content); if (mIsEmbeddingActivityEnabled) { - showFragment(fragmentBuilder, R.id.two_pane_suggestion_content); + showFragment(new SuggestionFragCreator(fragmentClass, /* isTwoPaneLayout= */ true), + R.id.two_pane_suggestion_content); } } - private T showFragment(FragmentBuilder fragmentBuilder, int id) { + private T showFragment(FragmentCreator fragmentCreator, int id) { final FragmentManager fragmentManager = getSupportFragmentManager(); final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); T showFragment = (T) fragmentManager.findFragmentById(id); if (showFragment == null) { - showFragment = fragmentBuilder.build(); + showFragment = fragmentCreator.create(); + fragmentCreator.init(showFragment); fragmentTransaction.add(id, showFragment); } else { + fragmentCreator.init(showFragment); fragmentTransaction.show(showFragment); } fragmentTransaction.commit(); @@ -447,9 +491,54 @@ public class SettingsHomepageActivity extends FragmentActivity implements } } + private void updateHomepagePaddings() { + if (!mIsEmbeddingActivityEnabled) { + return; + } + if (mIsTwoPane) { + int padding = getResources().getDimensionPixelSize( + R.dimen.homepage_padding_horizontal_two_pane); + mAppBar.setPaddingRelative(padding, 0, padding, 0); + mMainFragment.setPaddingHorizontal(padding); + } else { + mAppBar.setPaddingRelative(0, 0, 0, 0); + mMainFragment.setPaddingHorizontal(0); + } + mMainFragment.updatePreferencePadding(mIsTwoPane); + } + private int getSearchBoxHeight() { final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height); final int searchBarMargin = getResources().getDimensionPixelSize(R.dimen.search_bar_margin); return searchBarHeight + searchBarMargin * 2; } + + private static class SuggestionFragCreator implements FragmentCreator { + + private final Class mClass; + private final boolean mIsTwoPaneLayout; + + SuggestionFragCreator(Class clazz, boolean isTwoPaneLayout) { + mClass = clazz; + mIsTwoPaneLayout = isTwoPaneLayout; + } + + @Override + public Fragment create() { + try { + Fragment fragment = mClass.getConstructor().newInstance(); + return fragment; + } catch (Exception e) { + Log.w(TAG, "Cannot show fragment", e); + } + return null; + } + + @Override + public void init(Fragment fragment) { + if (fragment instanceof SplitLayoutListener) { + ((SplitLayoutListener) fragment).setSplitLayoutSupported(mIsTwoPaneLayout); + } + } + } } diff --git a/src/com/android/settings/homepage/SplitLayoutListener.java b/src/com/android/settings/homepage/SplitLayoutListener.java new file mode 100644 index 00000000000..63f4bc4e862 --- /dev/null +++ b/src/com/android/settings/homepage/SplitLayoutListener.java @@ -0,0 +1,34 @@ +/* + * 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.settings.homepage; + +/** A listener receiving the spilt layout change */ +public interface SplitLayoutListener { + + /** + * Called when the spilt layout is changed. + * + * @param isRegularLayout whether the layout should be regular or simplified + */ + void onSplitLayoutChanged(boolean isRegularLayout); + + /** + * Notifies the listener whether the split layout is supported. + */ + default void setSplitLayoutSupported(boolean supported) { + } +} diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java index 334462b0b46..8623509ce9b 100644 --- a/src/com/android/settings/homepage/TopLevelSettings.java +++ b/src/com/android/settings/homepage/TopLevelSettings.java @@ -27,6 +27,8 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; +import android.view.LayoutInflater; +import android.view.ViewGroup; import androidx.fragment.app.Fragment; import androidx.preference.Preference; @@ -44,12 +46,13 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.support.SupportPreferenceController; import com.android.settings.widget.HomepagePreference; +import com.android.settings.widget.HomepagePreferenceLayoutHelper.HomepagePreferenceLayout; import com.android.settingslib.core.instrumentation.Instrumentable; import com.android.settingslib.drawer.Tile; import com.android.settingslib.search.SearchIndexable; @SearchIndexable(forTarget = MOBILE) -public class TopLevelSettings extends DashboardFragment implements +public class TopLevelSettings extends DashboardFragment implements SplitLayoutListener, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { private static final String TAG = "TopLevelSettings"; @@ -58,6 +61,7 @@ public class TopLevelSettings extends DashboardFragment implements private boolean mIsEmbeddingActivityEnabled; private TopLevelHighlightMixin mHighlightMixin; + private int mPaddingHorizontal; private boolean mScrollNeeded = true; private boolean mFirstStarted = true; @@ -177,23 +181,13 @@ public class TopLevelSettings extends DashboardFragment implements @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { super.onCreatePreferences(savedInstanceState, rootKey); - final PreferenceScreen screen = getPreferenceScreen(); - if (screen == null) { - return; - } - // Tint the homepage icons - final int tintColor = Utils.getHomepageIconColor(getContext()); - final int count = screen.getPreferenceCount(); - for (int i = 0; i < count; i++) { - final Preference preference = screen.getPreference(i); - if (preference == null) { - break; - } - final Drawable icon = preference.getIcon(); + int tintColor = Utils.getHomepageIconColor(getContext()); + iteratePreferences(preference -> { + Drawable icon = preference.getIcon(); if (icon != null) { icon.setTint(tintColor); } - } + }); } @Override @@ -202,6 +196,15 @@ public class TopLevelSettings extends DashboardFragment implements highlightPreferenceIfNeeded(); } + @Override + public void onSplitLayoutChanged(boolean isRegularLayout) { + iteratePreferences(preference -> { + if (preference instanceof HomepagePreferenceLayout) { + ((HomepagePreferenceLayout) preference).getHelper().setIconVisible(isRegularLayout); + } + }); + } + @Override public void highlightPreferenceIfNeeded() { if (mHighlightMixin != null) { @@ -209,6 +212,52 @@ public class TopLevelSettings extends DashboardFragment implements } } + @Override + public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent, + Bundle savedInstanceState) { + RecyclerView recyclerView = super.onCreateRecyclerView(inflater, parent, + savedInstanceState); + recyclerView.setPadding(mPaddingHorizontal, 0, mPaddingHorizontal, 0); + return recyclerView; + } + + /** Sets the horizontal padding */ + public void setPaddingHorizontal(int padding) { + mPaddingHorizontal = padding; + RecyclerView recyclerView = getListView(); + if (recyclerView != null) { + recyclerView.setPadding(padding, 0, padding, 0); + } + } + + /** Updates the preference internal paddings */ + public void updatePreferencePadding(boolean isTwoPane) { + iteratePreferences(new PreferenceJob() { + private int mIconPaddingStart; + private int mTextPaddingStart; + + @Override + public void init() { + mIconPaddingStart = getResources().getDimensionPixelSize(isTwoPane + ? R.dimen.homepage_preference_icon_padding_start_two_pane + : R.dimen.homepage_preference_icon_padding_start); + mTextPaddingStart = getResources().getDimensionPixelSize(isTwoPane + ? R.dimen.homepage_preference_text_padding_start_two_pane + : R.dimen.homepage_preference_text_padding_start); + } + + @Override + public void doForEach(Preference preference) { + if (preference instanceof HomepagePreferenceLayout) { + ((HomepagePreferenceLayout) preference).getHelper() + .setIconPaddingStart(mIconPaddingStart); + ((HomepagePreferenceLayout) preference).getHelper() + .setTextPaddingStart(mTextPaddingStart); + } + } + }); + } + /** Returns a {@link TopLevelHighlightMixin} that performs highlighting */ public TopLevelHighlightMixin getHighlightMixin() { return mHighlightMixin; @@ -261,6 +310,31 @@ public class TopLevelSettings extends DashboardFragment implements } } + private void iteratePreferences(PreferenceJob job) { + if (job == null || getPreferenceManager() == null) { + return; + } + PreferenceScreen screen = getPreferenceScreen(); + if (screen == null) { + return; + } + + job.init(); + int count = screen.getPreferenceCount(); + for (int i = 0; i < count; i++) { + Preference preference = screen.getPreference(i); + if (preference == null) { + break; + } + job.doForEach(preference); + } + } + + private interface PreferenceJob { + default void init() {} + void doForEach(Preference preference); + } + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.top_level_settings) { diff --git a/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java b/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java index 911aabb13b8..338be483b6d 100644 --- a/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java +++ b/src/com/android/settings/widget/HighlightableTopLevelPreferenceAdapter.java @@ -21,7 +21,6 @@ import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -46,6 +45,10 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt private static final String TAG = "HighlightableTopLevelAdapter"; static final long DELAY_HIGHLIGHT_DURATION_MILLIS = 100L; + private static final int RES_NORMAL_BACKGROUND = + R.drawable.homepage_selectable_item_background; + private static final int RES_HIGHLIGHTED_BACKGROUND = + R.drawable.homepage_highlighted_item_background; private final int mTitleColorNormal; private final int mTitleColorHighlight; @@ -54,11 +57,8 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt private final int mIconColorNormal; private final int mIconColorHighlight; - private final Context mContext; private final SettingsHomepageActivity mHomepageActivity; private final RecyclerView mRecyclerView; - private final int mNormalBackgroundRes; - private final int mHighlightBackgroundRes; private String mHighlightKey; private int mHighlightPosition = RecyclerView.NO_POSITION; private int mScrollPosition = RecyclerView.NO_POSITION; @@ -74,23 +74,18 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt mHighlightKey = key; mScrolled = !scrollNeeded; mViewHolders = new SparseArray<>(); - mContext = preferenceGroup.getContext(); mHomepageActivity = homepageActivity; - final TypedValue outValue = new TypedValue(); - mContext.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, - outValue, true /* resolveRefs */); - mNormalBackgroundRes = outValue.resourceId; - mHighlightBackgroundRes = R.drawable.homepage_highlighted_item_background; - mTitleColorNormal = Utils.getColorAttrDefaultColor(mContext, + Context context = preferenceGroup.getContext(); + mTitleColorNormal = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary); - mTitleColorHighlight = Utils.getColorAttrDefaultColor(mContext, + mTitleColorHighlight = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimaryInverse); - mSummaryColorNormal = Utils.getColorAttrDefaultColor(mContext, + mSummaryColorNormal = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary); - mSummaryColorHighlight = Utils.getColorAttrDefaultColor(mContext, + mSummaryColorHighlight = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondaryInverse); - mIconColorNormal = Utils.getHomepageIconColor(mContext); - mIconColorHighlight = Utils.getHomepageIconColorHighlight(mContext); + mIconColorNormal = Utils.getHomepageIconColor(context); + mIconColorHighlight = Utils.getHomepageIconColorHighlight(context); } @Override @@ -236,7 +231,7 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt private void addHighlightBackground(PreferenceViewHolder holder) { final View v = holder.itemView; - v.setBackgroundResource(mHighlightBackgroundRes); + v.setBackgroundResource(RES_HIGHLIGHTED_BACKGROUND); ((TextView) v.findViewById(android.R.id.title)).setTextColor(mTitleColorHighlight); ((TextView) v.findViewById(android.R.id.summary)).setTextColor(mSummaryColorHighlight); final Drawable drawable = ((ImageView) v.findViewById(android.R.id.icon)).getDrawable(); @@ -247,7 +242,7 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt private void removeHighlightBackground(PreferenceViewHolder holder) { final View v = holder.itemView; - v.setBackgroundResource(mNormalBackgroundRes); + v.setBackgroundResource(RES_NORMAL_BACKGROUND); ((TextView) v.findViewById(android.R.id.title)).setTextColor(mTitleColorNormal); ((TextView) v.findViewById(android.R.id.summary)).setTextColor(mSummaryColorNormal); final Drawable drawable = ((ImageView) v.findViewById(android.R.id.icon)).getDrawable(); diff --git a/src/com/android/settings/widget/HomepagePreference.java b/src/com/android/settings/widget/HomepagePreference.java index ff4055ee226..d0780622631 100644 --- a/src/com/android/settings/widget/HomepagePreference.java +++ b/src/com/android/settings/widget/HomepagePreference.java @@ -20,29 +20,43 @@ import android.content.Context; import android.util.AttributeSet; import androidx.preference.Preference; - -import com.android.settings.R; +import androidx.preference.PreferenceViewHolder; /** A customized layout for homepage preference. */ -public class HomepagePreference extends Preference { +public class HomepagePreference extends Preference implements + HomepagePreferenceLayoutHelper.HomepagePreferenceLayout { + + private final HomepagePreferenceLayoutHelper mHelper; + public HomepagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); } public HomepagePreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); } public HomepagePreference(Context context, AttributeSet attrs) { super(context, attrs); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); } public HomepagePreference(Context context) { super(context); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + mHelper.onBindViewHolder(holder); + } + + @Override + public HomepagePreferenceLayoutHelper getHelper() { + return mHelper; } } diff --git a/src/com/android/settings/widget/HomepagePreferenceLayoutHelper.java b/src/com/android/settings/widget/HomepagePreferenceLayoutHelper.java new file mode 100644 index 00000000000..6242e23000c --- /dev/null +++ b/src/com/android/settings/widget/HomepagePreferenceLayoutHelper.java @@ -0,0 +1,78 @@ +/* + * 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.settings.widget; + +import android.view.View; + +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import com.android.settings.R; + +/** Helper for homepage preference to manage layout. */ +public class HomepagePreferenceLayoutHelper { + + private View mIcon; + private View mText; + private boolean mIconVisible = true; + private int mIconPaddingStart = -1; + private int mTextPaddingStart = -1; + + /** The interface for managing preference layouts on homepage */ + public interface HomepagePreferenceLayout { + /** Returns a {@link HomepagePreferenceLayoutHelper} */ + HomepagePreferenceLayoutHelper getHelper(); + } + + public HomepagePreferenceLayoutHelper(Preference preference) { + preference.setLayoutResource(R.layout.homepage_preference); + } + + /** Sets whether the icon should be visible */ + public void setIconVisible(boolean visible) { + mIconVisible = visible; + if (mIcon != null) { + mIcon.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + + /** Sets the icon padding start */ + public void setIconPaddingStart(int paddingStart) { + mIconPaddingStart = paddingStart; + if (mIcon != null && paddingStart >= 0) { + mIcon.setPaddingRelative(paddingStart, mIcon.getPaddingTop(), mIcon.getPaddingEnd(), + mIcon.getPaddingBottom()); + } + } + + /** Sets the text padding start */ + public void setTextPaddingStart(int paddingStart) { + mTextPaddingStart = paddingStart; + if (mText != null && paddingStart >= 0) { + mText.setPaddingRelative(paddingStart, mText.getPaddingTop(), mText.getPaddingEnd(), + mText.getPaddingBottom()); + } + } + + void onBindViewHolder(PreferenceViewHolder holder) { + mIcon = holder.findViewById(R.id.icon_frame); + mText = holder.findViewById(R.id.text_frame); + setIconVisible(mIconVisible); + setIconPaddingStart(mIconPaddingStart); + setTextPaddingStart(mTextPaddingStart); + } +} diff --git a/src/com/android/settings/widget/RestrictedHomepagePreference.java b/src/com/android/settings/widget/RestrictedHomepagePreference.java index 4667e2ce314..fbd6d4af097 100644 --- a/src/com/android/settings/widget/RestrictedHomepagePreference.java +++ b/src/com/android/settings/widget/RestrictedHomepagePreference.java @@ -19,29 +19,45 @@ package com.android.settings.widget; import android.content.Context; import android.util.AttributeSet; -import com.android.settings.R; +import androidx.preference.PreferenceViewHolder; + import com.android.settingslib.RestrictedTopLevelPreference; /** Homepage preference that can be disabled by a device admin using a user restriction. */ -public class RestrictedHomepagePreference extends RestrictedTopLevelPreference { +public class RestrictedHomepagePreference extends RestrictedTopLevelPreference implements + HomepagePreferenceLayoutHelper.HomepagePreferenceLayout { + + private final HomepagePreferenceLayoutHelper mHelper; + public RestrictedHomepagePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); } public RestrictedHomepagePreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); } public RestrictedHomepagePreference(Context context, AttributeSet attrs) { super(context, attrs); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); } public RestrictedHomepagePreference(Context context) { super(context); - setLayoutResource(R.layout.homepage_preference); + mHelper = new HomepagePreferenceLayoutHelper(this); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + mHelper.onBindViewHolder(holder); + } + + @Override + public HomepagePreferenceLayoutHelper getHelper() { + return mHelper; } } diff --git a/tests/robotests/src/com/android/settings/homepage/TopLevelSettingsTest.java b/tests/robotests/src/com/android/settings/homepage/TopLevelSettingsTest.java index da2f8b5e566..44f44aa8589 100644 --- a/tests/robotests/src/com/android/settings/homepage/TopLevelSettingsTest.java +++ b/tests/robotests/src/com/android/settings/homepage/TopLevelSettingsTest.java @@ -30,6 +30,7 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import androidx.preference.Preference; +import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import com.android.settings.R; @@ -73,6 +74,7 @@ public class TopLevelSettingsTest { doReturn(1).when(screen).getPreferenceCount(); doReturn(preference).when(screen).getPreference(anyInt()); doReturn(screen).when(mSettings).getPreferenceScreen(); + doReturn(new PreferenceManager(mContext)).when(mSettings).getPreferenceManager(); doReturn(0).when(mSettings).getPreferenceScreenResId(); mSettings.onCreatePreferences(new Bundle(), "rootKey");