Merge "Setting targetSdkVersion to 29 for ThemePicker" into ub-launcher3-qt-dev
diff --git a/res/color/edittext_background_color.xml b/res/color/edittext_background_color.xml
new file mode 100644
index 0000000..9191154
--- /dev/null
+++ b/res/color/edittext_background_color.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.16" android:color="@color/edit_background_base" android:state_hovered="true"/>
+ <item android:alpha="0.04" android:color="@color/edit_background_base" android:state_enabled="false"/>
+ <item android:alpha="0.05" android:color="@color/edit_background_base"/>
+</selector>
\ No newline at end of file
diff --git a/res/color/edittext_text_color.xml b/res/color/edittext_text_color.xml
new file mode 100644
index 0000000..174f6ca
--- /dev/null
+++ b/res/color/edittext_text_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="?android:textColorPrimaryNoDisable" android:state_focused="true"/>
+ <item android:alpha="0.4" android:color="?android:textColorPrimaryNoDisable"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/edittext_background.xml b/res/drawable/edittext_background.xml
new file mode 100644
index 0000000..8fa91c3
--- /dev/null
+++ b/res/drawable/edittext_background.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/edittext_background_color"/>
+ <corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:topLeftRadius="4dp" android:topRightRadius="4dp"/>
+ </shape>
+ </item>
+ <item android:gravity="bottom">
+ <shape android:shape="rectangle">
+ <solid android:color="?android:colorAccent"/>
+ <size android:height="1dp"/>
+ </shape>
+ </item>
+</layer-list>
+
diff --git a/res/layout-land/fragment_custom_theme_name.xml b/res/layout-land/fragment_custom_theme_name.xml
new file mode 100644
index 0000000..0f190a8
--- /dev/null
+++ b/res/layout-land/fragment_custom_theme_name.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="?android:colorPrimary">
+ <include layout="@layout/section_header"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+ <FrameLayout
+ android:id="@+id/component_preview_container"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@color/secondary_color">
+ <include
+ android:id="@+id/component_preview_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginHorizontal="@dimen/preview_page_horizontal_margin"
+ android:layout_marginTop="@dimen/preview_page_top_margin"
+ android:layout_marginBottom="@dimen/component_preview_page_bottom_margin"
+ layout="@layout/theme_preview_card"/>
+ </FrameLayout>
+ <LinearLayout
+ android:id="@+id/options_section"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingTop="10dp"
+ android:paddingBottom="@dimen/custom_theme_nav_height"
+ android:paddingVertical="10dp"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/component_options_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_margin="10dp"
+ android:textAlignment="center"
+ android:textAppearance="@style/HeaderTextAppearance"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/options_container_height"
+ android:layout_gravity="center">
+
+ <EditText
+ style="@style/CustomThemeNameEditText"
+ android:id="@+id/custom_theme_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:minWidth="300dp"/>
+ </FrameLayout>
+
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/fragment_custom_theme_name.xml b/res/layout/fragment_custom_theme_name.xml
new file mode 100644
index 0000000..98feb60
--- /dev/null
+++ b/res/layout/fragment_custom_theme_name.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:background="?android:colorPrimary">
+ <include layout="@layout/section_header"/>
+
+ <FrameLayout
+ android:id="@+id/component_preview_container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:background="@color/secondary_color">
+ <include
+ android:id="@+id/component_preview_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginHorizontal="@dimen/preview_page_horizontal_margin"
+ android:layout_marginTop="@dimen/preview_page_top_margin"
+ android:layout_marginBottom="@dimen/component_preview_page_bottom_margin"
+ layout="@layout/theme_preview_card"/>
+ </FrameLayout>
+ <LinearLayout
+ android:id="@+id/options_section"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="10dp"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/component_options_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_margin="10dp"
+ android:textAlignment="center"
+ android:textAppearance="@style/HeaderTextAppearance"/>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/options_container_height"
+ android:layout_gravity="center">
+
+ <EditText
+ style="@style/CustomThemeNameEditText"
+ android:id="@+id/custom_theme_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:minWidth="300dp"/>
+ </FrameLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 1ddfc10..6a79445 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -38,4 +38,6 @@
<color name="toolbar_color">#000000</color>
<color name="divider_color">@color/white_14_alpha</color>
+
+ <color name="edit_background_base">@color/material_white_100</color>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index ad4c1d2..68ad908 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -57,4 +57,6 @@
<color name="toolbar_color">@color/material_white_100</color>
<color name="divider_color">@color/black_14_alpha</color>
+
+ <color name="edit_background_base">@color/google_grey700</color>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 217b0ef..46de146 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -133,18 +133,21 @@
[CHAR LIMIT=30] -->
<string name="custom_theme_delete">Delete</string>
- <!-- Title of a page allowing the user to choose a font for a custom theme -->
+ <!-- Title of a page allowing the user to choose a font for a custom theme [CHAR LIMIT=40]-->
<string name="font_component_title">Choose font</string>
- <!-- Title of a page allowing the user to choose an icon set for a custom theme -->
+ <!-- Title of a page allowing the user to choose an icon set for a custom theme [CHAR LIMIT=40]-->
<string name="icon_component_title">Choose icons</string>
- <!-- Title of a page allowing the user to choose a color for a custom theme -->
+ <!-- Title of a page allowing the user to choose a color for a custom theme [CHAR LIMIT=40]-->
<string name="color_component_title">Choose color</string>
- <!-- Title of a page allowing the user to choose an icon shape for a custom theme -->
+ <!-- Title of a page allowing the user to choose an icon shape for a custom theme [CHAR LIMIT=40]-->
<string name="shape_component_title">Choose shape</string>
+ <!-- Title of a page allowing the user to set a name for a custom theme [CHAR LIMIT=40]-->
+ <string name="name_component_title">Name your style</string>
+
<!-- Title of a set of icons that the user can chose for their custom style (eg, "Icons 2") -->
<string name="icon_component_label">Icons <xliff:g name="component_number" example="1">%1$d</xliff:g></string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 345a3ee..7ccdbe2 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -105,4 +105,15 @@
<style name="EditLabelStyle">
<item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault</item>
</style>
+
+ <style name="CustomThemeNameEditText" parent="@android:style/Widget.DeviceDefault.EditText">
+ <item name="android:background">@drawable/edittext_background</item>
+ <item name="android:paddingTop">16dp</item>
+ <item name="android:paddingBottom">16dp</item>
+ <item name="android:paddingStart">12dp</item>
+ <item name="android:paddingEnd">12dp</item>
+ <item name="android:textColor">@color/edittext_text_color</item>
+ <item name="android:inputType">text</item>
+ <item name="android:maxLength">100</item>
+ </style>
</resources>
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index c1c6bbe..5123910 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -373,14 +373,15 @@
}
} catch (JSONException e) {
Log.w(TAG, "Couldn't read stored custom theme, resetting", e);
- mThemes.add(new CustomTheme(CustomTheme.newId(), mContext.getString(R.string.custom_theme_title,
- customThemesCount + 1), new HashMap<>(), null));
+ mThemes.add(new CustomTheme(CustomTheme.newId(), mContext.getString(
+ R.string.custom_theme_title, customThemesCount + 1),
+ new HashMap<>(), null));
}
}
// Add an empty one at the end.
- mThemes.add(new CustomTheme(CustomTheme.newId(), mContext.getString(R.string.custom_theme_title,
- customThemesCount + 1), new HashMap<>(), null));
+ mThemes.add(new CustomTheme(CustomTheme.newId(), mContext.getString(
+ R.string.custom_theme_title, customThemesCount + 1), new HashMap<>(), null));
}
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 9d2f397..12ec32c 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -49,7 +49,6 @@
import com.android.wallpaper.R;
import com.android.wallpaper.asset.Asset;
import com.android.wallpaper.asset.BitmapCachingAsset;
-import com.android.wallpaper.asset.ResourceAsset;
import com.android.wallpaper.model.LiveWallpaperInfo;
import com.android.wallpaper.model.WallpaperInfo;
@@ -295,7 +294,8 @@
@ColorInt private int mColorAccentLight = -1;
@ColorInt private int mColorAccentDark = -1;
private List<Drawable> mIcons = new ArrayList<>();
- private String mShapePath;
+ private String mPathString;
+ private Path mShapePath;
private boolean mIsDefault;
@Dimension private int mCornerRadius;
private Asset mWallpaperAsset;
@@ -308,11 +308,14 @@
createPreviewInfo(context));
}
- protected PreviewInfo createPreviewInfo(Context context) {
+ public PreviewInfo createPreviewInfo(Context context) {
ShapeDrawable shapeDrawable = null;
List<Drawable> shapeIcons = new ArrayList<>();
- if (!TextUtils.isEmpty(mShapePath)) {
- Path path = PathParser.createPathFromPathData(mShapePath);
+ Path path = mShapePath;
+ if (!TextUtils.isEmpty(mPathString)) {
+ path = PathParser.createPathFromPathData(mPathString);
+ }
+ if (path != null) {
PathShape shape = new PathShape(path, PATH_SIZE, PATH_SIZE);
shapeDrawable = new ShapeDrawable(shape);
shapeDrawable.setIntrinsicHeight((int) PATH_SIZE);
@@ -322,6 +325,8 @@
AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) icon;
shapeIcons.add(new DynamicAdaptiveIconDrawable(adaptiveIcon.getBackground(),
adaptiveIcon.getForeground(), path));
+ } else if (icon instanceof DynamicAdaptiveIconDrawable) {
+ shapeIcons.add(icon);
}
// TODO: add iconloader library's legacy treatment helper methods for
// non-adaptive icons
@@ -332,6 +337,10 @@
mWallpaperAsset, shapeIcons);
}
+ public Map<String, String> getPackages() {
+ return Collections.unmodifiableMap(mPackages);
+ }
+
public String getTitle() {
return mTitle;
}
@@ -372,6 +381,11 @@
}
public Builder setShapePath(String path) {
+ mPathString = path;
+ return this;
+ }
+
+ public Builder setShapePath(Path path) {
mShapePath = path;
return this;
}
diff --git a/src/com/android/customization/model/theme/ThemeManager.java b/src/com/android/customization/model/theme/ThemeManager.java
index de6a98b..d873972 100644
--- a/src/com/android/customization/model/theme/ThemeManager.java
+++ b/src/com/android/customization/model/theme/ThemeManager.java
@@ -164,7 +164,7 @@
private void applyOverlays(ThemeBundle theme, Callback callback) {
boolean allApplied = Settings.Secure.putString(mActivity.getContentResolver(),
ResourceConstants.THEME_SETTING, theme.getSerializedPackages());
- if (theme instanceof CustomTheme && !((CustomTheme) theme).isDefined()) {
+ if (theme instanceof CustomTheme) {
storeCustomTheme((CustomTheme) theme);
}
mCurrentOverlays = null;
diff --git a/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java b/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
index 07a876b..020e3ef 100644
--- a/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
+++ b/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
@@ -77,7 +77,7 @@
String iconPackage =
mCustomThemeManager.getOverlayPackages().get(OVERLAY_CATEGORY_ICON_ANDROID);
if (TextUtils.isEmpty(iconPackage)) {
- iconPackage = SYSUI_PACKAGE;
+ iconPackage = ANDROID_PACKAGE;
}
for (String iconName : ICONS_FOR_PREVIEW) {
try {
diff --git a/src/com/android/customization/model/theme/custom/CustomTheme.java b/src/com/android/customization/model/theme/custom/CustomTheme.java
index 15e4eb8..97a1876 100644
--- a/src/com/android/customization/model/theme/custom/CustomTheme.java
+++ b/src/com/android/customization/model/theme/custom/CustomTheme.java
@@ -34,6 +34,9 @@
return UUID.randomUUID().toString();
}
+ /**
+ * Used to uniquely identify a custom theme since names can change.
+ */
private final String mId;
public CustomTheme(@NonNull String id, String title, Map<String, String> overlayPackages,
diff --git a/src/com/android/customization/model/theme/custom/CustomThemeManager.java b/src/com/android/customization/model/theme/custom/CustomThemeManager.java
index 0cc0161..a3acba4 100644
--- a/src/com/android/customization/model/theme/custom/CustomThemeManager.java
+++ b/src/com/android/customization/model/theme/custom/CustomThemeManager.java
@@ -21,7 +21,9 @@
import androidx.annotation.Nullable;
import com.android.customization.model.CustomizationManager;
+import com.android.customization.model.theme.ThemeBundle.PreviewInfo;
import com.android.customization.model.theme.ThemeManager;
+import com.android.customization.model.theme.custom.CustomTheme.Builder;
import com.android.wallpaper.R;
import java.util.HashMap;
@@ -29,12 +31,13 @@
public class CustomThemeManager implements CustomizationManager<ThemeComponentOption> {
- private final Map<String, String> mOverlayPackages = new HashMap<>();
private final CustomTheme mOriginalTheme;
+ private final CustomTheme.Builder mBuilder;
private CustomThemeManager(Map<String, String> overlayPackages,
@Nullable CustomTheme originalTheme) {
- mOverlayPackages.putAll(overlayPackages);
+ mBuilder = new Builder();
+ overlayPackages.forEach(mBuilder::addOverlayPackage);
mOriginalTheme = originalTheme;
}
@@ -45,22 +48,23 @@
@Override
public void apply(ThemeComponentOption option, @Nullable Callback callback) {
- option.getOverlayPackages().forEach((category, packageName) -> {
- if (!TextUtils.isEmpty(packageName)) {
- mOverlayPackages.put(category, packageName);
- }
- });
+// option.getOverlayPackages().forEach((category, packageName) -> {
+// if (!TextUtils.isEmpty(packageName)) {
+// mBuilder.addOverlayPackage(category, packageName);
+// }
+// });
+ option.buildStep(mBuilder);
if (callback != null) {
callback.onSuccess();
}
}
public Map<String, String> getOverlayPackages() {
- return mOverlayPackages;
+ return mBuilder.getPackages();
}
- public CustomTheme buildPartialCustomTheme(String id, String title) {
- return new CustomTheme(id, title, mOverlayPackages, null);
+ public CustomTheme buildPartialCustomTheme(Context context, String id, String title) {
+ return ((CustomTheme.Builder)mBuilder.setId(id).setTitle(title)).build(context);
}
@Override
@@ -72,6 +76,10 @@
return mOriginalTheme;
}
+ public PreviewInfo buildCustomThemePreviewInfo(Context context) {
+ return mBuilder.createPreviewInfo(context);
+ }
+
public static CustomThemeManager create(
@Nullable CustomTheme customTheme, ThemeManager themeManager) {
if (customTheme != null && customTheme.isDefined()) {
@@ -80,4 +88,5 @@
// Seed the first custom theme with the currently applied theme.
return new CustomThemeManager(themeManager.getCurrentOverlays(), customTheme);
}
+
}
diff --git a/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java b/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java
index 112ed43..b050e41 100644
--- a/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java
+++ b/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java
@@ -16,9 +16,8 @@
package com.android.customization.model.theme.custom;
import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
+import static com.android.customization.model.ResourceConstants.CONFIG_CORNERRADIUS;
import static com.android.customization.model.ResourceConstants.CONFIG_ICON_MASK;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
import static com.android.customization.model.ResourceConstants.PATH_SIZE;
@@ -28,7 +27,6 @@
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Path;
-import android.graphics.Typeface;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
@@ -36,6 +34,7 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Dimension;
import androidx.core.graphics.PathParser;
import com.android.customization.model.ResourceConstants;
@@ -75,8 +74,8 @@
ShapeDrawable shapeDrawable = createShapeDrawable(path);
PackageManager pm = mContext.getPackageManager();
String label = pm.getApplicationInfo(overlayPackage, 0).loadLabel(pm).toString();
- mOptions.add(new ShapeOption(overlayPackage, label, shapeDrawable,
- getShapedIcons(path)));
+ mOptions.add(new ShapeOption(overlayPackage, label, path,
+ loadCornerRadius(overlayPackage), shapeDrawable, getShapedIcons(path)));
} catch (NameNotFoundException | NotFoundException e) {
Log.w(TAG, String.format("Couldn't load shape overlay %s, will skip it",
overlayPackage), e);
@@ -88,7 +87,10 @@
Resources system = Resources.getSystem();
Path path = loadPath(system, ANDROID_PACKAGE);
ShapeDrawable shapeDrawable = createShapeDrawable(path);
- mOptions.add(new ShapeOption(null, mContext.getString(R.string.default_theme_title),
+ mOptions.add(new ShapeOption(null, mContext.getString(R.string.default_theme_title), path,
+ system.getDimensionPixelOffset(
+ system.getIdentifier(ResourceConstants.CONFIG_CORNERRADIUS,
+ "dimen", ResourceConstants.ANDROID_PACKAGE)),
shapeDrawable, getShapedIcons(path)));
}
@@ -127,4 +129,15 @@
}
return null;
}
+
+ @Dimension
+ private int loadCornerRadius(String packageName)
+ throws NameNotFoundException, NotFoundException {
+
+ Resources overlayRes =
+ mContext.getPackageManager().getResourcesForApplication(
+ packageName);
+ return overlayRes.getDimensionPixelOffset(overlayRes.getIdentifier(
+ CONFIG_CORNERRADIUS, "dimen", packageName));
+ }
}
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
index 2dc163e..994b5f3 100644
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
+++ b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
@@ -17,6 +17,11 @@
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SYSUI;
+import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_THEMEPICKER;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
import android.content.Context;
@@ -24,10 +29,12 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
+import android.graphics.Path;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
+import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -39,17 +46,20 @@
import android.widget.TextView;
import androidx.annotation.ColorInt;
+import androidx.annotation.Dimension;
import androidx.annotation.Nullable;
import com.android.customization.model.CustomizationManager;
import com.android.customization.model.CustomizationOption;
import com.android.customization.model.ResourceConstants;
+import com.android.customization.model.theme.custom.CustomTheme.Builder;
import com.android.wallpaper.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Objects;
/**
@@ -79,6 +89,15 @@
public abstract void bindPreview(ViewGroup container);
+ public Builder buildStep(Builder builder) {
+ getOverlayPackages().forEach((category, packageName) -> {
+ if (!TextUtils.isEmpty(packageName)) {
+ builder.addOverlayPackage(category, packageName);
+ }
+ });
+ return builder;
+ }
+
public static class FontOption extends ThemeComponentOption {
private final String mLabel;
@@ -134,6 +153,12 @@
TextView bodyText = container.findViewById(R.id.font_card_body);
bodyText.setTypeface(mBodyFont);
}
+
+ @Override
+ public Builder buildStep(Builder builder) {
+ builder.setHeadlineFontFamily(mHeadlineFont).setBodyFontFamily(mBodyFont);
+ return super.buildStep(builder);
+ }
}
public static class IconOption extends ThemeComponentOption {
@@ -161,16 +186,21 @@
@Override
public boolean isActive(CustomizationManager<ThemeComponentOption> manager) {
CustomThemeManager customThemeManager = (CustomThemeManager) manager;
+ Map<String, String> themePackages = customThemeManager.getOverlayPackages();
if (getOverlayPackages().isEmpty()) {
- return customThemeManager.getOverlayPackages().isEmpty();
+ return themePackages.get(OVERLAY_CATEGORY_ICON_SYSUI) == null &&
+ themePackages.get(OVERLAY_CATEGORY_ICON_SETTINGS) == null &&
+ themePackages.get(OVERLAY_CATEGORY_ICON_ANDROID) == null &&
+ themePackages.get(OVERLAY_CATEGORY_ICON_LAUNCHER) == null &&
+ themePackages.get(OVERLAY_CATEGORY_ICON_THEMEPICKER) == null;
}
- for (Map.Entry<String, String> overlayEntry : getOverlayPackages().entrySet()) {
- if(!Objects.equals(overlayEntry.getValue(),
- customThemeManager.getOverlayPackages().get(overlayEntry.getKey()))) {
- return false;
- }
- }
- return true;
+ for (Map.Entry<String, String> overlayEntry : getOverlayPackages().entrySet()) {
+ if(!Objects.equals(overlayEntry.getValue(),
+ themePackages.get(overlayEntry.getKey()))) {
+ return false;
+ }
+ }
+ return true;
}
@Override
@@ -210,6 +240,14 @@
public void setLabel(String label) {
mLabel = label;
}
+
+ @Override
+ public Builder buildStep(Builder builder) {
+ for (Drawable icon : mIcons) {
+ builder.addIcon(icon);
+ }
+ return super.buildStep(builder);
+ }
}
public static class ColorOption extends ThemeComponentOption {
@@ -346,6 +384,12 @@
public void setShapeDrawable(@Nullable Drawable shapeDrawable) {
mShapeDrawable = shapeDrawable;
}
+
+ @Override
+ public Builder buildStep(Builder builder) {
+ builder.setColorAccentDark(mColorAccentDark).setColorAccentLight(mColorAccentLight);
+ return super.buildStep(builder);
+ }
}
public static class ShapeOption extends ThemeComponentOption {
@@ -353,16 +397,21 @@
private final LayerDrawable mShape;
private final List<Drawable> mAppIcons;
private final String mLabel;
+ private final Path mPath;
+ private final int mCornerRadius;
private int[] mShapeIconIds = {
R.id.shape_preview_icon_0, R.id.shape_preview_icon_1, R.id.shape_preview_icon_2,
R.id.shape_preview_icon_3, R.id.shape_preview_icon_4, R.id.shape_preview_icon_5
};
- ShapeOption(String packageName, String label, Drawable shapeDrawable,
+ ShapeOption(String packageName, String label, Path path,
+ @Dimension int cornerRadius, Drawable shapeDrawable,
List<Drawable> appIcons) {
addOverlayPackage(OVERLAY_CATEGORY_SHAPE, packageName);
mLabel = label;
mAppIcons = appIcons;
+ mPath = path;
+ mCornerRadius = cornerRadius;
Drawable background = shapeDrawable.getConstantState().newDrawable();
Drawable foreground = shapeDrawable.getConstantState().newDrawable();
mShape = new LayerDrawable(new Drawable[]{background, foreground});
@@ -418,5 +467,14 @@
iconView.setBackground(mAppIcons.get(i));
}
}
+
+ @Override
+ public Builder buildStep(Builder builder) {
+ builder.setShapePath(mPath).setBottomSheetCornerRadius(mCornerRadius);
+ for (Drawable appIcon : mAppIcons) {
+ builder.addShapePreviewIcon(appIcon);
+ }
+ return super.buildStep(builder);
+ }
}
}
diff --git a/src/com/android/customization/picker/theme/CustomThemeActivity.java b/src/com/android/customization/picker/theme/CustomThemeActivity.java
index 0ea9617..2bc371d 100644
--- a/src/com/android/customization/picker/theme/CustomThemeActivity.java
+++ b/src/com/android/customization/picker/theme/CustomThemeActivity.java
@@ -16,6 +16,7 @@
package com.android.customization.picker.theme;
import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
@@ -34,7 +35,6 @@
import com.android.customization.model.theme.DefaultThemeProvider;
import com.android.customization.model.theme.OverlayManagerCompat;
import com.android.customization.model.theme.ThemeBundle;
-import com.android.customization.model.theme.ThemeBundle.Builder;
import com.android.customization.model.theme.ThemeBundleProvider;
import com.android.customization.model.theme.ThemeManager;
import com.android.customization.model.theme.custom.ColorOptionsProvider;
@@ -51,7 +51,7 @@
import com.android.customization.model.theme.custom.ThemeComponentOptionProvider;
import com.android.customization.module.CustomizationInjector;
import com.android.customization.module.ThemesUserEventLogger;
-import com.android.customization.picker.theme.CustomThemeComponentFragment.CustomThemeComponentFragmentHost;
+import com.android.customization.picker.theme.CustomThemeStepFragment.CustomThemeComponentStepHost;
import com.android.wallpaper.R;
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.WallpaperSetter;
@@ -62,7 +62,7 @@
import java.util.List;
public class CustomThemeActivity extends FragmentActivity implements
- CustomThemeComponentFragmentHost {
+ CustomThemeComponentStepHost {
public static final String EXTRA_THEME_ID = "CustomThemeActivity.ThemeId";
public static final String EXTRA_THEME_TITLE = "CustomThemeActivity.ThemeTitle";
public static final String EXTRA_THEME_PACKAGES = "CustomThemeActivity.ThemePackages";
@@ -160,59 +160,64 @@
private void initSteps(int currentStep) {
mSteps = new ArrayList<>();
OverlayManagerCompat manager = new OverlayManagerCompat(this);
- mSteps.add(new FontStep(new FontOptionsProvider(this, manager), 0, 4));
- mSteps.add(new IconStep(new IconOptionsProvider(this, manager), 1, 4));
- mSteps.add(new ColorStep(new ColorOptionsProvider(this, manager, mCustomThemeManager),
- 2, 4));
- mSteps.add(new ShapeStep(new ShapeOptionsProvider(this, manager), 3, 4));
+ mSteps.add(new FontStep(new FontOptionsProvider(this, manager), 0));
+ mSteps.add(new IconStep(new IconOptionsProvider(this, manager), 1));
+ mSteps.add(new ColorStep(new ColorOptionsProvider(this, manager, mCustomThemeManager), 2));
+ mSteps.add(new ShapeStep(new ShapeOptionsProvider(this, manager), 3));
+ mSteps.add(new NameStep(4));
mCurrentStep = currentStep;
}
private void onNextOrApply() {
- mCustomThemeManager.apply(getCurrentStepFragment().getSelectedOption(), new Callback() {
- @Override
- public void onSuccess() {
- if (mCurrentStep < mSteps.size() - 1) {
+ CustomThemeStepFragment stepFragment = getCurrentStepFragment();
+ if (stepFragment instanceof CustomThemeComponentFragment) {
+ CustomThemeComponentFragment fragment = (CustomThemeComponentFragment) stepFragment;
+ mCustomThemeManager.apply(fragment.getSelectedOption(), new Callback() {
+ @Override
+ public void onSuccess() {
navigateToStep(mCurrentStep + 1);
- } else {
- CustomTheme originalTheme = mCustomThemeManager.getOriginalTheme();
-
- // We're on the last step, apply theme and leave
- CustomTheme themeToApply = mCustomThemeManager.buildPartialCustomTheme(
- originalTheme.getId(), originalTheme.getTitle());
-
- // If the current theme is equal to the original theme being edited, then
- // don't search for an equivalent, let the user apply the same one by keeping
- // it null.
- ThemeBundle equivalent = (originalTheme.isEquivalent(themeToApply))
- ? null : mThemeManager.findThemeByPackages(themeToApply);
-
- if (equivalent != null) {
- AlertDialog.Builder builder =
- new AlertDialog.Builder(CustomThemeActivity.this);
- builder.setTitle(getString(R.string.use_style_instead_title,
- equivalent.getTitle()))
- .setMessage(getString(R.string.use_style_instead_body,
- equivalent.getTitle()))
- .setPositiveButton(getString(R.string.use_style_button,
- equivalent.getTitle()),
- (dialogInterface, i) -> applyTheme(equivalent))
- .setNegativeButton(R.string.no_thanks, null)
- .create()
- .show();
- } else {
- applyTheme(themeToApply);
- }
}
- }
- @Override
- public void onError(@Nullable Throwable throwable) {
- Log.w(TAG, "Error applying custom theme component", throwable);
- Toast.makeText(CustomThemeActivity.this, R.string.apply_theme_error_msg,
- Toast.LENGTH_LONG).show();
+ @Override
+ public void onError(@Nullable Throwable throwable) {
+ Log.w(TAG, "Error applying custom theme component", throwable);
+ Toast.makeText(CustomThemeActivity.this, R.string.apply_theme_error_msg,
+ Toast.LENGTH_LONG).show();
+ }
+ });
+ } else if (stepFragment instanceof CustomThemeNameFragment) {
+ CustomThemeNameFragment fragment = (CustomThemeNameFragment) stepFragment;
+ CustomTheme originalTheme = mCustomThemeManager.getOriginalTheme();
+
+ // We're on the last step, apply theme and leave
+ CustomTheme themeToApply = mCustomThemeManager.buildPartialCustomTheme(this,
+ originalTheme.getId(), fragment.getThemeName());
+
+ // If the current theme is equal to the original theme being edited, then
+ // don't search for an equivalent, let the user apply the same one by keeping
+ // it null.
+ ThemeBundle equivalent = (originalTheme.isEquivalent(themeToApply))
+ ? null : mThemeManager.findThemeByPackages(themeToApply);
+
+ if (equivalent != null) {
+ Builder builder =
+ new Builder(CustomThemeActivity.this);
+ builder.setTitle(getString(R.string.use_style_instead_title,
+ equivalent.getTitle()))
+ .setMessage(getString(R.string.use_style_instead_body,
+ equivalent.getTitle()))
+ .setPositiveButton(getString(R.string.use_style_button,
+ equivalent.getTitle()),
+ (dialogInterface, i) -> applyTheme(equivalent))
+ .setNegativeButton(R.string.no_thanks, null)
+ .create()
+ .show();
+ } else {
+ applyTheme(themeToApply);
}
- });
+ } else {
+ throw new IllegalStateException("Unknown CustomThemeStepFragment");
+ }
}
private void applyTheme(ThemeBundle themeToApply) {
@@ -235,8 +240,8 @@
});
}
- private CustomThemeComponentFragment getCurrentStepFragment() {
- return (CustomThemeComponentFragment)
+ private CustomThemeStepFragment getCurrentStepFragment() {
+ return (CustomThemeStepFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container);
}
@@ -284,7 +289,7 @@
@StringRes final int titleResId;
final ThemeComponentOptionProvider<T> provider;
final int position;
- private CustomThemeComponentFragment mFragment;
+ private CustomThemeStepFragment mFragment;
protected ComponentStep(@StringRes int titleResId, ThemeComponentOptionProvider<T> provider,
int position) {
@@ -293,7 +298,7 @@
this.position = position;
}
- CustomThemeComponentFragment getFragment(String title) {
+ CustomThemeStepFragment getFragment(String title) {
if (mFragment == null) {
mFragment = createFragment(title);
}
@@ -303,13 +308,13 @@
/**
* @return a newly created fragment that will handle this step's UI.
*/
- abstract CustomThemeComponentFragment createFragment(String title);
+ abstract CustomThemeStepFragment createFragment(String title);
}
private class FontStep extends ComponentStep<FontOption> {
protected FontStep(ThemeComponentOptionProvider<FontOption> provider,
- int position, int totalSteps) {
+ int position) {
super(R.string.font_component_title, provider, position);
}
@@ -325,7 +330,7 @@
private class IconStep extends ComponentStep<IconOption> {
protected IconStep(ThemeComponentOptionProvider<IconOption> provider,
- int position, int totalSteps) {
+ int position) {
super(R.string.icon_component_title, provider, position);
}
@@ -341,7 +346,7 @@
private class ColorStep extends ComponentStep<ColorOption> {
protected ColorStep(ThemeComponentOptionProvider<ColorOption> provider,
- int position, int totalSteps) {
+ int position) {
super(R.string.color_component_title, provider, position);
}
@@ -358,7 +363,7 @@
private class ShapeStep extends ComponentStep<ShapeOption> {
protected ShapeStep(ThemeComponentOptionProvider<ShapeOption> provider,
- int position, int totalSteps) {
+ int position) {
super(R.string.shape_component_title, provider, position);
}
@@ -370,4 +375,19 @@
titleResId);
}
}
+
+ private class NameStep extends ComponentStep {
+
+ protected NameStep(int position) {
+ super(R.string.name_component_title, null, position);
+ }
+
+ @Override
+ CustomThemeNameFragment createFragment(String title) {
+ return CustomThemeNameFragment.newInstance(
+ title,
+ position,
+ titleResId);
+ }
+ }
}
diff --git a/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java b/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
index a50051b..f6471f0 100644
--- a/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
+++ b/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
@@ -37,22 +37,8 @@
import com.android.wallpaper.R;
import com.android.wallpaper.picker.ToolbarFragment;
-public class CustomThemeComponentFragment extends ToolbarFragment {
- private static final String ARG_KEY_POSITION = "CustomThemeComponentFragment.position";
- private static final String ARG_KEY_TITLE_RES_ID = "CustomThemeComponentFragment.title_res";
+public class CustomThemeComponentFragment extends CustomThemeStepFragment {
private static final String ARG_USE_GRID_LAYOUT = "CustomThemeComponentFragment.use_grid";;
- private CustomThemeComponentFragmentHost mHost;
-
- public interface CustomThemeComponentFragmentHost {
- void delete();
- void cancel();
- ThemeComponentOptionProvider<? extends ThemeComponentOption> getComponentOptionProvider(
- int position);
-
- CustomThemeManager getCustomThemeManager();
-
- void setCurrentStep(int step);
- }
public static CustomThemeComponentFragment newInstance(CharSequence toolbarTitle, int position,
int titleResId) {
@@ -71,53 +57,24 @@
}
private ThemeComponentOptionProvider<? extends ThemeComponentOption> mProvider;
- private CustomThemeManager mCustomThemeManager;
- private int mPosition;
- @StringRes private int mTitleResId;
private boolean mUseGridLayout;
private RecyclerView mOptionsContainer;
private OptionSelectorController<ThemeComponentOption> mOptionsController;
- private ViewGroup mPreviewContainer;
- private TextView mTitle;
private ThemeComponentOption mSelectedOption;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mPosition = getArguments().getInt(ARG_KEY_POSITION);
- mTitleResId = getArguments().getInt(ARG_KEY_TITLE_RES_ID);
mUseGridLayout = getArguments().getBoolean(ARG_USE_GRID_LAYOUT);
mProvider = mHost.getComponentOptionProvider(mPosition);
- mCustomThemeManager = mHost.getCustomThemeManager();
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- mHost = (CustomThemeComponentFragmentHost) context;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
- View view = inflater.inflate(
- R.layout.fragment_custom_theme_component, container, /* attachToRoot */ false);
- // No original theme means it's a new one, so no toolbar icon for deleting it is needed
- if (mCustomThemeManager.getOriginalTheme() == null) {
- setUpToolbar(view);
- } else {
- setUpToolbar(view, R.menu.custom_theme_editor_menu);
- mToolbar.getMenu().getItem(0).setIconTintList(
- getContext().getColorStateList(R.color.toolbar_icon_color));
- }
- Drawable closeIcon = getResources().getDrawable(R.drawable.ic_close_24px, null).mutate();
- closeIcon.setTintList(getResources().getColorStateList(R.color.toolbar_icon_color, null));
- mToolbar.setNavigationIcon(closeIcon);
-
- mToolbar.setNavigationContentDescription(R.string.cancel);
- mToolbar.setNavigationOnClickListener(v -> mHost.cancel());
+ View view = super.onCreateView(inflater, container, savedInstanceState);
mOptionsContainer = view.findViewById(R.id.options_container);
mPreviewContainer = view.findViewById(R.id.component_preview_content);
mTitle = view.findViewById(R.id.component_options_title);
@@ -128,24 +85,8 @@
}
@Override
- public void onResume() {
- super.onResume();
- mHost.setCurrentStep(mPosition);
- }
-
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- if (item.getItemId() == R.id.custom_theme_delete) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- builder.setMessage(R.string.delete_custom_theme_confirmation)
- .setPositiveButton(R.string.delete_custom_theme_button,
- (dialogInterface, i) -> mHost.delete())
- .setNegativeButton(R.string.cancel, null)
- .create()
- .show();
- return true;
- }
- return super.onMenuItemClick(item);
+ protected int getFragmentLayoutResId() {
+ return R.layout.fragment_custom_theme_component;
}
public ThemeComponentOption getSelectedOption() {
diff --git a/src/com/android/customization/picker/theme/CustomThemeNameFragment.java b/src/com/android/customization/picker/theme/CustomThemeNameFragment.java
new file mode 100644
index 0000000..84915ff
--- /dev/null
+++ b/src/com/android/customization/picker/theme/CustomThemeNameFragment.java
@@ -0,0 +1,175 @@
+/*
+ * 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.customization.picker.theme;
+
+import android.app.WallpaperColors;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.cardview.widget.CardView;
+
+import com.android.customization.model.theme.ThemeBundle.PreviewInfo;
+import com.android.customization.model.theme.custom.CustomTheme;
+import com.android.customization.picker.theme.ThemePreviewPage.ThemeCoverPage;
+import com.android.wallpaper.R;
+import com.android.wallpaper.asset.Asset;
+import com.android.wallpaper.asset.BitmapCachingAsset;
+import com.android.wallpaper.module.CurrentWallpaperInfoFactory;
+import com.android.wallpaper.module.InjectorProvider;
+import com.android.wallpaper.picker.ToolbarFragment;
+
+public class CustomThemeNameFragment extends CustomThemeStepFragment {
+
+ public static CustomThemeNameFragment newInstance(CharSequence toolbarTitle, int position,
+ int titleResId) {
+ CustomThemeNameFragment fragment = new CustomThemeNameFragment();
+ Bundle arguments = ToolbarFragment.createArguments(toolbarTitle);
+ arguments.putInt(ARG_KEY_POSITION, position);
+ arguments.putInt(ARG_KEY_TITLE_RES_ID, titleResId);
+ fragment.setArguments(arguments);
+ return fragment;
+ }
+
+
+ private int[] mColorButtonIds = {
+ R.id.preview_check_selected, R.id.preview_radio_selected, R.id.preview_toggle_selected
+ };
+ private int[] mColorTileIds = {
+ R.id.preview_color_qs_0_bg, R.id.preview_color_qs_1_bg, R.id.preview_color_qs_2_bg
+ };
+ private int[] mColorTileIconIds = {
+ R.id.preview_color_qs_0_icon, R.id.preview_color_qs_1_icon, R.id.preview_color_qs_2_icon
+ };
+
+ private int[] mShapeIconIds = {
+ R.id.shape_preview_icon_0, R.id.shape_preview_icon_1, R.id.shape_preview_icon_2,
+ R.id.shape_preview_icon_3, R.id.shape_preview_icon_4, R.id.shape_preview_icon_5
+ };
+
+ private Asset mWallpaperAsset;
+ private ThemeCoverPage mCoverPage;
+
+ private EditText mNameEditor;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ CurrentWallpaperInfoFactory currentWallpaperFactory = InjectorProvider.getInjector()
+ .getCurrentWallpaperFactory(getActivity().getApplicationContext());
+ currentWallpaperFactory.createCurrentWallpaperInfos(
+ (homeWallpaper, lockWallpaper, presentationMode) -> {
+ mWallpaperAsset = new BitmapCachingAsset(getContext(),
+ homeWallpaper.getThumbAsset(getContext()));
+ if (mCoverPage != null) {
+ mCoverPage.bindBody(true);
+ }
+ }, false);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
+ mTitle = view.findViewById(R.id.component_options_title);
+ mTitle.setText(mTitleResId);
+ mNameEditor = view.findViewById(R.id.custom_theme_name);
+ mNameEditor.setText(mCustomThemeManager.getOriginalTheme().getTitle());
+ bindCover(view.findViewById(R.id.component_preview_content));
+
+ return view;
+ }
+
+ private void bindCover(CardView card) {
+ PreviewInfo previewInfo = mCustomThemeManager.buildCustomThemePreviewInfo(getContext());
+ mCoverPage = new ThemeCoverPage(getContext(), getThemeName(),
+ previewInfo.resolveAccentColor(getResources()), previewInfo.icons,
+ previewInfo.headlineFontFamily, previewInfo.bottomSheeetCornerRadius,
+ previewInfo.shapeDrawable, previewInfo.shapeAppIcons, null,
+ mColorButtonIds, mColorTileIds, mColorTileIconIds, mShapeIconIds,
+ new WallpaperLayoutListener());
+ mCoverPage.setCard(card);
+ mCoverPage.bindPreviewContent();
+ mNameEditor.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ ((TextView)card.findViewById(R.id.theme_preview_card_header)).setText(charSequence);
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+
+ }
+ });
+ }
+
+ private class WallpaperLayoutListener implements OnLayoutChangeListener {
+ @Override
+ public void onLayoutChange(View view, int left, int top, int right,
+ int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ int targetWidth = right - left;
+ int targetHeight = bottom - top;
+ if (targetWidth > 0 && targetHeight > 0) {
+ if (mWallpaperAsset != null) {
+ mWallpaperAsset.decodeBitmap(
+ targetWidth, targetHeight,
+ bitmap -> setWallpaperBitmap(view, bitmap));
+ }
+ view.removeOnLayoutChangeListener(this);
+ }
+ }
+
+ private void setWallpaperBitmap(View view, Bitmap bitmap) {
+ Resources res = view.getContext().getResources();
+ BitmapDrawable background = new BitmapDrawable(res, bitmap);
+ background.setAlpha(128);
+ view.findViewById(R.id.theme_preview_card_background).setBackground(background);
+ }
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ mCoverPage = null;
+ }
+
+ @Override
+ protected int getFragmentLayoutResId() {
+ return R.layout.fragment_custom_theme_name;
+ }
+
+ public String getThemeName() {
+ return mNameEditor.getText().toString();
+ }
+}
diff --git a/src/com/android/customization/picker/theme/CustomThemeStepFragment.java b/src/com/android/customization/picker/theme/CustomThemeStepFragment.java
new file mode 100644
index 0000000..ebf55e3
--- /dev/null
+++ b/src/com/android/customization/picker/theme/CustomThemeStepFragment.java
@@ -0,0 +1,106 @@
+package com.android.customization.picker.theme;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
+import com.android.customization.model.theme.custom.CustomThemeManager;
+import com.android.customization.model.theme.custom.ThemeComponentOption;
+import com.android.customization.model.theme.custom.ThemeComponentOptionProvider;
+import com.android.wallpaper.R;
+import com.android.wallpaper.picker.ToolbarFragment;
+
+abstract class CustomThemeStepFragment extends ToolbarFragment {
+ protected static final String ARG_KEY_POSITION = "CustomThemeStepFragment.position";
+ protected static final String ARG_KEY_TITLE_RES_ID = "CustomThemeStepFragment.title_res";
+ protected CustomThemeComponentStepHost mHost;
+ protected CustomThemeManager mCustomThemeManager;
+ protected int mPosition;
+ protected ViewGroup mPreviewContainer;
+ protected TextView mTitle;
+ @StringRes
+ protected int mTitleResId;
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mHost = (CustomThemeComponentStepHost) context;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mHost.setCurrentStep(mPosition);
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mPosition = getArguments().getInt(ARG_KEY_POSITION);
+ mTitleResId = getArguments().getInt(ARG_KEY_TITLE_RES_ID);
+ mCustomThemeManager = mHost.getCustomThemeManager();
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(
+ getFragmentLayoutResId(), container, /* attachToRoot */ false);
+ // No original theme means it's a new one, so no toolbar icon for deleting it is needed
+ if (mCustomThemeManager.getOriginalTheme() == null
+ || !mCustomThemeManager.getOriginalTheme().isDefined()) {
+ setUpToolbar(view);
+ } else {
+ setUpToolbar(view, R.menu.custom_theme_editor_menu);
+ mToolbar.getMenu().getItem(0).setIconTintList(
+ getContext().getColorStateList(R.color.toolbar_icon_color));
+ }
+ Drawable closeIcon = getResources().getDrawable(R.drawable.ic_close_24px, null).mutate();
+ closeIcon.setTintList(getResources().getColorStateList(R.color.toolbar_icon_color, null));
+ mToolbar.setNavigationIcon(closeIcon);
+
+ mToolbar.setNavigationContentDescription(R.string.cancel);
+ mToolbar.setNavigationOnClickListener(v -> mHost.cancel());
+
+ mPreviewContainer = view.findViewById(R.id.component_preview_content);
+ return view;
+ }
+
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ if (item.getItemId() == R.id.custom_theme_delete) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setMessage(R.string.delete_custom_theme_confirmation)
+ .setPositiveButton(R.string.delete_custom_theme_button,
+ (dialogInterface, i) -> mHost.delete())
+ .setNegativeButton(R.string.cancel, null)
+ .create()
+ .show();
+ return true;
+ }
+ return super.onMenuItemClick(item);
+ }
+
+ protected abstract int getFragmentLayoutResId();
+
+ public interface CustomThemeComponentStepHost {
+ void delete();
+ void cancel();
+ ThemeComponentOptionProvider<? extends ThemeComponentOption> getComponentOptionProvider(
+ int position);
+
+ CustomThemeManager getCustomThemeManager();
+
+ void setCurrentStep(int step);
+ }
+}
diff --git a/src/com/android/customization/picker/theme/ThemeFragment.java b/src/com/android/customization/picker/theme/ThemeFragment.java
index 5b590f0..134d255 100644
--- a/src/com/android/customization/picker/theme/ThemeFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFragment.java
@@ -22,17 +22,12 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
-import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.icu.text.DateFormat;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
@@ -44,12 +39,8 @@
import android.widget.TextView;
import android.widget.Toast;
-import androidx.annotation.ColorInt;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
import androidx.recyclerview.widget.RecyclerView;
import com.android.customization.model.CustomizationManager.Callback;
@@ -59,7 +50,7 @@
import com.android.customization.model.theme.custom.CustomTheme;
import com.android.customization.module.ThemesUserEventLogger;
import com.android.customization.picker.BasePreviewAdapter;
-import com.android.customization.picker.BasePreviewAdapter.PreviewPage;
+import com.android.customization.picker.theme.ThemePreviewPage.ThemeCoverPage;
import com.android.customization.widget.OptionSelectorController;
import com.android.customization.widget.PreviewPager;
import com.android.wallpaper.R;
@@ -69,10 +60,7 @@
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.picker.ToolbarFragment;
-import java.text.FieldPosition;
-import java.util.Calendar;
import java.util.List;
-import java.util.TimeZone;
/**
* Fragment that contains the main UI for selecting and applying a ThemeBundle.
@@ -301,143 +289,6 @@
startActivityForResult(intent, CustomThemeActivity.REQUEST_CODE_CUSTOM_THEME);
}
- private static abstract class ThemePreviewPage extends PreviewPage {
- @StringRes final int nameResId;
- @DrawableRes final int iconSrc;
- @LayoutRes final int contentLayoutRes;
- @ColorInt final int accentColor;
- protected final LayoutInflater inflater;
-
- private ThemePreviewPage(Context context, @StringRes int titleResId,
- @DrawableRes int iconSrc, @LayoutRes int contentLayoutRes,
- @ColorInt int accentColor) {
- super(null);
- this.nameResId = titleResId;
- this.iconSrc = iconSrc;
- this.contentLayoutRes = contentLayoutRes;
- this.accentColor = accentColor;
- this.inflater = LayoutInflater.from(context);
- }
-
- @Override
- public void bindPreviewContent() {
- TextView header = card.findViewById(R.id.theme_preview_card_header);
- header.setText(nameResId);
- header.setCompoundDrawablesWithIntrinsicBounds(0, iconSrc, 0, 0);
- header.setCompoundDrawableTintList(ColorStateList.valueOf(accentColor));
- card.findViewById(R.id.theme_preview_top_bar).setVisibility(View.GONE);
- card.findViewById(R.id.edit_label).setVisibility(View.GONE);
-
- ViewGroup body = card.findViewById(R.id.theme_preview_card_body_container);
- inflater.inflate(contentLayoutRes, body, true);
- bindBody(false);
- }
-
- protected boolean containsWallpaper() {
- return false;
- }
-
- protected abstract void bindBody(boolean forceRebind);
- }
-
- private static class ThemeCoverPage extends ThemePreviewPage {
-
- private final Typeface mHeadlineFont;
- private final List<Drawable> mIcons;
- private String mTitle;
- private OnClickListener mEditClickListener;
- private final ThemePreviewAdapter.WallpaperPreviewLayoutListener mListener;
- private final int mCornerRadius;
-
- private ThemeCoverPage(Context context, String title, int accentColor, List<Drawable> icons,
- Typeface headlineFont, int cornerRadius,
- OnClickListener editClickListener,
- ThemePreviewAdapter.WallpaperPreviewLayoutListener wallpaperListener) {
- super(context, 0, 0, R.layout.preview_card_cover_content, accentColor);
- mTitle = title;
- mHeadlineFont = headlineFont;
- mIcons = icons;
- mCornerRadius = cornerRadius;
- mEditClickListener = editClickListener;
- mListener = wallpaperListener;
- }
-
- @Override
- protected void bindBody(boolean forceRebind) {
- card.addOnLayoutChangeListener(mListener);
- if (forceRebind) {
- card.requestLayout();
- }
- }
-
- @Override
- public void bindPreviewContent() {
- TextView header = card.findViewById(R.id.theme_preview_card_header);
- header.setText(mTitle);
- header.setTextAppearance(R.style.CoverTitleTextAppearance);
- header.setTypeface(mHeadlineFont);
-
- card.findViewById(R.id.theme_preview_top_bar).setVisibility(View.VISIBLE);
- TextView clock = card.findViewById(R.id.theme_preview_clock);
- clock.setText(getFormattedTime());
- clock.setTypeface(mHeadlineFont);
-
- ViewGroup iconsContainer = card.findViewById(R.id.theme_preview_top_bar_icons);
-
- for (int i = 0; i < iconsContainer.getChildCount() && i < mIcons.size(); i++) {
- ((ImageView) iconsContainer.getChildAt(i))
- .setImageDrawable(mIcons.get(i).getConstantState().newDrawable().mutate());
- }
-
- ViewGroup body = card.findViewById(R.id.theme_preview_card_body_container);
-
- inflater.inflate(contentLayoutRes, body, true);
-
- bindBody(false);
-
- TextView editLabel = card.findViewById(R.id.edit_label);
- editLabel.setOnClickListener(mEditClickListener);
- card.setOnClickListener(mEditClickListener);
- editLabel.setVisibility(mEditClickListener != null
- ? View.VISIBLE : View.INVISIBLE);
- ColorStateList themeAccentColor = ColorStateList.valueOf(accentColor);
- editLabel.setTextColor(themeAccentColor);
- editLabel.setCompoundDrawableTintList(themeAccentColor);
- View qsb = card.findViewById(R.id.theme_qsb);
- if (qsb != null && qsb.getVisibility() == View.VISIBLE) {
- if (qsb.getBackground() instanceof GradientDrawable) {
- GradientDrawable bg = (GradientDrawable) qsb.getBackground();
- float cornerRadius = useRoundedQSB(mCornerRadius)
- ? (float)qsb.getLayoutParams().height / 2 : mCornerRadius;
- bg.setCornerRadii(new float[]{
- cornerRadius, cornerRadius, cornerRadius, cornerRadius,
- cornerRadius, cornerRadius, cornerRadius, cornerRadius});
- }
- }
- }
-
- private boolean useRoundedQSB(int cornerRadius) {
- return cornerRadius >=
- card.getResources().getDimensionPixelSize(R.dimen.roundCornerThreshold);
- }
-
- private String getFormattedTime() {
- DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
- StringBuffer time = new StringBuffer();
- FieldPosition amPmPosition = new FieldPosition(DateFormat.Field.AM_PM);
- df.format(Calendar.getInstance(TimeZone.getDefault()).getTime(), time, amPmPosition);
- if (amPmPosition.getBeginIndex() > 0) {
- time.delete(amPmPosition.getBeginIndex(), amPmPosition.getEndIndex());
- }
- return time.toString();
- }
-
- @Override
- protected boolean containsWallpaper() {
- return true;
- }
- }
-
/**
* Adapter class for mPreviewPager.
* This is a ViewPager as it allows for a nice pagination effect (ie, pages snap on swipe,
@@ -473,66 +324,9 @@
addPage(new ThemeCoverPage(activity, theme.getTitle(),
previewInfo.resolveAccentColor(res), previewInfo.icons,
previewInfo.headlineFontFamily, previewInfo.bottomSheeetCornerRadius,
- editClickListener,
- new WallpaperPreviewLayoutListener(theme, previewInfo, true)) {
-
- @Override
- protected void bindBody(boolean forceRebind) {
- if (card == null) {
- return;
- }
- card.addOnLayoutChangeListener(coverCardLayoutListener);
- super.bindBody(forceRebind);
-
- // Color QS icons:
- int controlGreyColor = res.getColor(R.color.control_grey);
- ColorStateList tintList = new ColorStateList(
- new int[][]{
- new int[]{android.R.attr.state_selected},
- new int[]{android.R.attr.state_checked},
- new int[]{-android.R.attr.state_enabled},
- },
- new int[] {
- accentColor,
- accentColor,
- controlGreyColor
- }
- );
-
- for (int i = 0; i < mColorButtonIds.length; i++) {
- CompoundButton button = card.findViewById(mColorButtonIds[i]);
- if (button != null) {
- button.setButtonTintList(tintList);
- }
- }
- for (int i = 0; i < 3 && i < previewInfo.icons.size(); i++) {
- Drawable icon =
- previewInfo.icons.get(i).getConstantState().newDrawable().mutate();
- Drawable bgShape =
- previewInfo.shapeDrawable.getConstantState().newDrawable();
- bgShape.setTint(accentColor);
-
- ImageView bg = card.findViewById(mColorTileIds[i]);
- bg.setImageDrawable(bgShape);
- ImageView fg = card.findViewById(mColorTileIconIds[i]);
- fg.setImageDrawable(icon);
- }
-
- // Shape preview icons:
-
- for (int i = 0; i < 3 && i < previewInfo.shapeAppIcons.size(); i++) {
- ImageView iconView = card.findViewById(mShapeIconIds[i]);
- iconView.setBackground(
- previewInfo.shapeAppIcons.get(i));
- }
-
- Drawable background = card.findViewById(R.id.theme_preview_card_background)
- .getBackground();
- if (background != null) {
- background.setAlpha(128);
- }
- }
- });
+ previewInfo.shapeDrawable, previewInfo.shapeAppIcons, editClickListener,
+ mColorButtonIds, mColorTileIds, mColorTileIconIds, mShapeIconIds,
+ new WallpaperPreviewLayoutListener(theme, previewInfo, true)));
addPage(new ThemePreviewPage(activity, R.string.preview_name_font, R.drawable.ic_font,
R.layout.preview_card_font_content,
previewInfo.resolveAccentColor(res)) {
diff --git a/src/com/android/customization/picker/theme/ThemePreviewPage.java b/src/com/android/customization/picker/theme/ThemePreviewPage.java
new file mode 100644
index 0000000..73bd886
--- /dev/null
+++ b/src/com/android/customization/picker/theme/ThemePreviewPage.java
@@ -0,0 +1,238 @@
+package com.android.customization.picker.theme;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.icu.text.DateFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.LayoutRes;
+import androidx.annotation.StringRes;
+
+import com.android.customization.picker.BasePreviewAdapter.PreviewPage;
+import com.android.wallpaper.R;
+
+import java.text.FieldPosition;
+import java.util.Calendar;
+import java.util.List;
+import java.util.TimeZone;
+
+abstract class ThemePreviewPage extends PreviewPage {
+ @StringRes
+ final int nameResId;
+ @DrawableRes
+ final int iconSrc;
+ @LayoutRes
+ final int contentLayoutRes;
+ @ColorInt
+ final int accentColor;
+ protected final LayoutInflater inflater;
+
+ public ThemePreviewPage(Context context, @StringRes int titleResId,
+ @DrawableRes int iconSrc, @LayoutRes int contentLayoutRes,
+ @ColorInt int accentColor) {
+ super(null);
+ this.nameResId = titleResId;
+ this.iconSrc = iconSrc;
+ this.contentLayoutRes = contentLayoutRes;
+ this.accentColor = accentColor;
+ this.inflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public void bindPreviewContent() {
+ TextView header = card.findViewById(R.id.theme_preview_card_header);
+ header.setText(nameResId);
+ header.setCompoundDrawablesWithIntrinsicBounds(0, iconSrc, 0, 0);
+ header.setCompoundDrawableTintList(ColorStateList.valueOf(accentColor));
+ card.findViewById(R.id.theme_preview_top_bar).setVisibility(View.GONE);
+ card.findViewById(R.id.edit_label).setVisibility(View.GONE);
+
+ ViewGroup body = card.findViewById(R.id.theme_preview_card_body_container);
+ inflater.inflate(contentLayoutRes, body, true);
+ bindBody(false);
+ }
+
+ protected boolean containsWallpaper() {
+ return false;
+ }
+
+ protected abstract void bindBody(boolean forceRebind);
+
+ static class ThemeCoverPage extends ThemePreviewPage {
+
+ private final Typeface mHeadlineFont;
+ private final List<Drawable> mIcons;
+ private final List<Drawable> mShapeAppIcons;
+ private Drawable mShapeDrawable;
+ private final int[] mColorButtonIds;
+ private final int[] mColorTileIds;
+ private final int[] mColorTileIconIds;
+ private final int[] mShapeIconIds;
+ private final Resources mRes;
+ private String mTitle;
+ private OnClickListener mEditClickListener;
+ private final OnLayoutChangeListener mListener;
+ private final int mCornerRadius;
+
+ public ThemeCoverPage(Context context, String title, int accentColor, List<Drawable> icons,
+ Typeface headlineFont, int cornerRadius,
+ Drawable shapeDrawable,
+ List<Drawable> shapeAppIcons,
+ OnClickListener editClickListener,
+ int[] colorButtonIds, int[] colorTileIds, int[] colorTileIconIds,
+ int[] shapeIconIds, OnLayoutChangeListener wallpaperListener) {
+ super(context, 0, 0, R.layout.preview_card_cover_content, accentColor);
+ mRes = context.getResources();
+ mTitle = title;
+ mHeadlineFont = headlineFont;
+ mIcons = icons;
+ mCornerRadius = cornerRadius;
+ mShapeDrawable = shapeDrawable;
+ mShapeAppIcons = shapeAppIcons;
+ mEditClickListener = editClickListener;
+ mColorButtonIds = colorButtonIds;
+ mColorTileIds = colorTileIds;
+ mColorTileIconIds = colorTileIconIds;
+ mShapeIconIds = shapeIconIds;
+ mListener = wallpaperListener;
+ }
+
+ @Override
+ protected void bindBody(boolean forceRebind) {
+ if (card == null) {
+ return;
+ }
+
+ card.addOnLayoutChangeListener(mListener);
+ if (forceRebind) {
+ card.requestLayout();
+ }
+
+ // Color QS icons:
+ int controlGreyColor = mRes.getColor(R.color.control_grey, null);
+ ColorStateList tintList = new ColorStateList(
+ new int[][]{
+ new int[]{android.R.attr.state_selected},
+ new int[]{android.R.attr.state_checked},
+ new int[]{-android.R.attr.state_enabled},
+ },
+ new int[] {
+ accentColor,
+ accentColor,
+ controlGreyColor
+ }
+ );
+
+ for (int i = 0; i < mColorButtonIds.length; i++) {
+ CompoundButton button = card.findViewById(mColorButtonIds[i]);
+ if (button != null) {
+ button.setButtonTintList(tintList);
+ }
+ }
+ for (int i = 0; i < 3 && i < mIcons.size(); i++) {
+ Drawable icon =
+ mIcons.get(i).getConstantState().newDrawable().mutate();
+ Drawable bgShape = mShapeDrawable.getConstantState().newDrawable();
+ bgShape.setTint(accentColor);
+
+ ImageView bg = card.findViewById(mColorTileIds[i]);
+ bg.setImageDrawable(bgShape);
+ ImageView fg = card.findViewById(mColorTileIconIds[i]);
+ fg.setImageDrawable(icon);
+ }
+
+ // Shape preview icons:
+
+ for (int i = 0; i < 3 && i < mShapeAppIcons.size(); i++) {
+ ImageView iconView = card.findViewById(mShapeIconIds[i]);
+ iconView.setBackground(mShapeAppIcons.get(i));
+ }
+
+ Drawable background = card.findViewById(R.id.theme_preview_card_background)
+ .getBackground();
+ if (background != null) {
+ background.setAlpha(128);
+ }
+ }
+
+ @Override
+ public void bindPreviewContent() {
+ TextView header = card.findViewById(R.id.theme_preview_card_header);
+ header.setText(mTitle);
+ header.setTextAppearance(R.style.CoverTitleTextAppearance);
+ header.setTypeface(mHeadlineFont);
+
+ card.findViewById(R.id.theme_preview_top_bar).setVisibility(View.VISIBLE);
+ TextView clock = card.findViewById(R.id.theme_preview_clock);
+ clock.setText(getFormattedTime());
+ clock.setTypeface(mHeadlineFont);
+
+ ViewGroup iconsContainer = card.findViewById(R.id.theme_preview_top_bar_icons);
+
+ for (int i = 0; i < iconsContainer.getChildCount() && i < mIcons.size(); i++) {
+ ((ImageView) iconsContainer.getChildAt(i))
+ .setImageDrawable(mIcons.get(i).getConstantState().newDrawable().mutate());
+ }
+
+ ViewGroup body = card.findViewById(R.id.theme_preview_card_body_container);
+
+ inflater.inflate(contentLayoutRes, body, true);
+
+ bindBody(false);
+
+ TextView editLabel = card.findViewById(R.id.edit_label);
+ editLabel.setOnClickListener(mEditClickListener);
+ card.setOnClickListener(mEditClickListener);
+ editLabel.setVisibility(mEditClickListener != null
+ ? View.VISIBLE : View.INVISIBLE);
+ ColorStateList themeAccentColor = ColorStateList.valueOf(accentColor);
+ editLabel.setTextColor(themeAccentColor);
+ editLabel.setCompoundDrawableTintList(themeAccentColor);
+ View qsb = card.findViewById(R.id.theme_qsb);
+ if (qsb != null && qsb.getVisibility() == View.VISIBLE) {
+ if (qsb.getBackground() instanceof GradientDrawable) {
+ GradientDrawable bg = (GradientDrawable) qsb.getBackground();
+ float cornerRadius = useRoundedQSB(mCornerRadius)
+ ? (float)qsb.getLayoutParams().height / 2 : mCornerRadius;
+ bg.setCornerRadii(new float[]{
+ cornerRadius, cornerRadius, cornerRadius, cornerRadius,
+ cornerRadius, cornerRadius, cornerRadius, cornerRadius});
+ }
+ }
+ }
+
+ private boolean useRoundedQSB(int cornerRadius) {
+ return cornerRadius >=
+ card.getResources().getDimensionPixelSize(R.dimen.roundCornerThreshold);
+ }
+
+ private String getFormattedTime() {
+ DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
+ StringBuffer time = new StringBuffer();
+ FieldPosition amPmPosition = new FieldPosition(DateFormat.Field.AM_PM);
+ df.format(Calendar.getInstance(TimeZone.getDefault()).getTime(), time, amPmPosition);
+ if (amPmPosition.getBeginIndex() > 0) {
+ time.delete(amPmPosition.getBeginIndex(), amPmPosition.getEndIndex());
+ }
+ return time.toString();
+ }
+
+ @Override
+ protected boolean containsWallpaper() {
+ return true;
+ }
+ }
+}