Add infrastructure for extra customization sections
Bug: 175869253
Test: Build WPPG and install to run
Change-Id: Ib0c1edb0e1b0529bd3326f8d4df502f4dfc56b76
diff --git a/src/com/android/customization/model/CustomizationManager.java b/src/com/android/customization/model/CustomizationManager.java
index 7b9f463..efc4c74 100644
--- a/src/com/android/customization/model/CustomizationManager.java
+++ b/src/com/android/customization/model/CustomizationManager.java
@@ -16,7 +16,6 @@
package com.android.customization.model;
import android.util.Log;
-import android.widget.Toast;
import androidx.annotation.Nullable;
@@ -29,6 +28,20 @@
public interface CustomizationManager<T extends CustomizationOption> {
/**
+ * Create a new {@link CustomizationSection} corresponding to this Manager
+ */
+ default CustomizationSection<T> createSection() {
+ return null;
+ }
+
+ /**
+ * @return the id in the navigation menu for the section this Manager manages.
+ */
+ default int getNavId() {
+ return 0;
+ };
+
+ /**
* Callback for applying a customization option.
*/
interface Callback {
diff --git a/src/com/android/customization/model/CustomizationSection.java b/src/com/android/customization/model/CustomizationSection.java
new file mode 100644
index 0000000..da1b4f8
--- /dev/null
+++ b/src/com/android/customization/model/CustomizationSection.java
@@ -0,0 +1,52 @@
+/*
+ * 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.customization.model;
+
+import android.content.Context;
+
+import androidx.annotation.IdRes;
+import androidx.fragment.app.Fragment;
+
+/**
+ * Represents a section of the Picker (eg "ThemeBundle", "Clock", etc).
+ * There should be a concrete subclass per available section, providing the corresponding
+ * Fragment to be displayed when switching to each section.
+ * @param <T> CustomizationOption that this section represents.
+ */
+public abstract class CustomizationSection<T extends CustomizationOption> {
+
+ /**
+ * IdRes used to identify this section in the BottomNavigationView menu.
+ */
+ @IdRes
+ public final int id;
+ protected final CustomizationManager<T> mCustomizationManager;
+
+ public CustomizationSection(@IdRes int id, CustomizationManager<T> manager) {
+ this.id = id;
+ mCustomizationManager = manager;
+ }
+
+ /**
+ * @return the Fragment corresponding to this section.
+ */
+ public abstract Fragment getFragment(Context c);
+
+ public CustomizationManager<T> getCustomizationManager() {
+ return mCustomizationManager;
+ }
+
+}
diff --git a/src/com/android/customization/module/CustomizationInjector.java b/src/com/android/customization/module/CustomizationInjector.java
index 85853de..913b686 100644
--- a/src/com/android/customization/module/CustomizationInjector.java
+++ b/src/com/android/customization/module/CustomizationInjector.java
@@ -19,6 +19,7 @@
import androidx.fragment.app.FragmentActivity;
+import com.android.customization.model.CustomizationManager;
import com.android.customization.model.theme.OverlayManagerCompat;
import com.android.customization.model.theme.ThemeBundleProvider;
import com.android.customization.model.theme.ThemeManager;
@@ -30,4 +31,12 @@
ThemeManager getThemeManager(ThemeBundleProvider provider, FragmentActivity activity,
OverlayManagerCompat overlayManagerCompat, ThemesUserEventLogger logger);
+
+ /**
+ * Obtain an extra CustomizationManager to add to the bottom nav
+ */
+ default CustomizationManager<?> getExtraManager(FragmentActivity activity,
+ OverlayManagerCompat overlayManagerCompat, ThemesUserEventLogger eventLogger) {
+ return null;
+ }
}
diff --git a/src/com/android/customization/picker/CustomizationFragmentHost.java b/src/com/android/customization/picker/CustomizationFragmentHost.java
new file mode 100644
index 0000000..d700ec6
--- /dev/null
+++ b/src/com/android/customization/picker/CustomizationFragmentHost.java
@@ -0,0 +1,30 @@
+/*
+ * 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.customization.picker;
+
+import com.android.customization.model.CustomizationManager;
+
+/**
+ * Interface to be implemented by an Activity hosting any Customization Fragment
+ */
+public interface CustomizationFragmentHost {
+
+ /**
+ * Gets the CustomizationManager manager for the given section
+ * @return the {@link CustomizationManager}
+ */
+ CustomizationManager<?> getCustomizationManager(int sectionId);
+}
diff --git a/src/com/android/customization/picker/CustomizationPickerActivity.java b/src/com/android/customization/picker/CustomizationPickerActivity.java
index 45f4cf4..d28ee66 100644
--- a/src/com/android/customization/picker/CustomizationPickerActivity.java
+++ b/src/com/android/customization/picker/CustomizationPickerActivity.java
@@ -16,6 +16,7 @@
package com.android.customization.picker;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
@@ -37,7 +38,7 @@
import androidx.fragment.app.FragmentTransaction;
import com.android.customization.model.CustomizationManager;
-import com.android.customization.model.CustomizationOption;
+import com.android.customization.model.CustomizationSection;
import com.android.customization.model.clock.ClockManager;
import com.android.customization.model.clock.Clockface;
import com.android.customization.model.clock.ContentProviderClockProvider;
@@ -90,8 +91,9 @@
* Fragments providing customization options.
*/
public class CustomizationPickerActivity extends FragmentActivity implements WallpapersUiContainer,
- CategoryFragmentHost, ThemeFragmentHost, GridFragmentHost, ClockFragmentHost,
- BottomActionBarHost, FragmentTransactionChecker {
+ CategoryFragmentHost, CustomizationFragmentHost,
+ ThemeFragmentHost, GridFragmentHost,
+ ClockFragmentHost, BottomActionBarHost, FragmentTransactionChecker {
public static final String WALLPAPER_FLAVOR_EXTRA =
"com.android.launcher3.WALLPAPER_FLAVOR";
@@ -180,7 +182,6 @@
// Keep CategoryFragment's design to load category within its fragment
if (section instanceof WallpaperSection) {
switchFragment(section);
- section.onVisible();
}
}
@@ -232,6 +233,11 @@
CustomizationInjector injector = (CustomizationInjector) InjectorProvider.getInjector();
ThemesUserEventLogger eventLogger = (ThemesUserEventLogger) injector.getUserEventLogger(
this);
+ CustomizationManager<?> extraManager = injector.getExtraManager(
+ this, new OverlayManagerCompat(this), eventLogger);
+ if (extraManager != null && extraManager.isAvailable()) {
+ mSections.put(extraManager.getNavId(), extraManager.createSection());
+ }
ThemeManager themeManager = injector.getThemeManager(
new DefaultThemeProvider(this, injector.getCustomizationPreferences(this)),
this, new OverlayManagerCompat(this), eventLogger);
@@ -280,7 +286,6 @@
int id = item.getItemId();
CustomizationSection section = mSections.get(id);
switchFragment(section);
- section.onVisible();
String name = getResources().getResourceName(id);
if (!prefs.getTabVisited(name)) {
prefs.setTabVisited(name);
@@ -357,7 +362,7 @@
private void switchFragment(CustomizationSection section) {
final FragmentManager fragmentManager = getSupportFragmentManager();
- Fragment fragment = section.getFragment();
+ Fragment fragment = section.getFragment(this);
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
@@ -427,22 +432,29 @@
return mDelegate;
}
+
+ @Override
+ public CustomizationManager<?> getCustomizationManager(int id) {
+ CustomizationSection<?> section = mSections.get(id);
+ return section == null ? null : section.getCustomizationManager();
+ }
+
@Override
public ClockManager getClockManager() {
CustomizationSection section = mSections.get(R.id.nav_clock);
- return section == null ? null : (ClockManager) section.customizationManager;
+ return section == null ? null : (ClockManager) section.getCustomizationManager();
}
@Override
public GridOptionsManager getGridOptionsManager() {
CustomizationSection section = mSections.get(R.id.nav_grid);
- return section == null ? null : (GridOptionsManager) section.customizationManager;
+ return section == null ? null : (GridOptionsManager) section.getCustomizationManager();
}
@Override
public ThemeManager getThemeManager() {
CustomizationSection section = mSections.get(R.id.nav_theme);
- return section == null ? null : (ThemeManager) section.customizationManager;
+ return section == null ? null : (ThemeManager) section.getCustomizationManager();
}
@Override
@@ -476,32 +488,6 @@
}
/**
- * Represents a section of the Picker (eg "ThemeBundle", "Clock", etc).
- * There should be a concrete subclass per available section, providing the corresponding
- * Fragment to be displayed when switching to each section.
- */
- static abstract class CustomizationSection<T extends CustomizationOption> {
-
- /**
- * IdRes used to identify this section in the BottomNavigationView menu.
- */
- @IdRes final int id;
- protected final CustomizationManager<T> customizationManager;
-
- private CustomizationSection(@IdRes int id, CustomizationManager<T> manager) {
- this.id = id;
- this.customizationManager = manager;
- }
-
- /**
- * @return the Fragment corresponding to this section.
- */
- abstract Fragment getFragment();
-
- void onVisible() {}
- }
-
- /**
* {@link CustomizationSection} corresponding to the "Wallpaper" section of the Picker.
*/
private class WallpaperSection extends CustomizationSection {
@@ -511,7 +497,7 @@
}
@Override
- Fragment getFragment() {
+ public Fragment getFragment(Context c) {
if (mWallpaperCategoryFragment == null) {
mWallpaperCategoryFragment = CategoryFragment.newInstance(
getString(R.string.wallpaper_title));
@@ -529,7 +515,7 @@
}
@Override
- Fragment getFragment() {
+ public Fragment getFragment(Context c) {
if (mFragment == null) {
mFragment = ThemeFragment.newInstance(getString(R.string.theme_title));
}
@@ -546,7 +532,7 @@
}
@Override
- Fragment getFragment() {
+ public Fragment getFragment(Context c) {
if (mFragment == null) {
mFragment = GridFragment.newInstance(getString(R.string.grid_title));
}
@@ -563,7 +549,7 @@
}
@Override
- Fragment getFragment() {
+ public Fragment getFragment(Context c) {
if (mFragment == null) {
mFragment = ClockFragment.newInstance(getString(R.string.clock_title));
}
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java
index db09aa6..47b0aa7 100644
--- a/src/com/android/customization/widget/OptionSelectorController.java
+++ b/src/com/android/customization/widget/OptionSelectorController.java
@@ -153,6 +153,17 @@
}
/**
+ * Notify that a given option has changed.
+ * @param option the option that changed
+ */
+ public void optionChanged(T option) {
+ if (!mOptions.contains(option)) {
+ throw new IllegalArgumentException("Invalid option");
+ }
+ mAdapter.notifyItemChanged(mOptions.indexOf(option));
+ }
+
+ /**
* Initializes the UI for the options passed in the constructor of this class.
*/
public void initOptions(final CustomizationManager<T> manager) {