Merge "Fix state restoration ordering for ThemePicker." into ub-launcher3-qt-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0046cad..4857768 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />
<application
android:extractNativeLibs="false"
diff --git a/res/layout/theme_color_option.xml b/res/layout/theme_color_option.xml
index 0b7ca9e..72acd8b 100644
--- a/res/layout/theme_color_option.xml
+++ b/res/layout/theme_color_option.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginHorizontal="6dp"
- android:paddingHorizontal="4dp">
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:padding="4dp">
<ImageView
android:id="@+id/option_tile"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 465a926..30123ed 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -57,7 +57,6 @@
<dimen name="theme_option_title_font_text_size">12sp</dimen>
<dimen name="option_tile_margin_horizontal">4dp</dimen>
- <dimen name="option_tile_margin_horizontal_ends">10dp</dimen>
<dimen name="theme_option_label_margin">4dp</dimen>
<dimen name="preview_card_corner_radius">8dp</dimen>
diff --git a/res/values/integers.xml b/res/values/integers.xml
new file mode 100644
index 0000000..6e2db17
--- /dev/null
+++ b/res/values/integers.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<resources>
+ <integer name="options_grid_num_columns">4</integer>
+</resources>
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index a2b9ab5..e282cbd 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -31,15 +31,20 @@
import static com.android.customization.model.ResourceConstants.SETTINGS_PACKAGE;
import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.om.OverlayInfo;
import android.content.om.OverlayManager;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
+import android.service.wallpaper.WallpaperService;
import android.text.TextUtils;
import android.util.Log;
@@ -54,12 +59,15 @@
import com.android.customization.module.CustomizationPreferences;
import com.android.wallpaper.R;
import com.android.wallpaper.asset.ResourceAsset;
+import com.android.wallpaper.model.LiveWallpaperInfo;
import com.bumptech.glide.request.RequestOptions;
import org.json.JSONException;
import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParserException;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -169,26 +177,7 @@
addNoPreviewIconOverlay(builder, iconSettingsOverlayPackage);
- try {
- String wallpaperResName = WALLPAPER_PREFIX + themeName;
- int wallpaperResId = mStubApkResources.getIdentifier(wallpaperResName,
- "drawable", mStubPackageName);
- if (wallpaperResId > 0) {
- builder.setWallpaperInfo(mStubPackageName, wallpaperResName,
- themeName, wallpaperResId,
- mStubApkResources.getIdentifier(WALLPAPER_TITLE_PREFIX + themeName,
- "string", mStubPackageName),
- mStubApkResources.getIdentifier(
- WALLPAPER_ATTRIBUTION_PREFIX + themeName, "string",
- mStubPackageName),
- mStubApkResources.getIdentifier(WALLPAPER_ACTION_PREFIX + themeName,
- "string", mStubPackageName))
- .setWallpaperAsset(
- getDrawableResourceAsset(WALLPAPER_PREFIX, themeName));
- }
- } catch (NotFoundException e) {
- // Nothing to do here, if there's no wallpaper we'll just omit wallpaper
- }
+ addWallpaper(themeName, builder);
mThemes.add(builder.build(mContext));
} catch (NameNotFoundException | NotFoundException e) {
@@ -200,6 +189,58 @@
addCustomTheme();
}
+ private void addWallpaper(String themeName, Builder builder) {
+ try {
+ String wallpaperResName = WALLPAPER_PREFIX + themeName;
+ int wallpaperResId = mStubApkResources.getIdentifier(wallpaperResName,
+ "drawable", mStubPackageName);
+ if (wallpaperResId > 0) {
+ builder.setWallpaperInfo(mStubPackageName, wallpaperResName,
+ themeName, wallpaperResId,
+ mStubApkResources.getIdentifier(WALLPAPER_TITLE_PREFIX + themeName,
+ "string", mStubPackageName),
+ mStubApkResources.getIdentifier(
+ WALLPAPER_ATTRIBUTION_PREFIX + themeName, "string",
+ mStubPackageName),
+ mStubApkResources.getIdentifier(WALLPAPER_ACTION_PREFIX + themeName,
+ "string", mStubPackageName))
+ .setWallpaperAsset(
+ getDrawableResourceAsset(WALLPAPER_PREFIX, themeName));
+ } else {
+ // Try to see if it's a live wallpaper reference
+ wallpaperResId = mStubApkResources.getIdentifier(wallpaperResName,
+ "string", mStubPackageName);
+ if (wallpaperResId > 0) {
+ String wpComponent = mStubApkResources.getString(wallpaperResId);
+ String[] componentParts = wpComponent.split("/");
+ Intent liveWpIntent = new Intent(WallpaperService.SERVICE_INTERFACE);
+ liveWpIntent.setComponent(
+ new ComponentName(componentParts[0],
+ componentParts[0] + componentParts[1]));
+ Context appContext = mContext.getApplicationContext();
+ PackageManager pm = appContext.getPackageManager();
+ ResolveInfo resolveInfo =
+ pm.resolveService(liveWpIntent, PackageManager.GET_META_DATA);
+ if (resolveInfo != null) {
+ android.app.WallpaperInfo wallpaperInfo;
+ try {
+ wallpaperInfo = new android.app.WallpaperInfo(appContext, resolveInfo);
+ LiveWallpaperInfo liveInfo = new LiveWallpaperInfo(wallpaperInfo);
+ builder.setLiveWallpaperInfo(liveInfo)
+ .setWallpaperAsset(liveInfo.getThumbAsset(mContext));
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Skipping wallpaper " + resolveInfo.serviceInfo, e);
+ } catch (IOException e) {
+ Log.w(TAG, "Skipping wallpaper " + resolveInfo.serviceInfo, e);
+ }
+ }
+ }
+ }
+ } catch (NotFoundException e) {
+ // Nothing to do here, if there's no wallpaper we'll just omit wallpaper
+ }
+ }
+
private void addColorOverlay(Builder builder, String colorOverlayPackage)
throws NameNotFoundException {
if (!TextUtils.isEmpty(colorOverlayPackage)) {
@@ -373,29 +414,7 @@
addSystemDefaultIcons(builder, SYSUI_PACKAGE, ICONS_FOR_PREVIEW);
}
- try {
- String wallpaperResName = WALLPAPER_PREFIX + DEFAULT_THEME_NAME;
- int wallpaperResId = mStubApkResources.getIdentifier(wallpaperResName,
- "drawable", mStubPackageName);
- if (wallpaperResId > 0) {
- builder.setWallpaperInfo(mStubPackageName, wallpaperResName, DEFAULT_THEME_NAME,
- mStubApkResources.getIdentifier(
- wallpaperResName,
- "drawable", mStubPackageName),
- mStubApkResources.getIdentifier(WALLPAPER_TITLE_PREFIX + DEFAULT_THEME_NAME,
- "string", mStubPackageName),
- mStubApkResources.getIdentifier(
- WALLPAPER_ATTRIBUTION_PREFIX + DEFAULT_THEME_NAME, "string",
- mStubPackageName),
- mStubApkResources.getIdentifier(
- WALLPAPER_ACTION_PREFIX + DEFAULT_THEME_NAME,
- "string", mStubPackageName))
- .setWallpaperAsset(
- getDrawableResourceAsset(WALLPAPER_PREFIX, DEFAULT_THEME_NAME));
- }
- } catch (NotFoundException e) {
- // Nothing to do here, if there's no wallpaper we'll just omit wallpaper
- }
+ addWallpaper(DEFAULT_THEME_NAME, builder);
mThemes.add(builder.build(mContext));
}
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index e13efb5..414719e 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -45,12 +45,12 @@
import com.android.customization.model.CustomizationManager;
import com.android.customization.model.CustomizationOption;
-import com.android.customization.model.theme.custom.CustomTheme;
import com.android.customization.widget.DynamicAdaptiveIconDrawable;
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;
import org.json.JSONObject;
@@ -108,7 +108,7 @@
mPreviewInfo.shapeDrawable);
}
if (!mPreviewInfo.icons.isEmpty()) {
- Drawable icon = mPreviewInfo.icons.get(0).mutate();
+ Drawable icon = mPreviewInfo.icons.get(0).getConstantState().newDrawable().mutate();
icon.setTint(res.getColor(R.color.icon_thumbnail_color, null));
((ImageView) view.findViewById(R.id.theme_option_icon)).setImageDrawable(
icon);
@@ -256,7 +256,7 @@
private PreviewInfo(Context context, Typeface bodyFontFamily, Typeface headlineFontFamily,
int colorAccentLight, int colorAccentDark, List<Drawable> icons,
Drawable shapeDrawable, @Dimension int cornerRadius,
- @Nullable ResourceAsset wallpaperAsset, List<Drawable> shapeAppIcons) {
+ @Nullable Asset wallpaperAsset, List<Drawable> shapeAppIcons) {
this.bodyFontFamily = bodyFontFamily;
this.headlineFontFamily = headlineFontFamily;
this.colorAccentLight = colorAccentLight;
@@ -291,7 +291,7 @@
private String mShapePath;
private boolean mIsDefault;
@Dimension private int mCornerRadius;
- private ResourceAsset mWallpaperAsset;
+ private Asset mWallpaperAsset;
private WallpaperInfo mWallpaperInfo;
protected Map<String, String> mPackages = new HashMap<>();
private List<Drawable> mAppIcons = new ArrayList<>();
@@ -373,7 +373,13 @@
return this;
}
- public Builder setWallpaperAsset(ResourceAsset wallpaperAsset) {
+ public Builder setLiveWallpaperInfo(LiveWallpaperInfo info) {
+ mWallpaperInfo = info;
+ return this;
+ }
+
+
+ public Builder setWallpaperAsset(Asset wallpaperAsset) {
mWallpaperAsset = wallpaperAsset;
return this;
}
diff --git a/src/com/android/customization/model/theme/ThemeManager.java b/src/com/android/customization/model/theme/ThemeManager.java
index ec859bf..cd33f6b 100644
--- a/src/com/android/customization/model/theme/ThemeManager.java
+++ b/src/com/android/customization/model/theme/ThemeManager.java
@@ -27,9 +27,7 @@
import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
import android.graphics.Point;
-import android.os.UserHandle;
import android.provider.Settings;
-import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
@@ -40,8 +38,6 @@
import com.android.customization.module.ThemesUserEventLogger;
import com.android.wallpaper.R;
import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.module.Injector;
-import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.WallpaperPersister;
import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
import com.android.wallpaper.module.WallpaperSetter;
@@ -95,7 +91,8 @@
// Set wallpaper
if (theme.shouldUseThemeWallpaper()) {
mWallpaperSetter.requestDestination(mActivity, mActivity.getSupportFragmentManager(),
- R.string.set_theme_wallpaper_dialog_message, new Listener() {
+ R.string.set_theme_wallpaper_dialog_message, theme.getWallpaperInfo(),
+ new Listener() {
@Override
public void onSetHomeScreen() {
applyWallpaper(theme, WallpaperPersister.DEST_HOME_SCREEN,
@@ -140,19 +137,27 @@
mActivity.getResources(),
mActivity.getWindowManager().getDefaultDisplay());
Asset wallpaperAsset = theme.getWallpaperInfo().getAsset(mActivity);
- wallpaperAsset.decodeRawDimensions(mActivity,
- dimensions -> {
- float scale = 1f;
- // Calculate scale to fit the screen height
- if (dimensions != null && dimensions.y > 0) {
- scale = (float) defaultCropSurfaceSize.y / dimensions.y;
- }
- mWallpaperSetter.setCurrentWallpaper(mActivity,
- theme.getWallpaperInfo(),
- wallpaperAsset,
- destination,
- scale, null, callback);
- });
+ if (wallpaperAsset != null) {
+ wallpaperAsset.decodeRawDimensions(mActivity,
+ dimensions -> {
+ float scale = 1f;
+ // Calculate scale to fit the screen height
+ if (dimensions != null && dimensions.y > 0) {
+ scale = (float) defaultCropSurfaceSize.y / dimensions.y;
+ }
+ mWallpaperSetter.setCurrentWallpaper(mActivity,
+ theme.getWallpaperInfo(),
+ wallpaperAsset,
+ destination,
+ scale, null, callback);
+ });
+ } else {
+ mWallpaperSetter.setCurrentWallpaper(mActivity,
+ theme.getWallpaperInfo(),
+ null,
+ destination,
+ 1f, null, callback);
+ }
}
private void applyOverlays(ThemeBundle theme, Callback callback) {
diff --git a/src/com/android/customization/picker/theme/CustomThemeActivity.java b/src/com/android/customization/picker/theme/CustomThemeActivity.java
index df14c86..40d1fe8 100644
--- a/src/com/android/customization/picker/theme/CustomThemeActivity.java
+++ b/src/com/android/customization/picker/theme/CustomThemeActivity.java
@@ -339,7 +339,8 @@
return CustomThemeComponentFragment.newInstance(
CustomThemeActivity.this.getString(R.string.custom_theme_fragment_title),
position,
- titleResId);
+ titleResId,
+ true);
}
}
diff --git a/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java b/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
index f2088ae..cd2c067 100644
--- a/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
+++ b/src/com/android/customization/picker/theme/CustomThemeComponentFragment.java
@@ -40,6 +40,7 @@
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";
+ private static final String ARG_USE_GRID_LAYOUT = "CustomThemeComponentFragment.use_grid";;
private CustomThemeComponentFragmentHost mHost;
public interface CustomThemeComponentFragmentHost {
@@ -55,10 +56,16 @@
public static CustomThemeComponentFragment newInstance(CharSequence toolbarTitle, int position,
int titleResId) {
+ return newInstance(toolbarTitle, position, titleResId, false);
+ }
+
+ public static CustomThemeComponentFragment newInstance(CharSequence toolbarTitle, int position,
+ int titleResId, boolean allowGridLayout) {
CustomThemeComponentFragment fragment = new CustomThemeComponentFragment();
Bundle arguments = ToolbarFragment.createArguments(toolbarTitle);
arguments.putInt(ARG_KEY_POSITION, position);
arguments.putInt(ARG_KEY_TITLE_RES_ID, titleResId);
+ arguments.putBoolean(ARG_USE_GRID_LAYOUT, allowGridLayout);
fragment.setArguments(arguments);
return fragment;
}
@@ -67,6 +74,7 @@
private CustomThemeManager mCustomThemeManager;
private int mPosition;
@StringRes private int mTitleResId;
+ private boolean mUseGridLayout;
private RecyclerView mOptionsContainer;
private OptionSelectorController<ThemeComponentOption> mOptionsController;
@@ -79,6 +87,7 @@
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();
}
@@ -144,7 +153,8 @@
private void setUpOptions() {
mProvider.fetch(options -> {
- mOptionsController = new OptionSelectorController(mOptionsContainer, options);
+ mOptionsController = new OptionSelectorController(
+ mOptionsContainer, options, mUseGridLayout, false);
mOptionsController.addListener(selected -> {
mSelectedOption = (ThemeComponentOption) selected;
diff --git a/src/com/android/customization/picker/theme/ThemeFragment.java b/src/com/android/customization/picker/theme/ThemeFragment.java
index 7e1982a..7f6754f 100644
--- a/src/com/android/customization/picker/theme/ThemeFragment.java
+++ b/src/com/android/customization/picker/theme/ThemeFragment.java
@@ -384,7 +384,8 @@
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));
+ ((ImageView) iconsContainer.getChildAt(i))
+ .setImageDrawable(mIcons.get(i).getConstantState().newDrawable().mutate());
}
ViewGroup body = card.findViewById(R.id.theme_preview_card_body_container);
@@ -503,7 +504,7 @@
}
for (int i = 0; i < 3 && i < previewInfo.icons.size(); i++) {
Drawable icon =
- previewInfo.icons.get(i).getConstantState().newDrawable();
+ previewInfo.icons.get(i).getConstantState().newDrawable().mutate();
Drawable bgShape =
previewInfo.shapeDrawable.getConstantState().newDrawable();
bgShape.setTint(accentColor);
@@ -548,8 +549,9 @@
@Override
protected void bindBody(boolean forceRebind) {
for (int i = 0; i < mIconIds.length && i < previewInfo.icons.size(); i++) {
- ((ImageView) card.findViewById(mIconIds[i])).setImageDrawable(
- previewInfo.icons.get(i));
+ ((ImageView) card.findViewById(mIconIds[i]))
+ .setImageDrawable(previewInfo.icons.get(i)
+ .getConstantState().newDrawable().mutate());
}
}
});
@@ -601,10 +603,10 @@
for (int i = 0; i < mColorTileIds.length && i < previewInfo.icons.size();
i++) {
- Drawable icon =
- previewInfo.icons.get(i).getConstantState().newDrawable();
+ Drawable icon = previewInfo.icons.get(i)
+ .getConstantState().newDrawable().mutate();
Drawable bgShape =
- previewInfo.shapeDrawable.getConstantState().newDrawable();
+ previewInfo.shapeDrawable.getConstantState().newDrawable();
bgShape.setTint(accentColor);
ImageView bg = card.findViewById(mColorTileIds[i]);
diff --git a/src/com/android/customization/widget/HorizontalSpacerItemDecoration.java b/src/com/android/customization/widget/HorizontalSpacerItemDecoration.java
index f17d52f..df38e6e 100644
--- a/src/com/android/customization/widget/HorizontalSpacerItemDecoration.java
+++ b/src/com/android/customization/widget/HorizontalSpacerItemDecoration.java
@@ -11,24 +11,22 @@
/**
* RecyclerView ItemDecorator that adds a horizontal space of the given size between items
- * (except the first and last)
+ * and double that space on the ends.
*/
public class HorizontalSpacerItemDecoration extends ItemDecoration {
private final int mOffset;
- private final int mEndOffset;
- public HorizontalSpacerItemDecoration(@Dimension int offset, @Dimension int endOffset) {
+ public HorizontalSpacerItemDecoration(@Dimension int offset) {
mOffset = offset;
- mEndOffset = endOffset;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
@NonNull RecyclerView parent, @NonNull State state) {
int position = parent.getChildAdapterPosition(view);
- int left = position == 0 ? mEndOffset : mOffset;
- int right = (position == parent.getAdapter().getItemCount() - 1) ? mEndOffset : mOffset;
+ int left = position == 0 ? mOffset * 2: mOffset;
+ int right = (position == parent.getAdapter().getItemCount() - 1) ? mOffset * 2 : mOffset;
outRect.set(left, 0, right, 0);
}
}
diff --git a/src/com/android/customization/widget/OptionSelectorController.java b/src/com/android/customization/widget/OptionSelectorController.java
index 615d7d8..b311abe 100644
--- a/src/com/android/customization/widget/OptionSelectorController.java
+++ b/src/com/android/customization/widget/OptionSelectorController.java
@@ -18,18 +18,22 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.android.customization.model.CustomizationManager;
import com.android.customization.model.CustomizationOption;
+import com.android.customization.model.theme.custom.ThemeComponentOption;
import com.android.wallpaper.R;
import java.util.HashSet;
@@ -49,6 +53,7 @@
* Interface to be notified when an option is selected by the user.
*/
public interface OptionSelectedListener {
+
/**
* Called when an option has been selected (and marked as such in the UI)
*/
@@ -57,6 +62,8 @@
private final RecyclerView mContainer;
private final List<T> mOptions;
+ private final boolean mUseGrid;
+ private final boolean mShowCheckmark;
private final Set<OptionSelectedListener> mListeners = new HashSet<>();
private RecyclerView.Adapter<TileViewHolder> mAdapter;
@@ -64,8 +71,15 @@
private CustomizationOption mAppliedOption;
public OptionSelectorController(RecyclerView container, List<T> options) {
+ this(container, options, false, true);
+ }
+
+ public OptionSelectorController(RecyclerView container, List<T> options,
+ boolean useGrid, boolean showCheckmark) {
mContainer = container;
mOptions = options;
+ mUseGrid = useGrid;
+ mShowCheckmark = showCheckmark;
}
public void addListener(OptionSelectedListener listener) {
@@ -140,7 +154,7 @@
holder.itemView.setActivated(option.equals(mSelectedOption));
holder.itemView.setOnClickListener(view -> setSelectedOption(option));
- if (option.equals(mAppliedOption)) {
+ if (mShowCheckmark && option.equals(mAppliedOption)) {
Resources res = mContainer.getContext().getResources();
Drawable checkmark = res.getDrawable(R.drawable.ic_check_circle_filled_24px);
Drawable frame = holder.itemView.getForeground();
@@ -171,10 +185,38 @@
mContainer.setLayoutManager(new LinearLayoutManager(mContainer.getContext(),
LinearLayoutManager.HORIZONTAL, false));
Resources res = mContainer.getContext().getResources();
- mContainer.addItemDecoration(new HorizontalSpacerItemDecoration(
- res.getDimensionPixelOffset(R.dimen.option_tile_margin_horizontal),
- res.getDimensionPixelOffset(R.dimen.option_tile_margin_horizontal_ends)));
mContainer.setAdapter(mAdapter);
+
+ // Measure RecyclerView to get to the total amount of space used by all options.
+ mContainer.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ DisplayMetrics metrics = new DisplayMetrics();
+ // TODO: retrieve fixed container width for landscape
+ mContainer.getContext().getSystemService(WindowManager.class)
+ .getDefaultDisplay().getMetrics(metrics);
+ int totalWidth = mContainer.getMeasuredWidth();
+
+ if (mUseGrid) {
+ int numColumns = res.getInteger(R.integer.options_grid_num_columns);
+ int widthPerItem = totalWidth / mAdapter.getItemCount();
+ int extraSpace = metrics.widthPixels - widthPerItem * numColumns;
+ int containerSidePadding = extraSpace / (numColumns + 1);
+ mContainer.setLayoutManager(new GridLayoutManager(mContainer.getContext(), numColumns));
+ mContainer.setPaddingRelative(containerSidePadding, 0, containerSidePadding, 0);
+ mContainer.setOverScrollMode(View.OVER_SCROLL_NEVER);
+ return;
+ }
+
+ int extraSpace = metrics.widthPixels - totalWidth;
+ if (extraSpace >= 0) {
+ mContainer.setOverScrollMode(View.OVER_SCROLL_NEVER);
+ }
+ int itemSideMargin = res.getDimensionPixelOffset(R.dimen.option_tile_margin_horizontal);
+ int defaultTotalPadding = itemSideMargin * (mAdapter.getItemCount() * 2 + 2);
+ if (extraSpace > defaultTotalPadding) {
+ int spaceBetweenItems = extraSpace / (mAdapter.getItemCount() + 1);
+ itemSideMargin = spaceBetweenItems / 2;
+ }
+ mContainer.addItemDecoration(new HorizontalSpacerItemDecoration(itemSideMargin));
}
public void resetOptions(List<T> options) {