summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYvonne Wong <ywong@cyngn.com>2015-12-01 17:04:07 -0800
committerTom Powell <zifnab@zifnab06.net>2017-03-26 15:52:42 -0700
commit9c9418bc626d36dce33f2ac6513e7407f07298d4 (patch)
tree06b1b9bc48a3bbd03c5aa66ab8ee637ace1ae70f /src
parent14e1bef375ccb9e719bac1877c53359fad8d9d47 (diff)
downloadandroid_packages_apps_Trebuchet-9c9418bc626d36dce33f2ac6513e7407f07298d4.tar.gz
android_packages_apps_Trebuchet-9c9418bc626d36dce33f2ac6513e7407f07298d4.tar.bz2
android_packages_apps_Trebuchet-9c9418bc626d36dce33f2ac6513e7407f07298d4.zip
Reimplement CM Settings Overview Panel Part 3
- Enable dynamic grid resizing Change-Id: I95a7f20da48e037a94ce5b6191c5597490d91d9d
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/DeviceProfile.java1
-rw-r--r--src/com/android/launcher3/DynamicGridSizeFragment.java381
-rw-r--r--src/com/android/launcher3/InsettableLinearLayout.java122
-rw-r--r--src/com/android/launcher3/InvariantDeviceProfile.java57
-rw-r--r--src/com/android/launcher3/ItemInfo.java6
-rw-r--r--src/com/android/launcher3/Launcher.java130
-rw-r--r--src/com/android/launcher3/LauncherModel.java103
-rw-r--r--src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java27
8 files changed, 781 insertions, 46 deletions
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 7e9d8f8a7..6115df62f 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -37,7 +37,6 @@ import com.android.launcher3.settings.SettingsProvider;
import com.android.launcher3.allapps.AllAppsContainerView;
public class DeviceProfile {
-
public final InvariantDeviceProfile inv;
// Device properties
diff --git a/src/com/android/launcher3/DynamicGridSizeFragment.java b/src/com/android/launcher3/DynamicGridSizeFragment.java
new file mode 100644
index 000000000..103d660dd
--- /dev/null
+++ b/src/com/android/launcher3/DynamicGridSizeFragment.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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.launcher3;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.NumberPicker;
+import android.widget.TextView;
+import com.android.launcher3.settings.SettingsProvider;
+
+public class DynamicGridSizeFragment extends Fragment
+ implements NumberPicker.OnValueChangeListener, Dialog.OnDismissListener {
+ public static final String DYNAMIC_GRID_SIZE_FRAGMENT = "DynamicGridSizeFragment";
+
+ public static final int MIN_DYNAMIC_GRID_ROWS = 2;
+ public static final int MIN_DYNAMIC_GRID_COLUMNS = 3;
+
+ GridSizeView mDynamicGrid;
+
+ ListView mListView;
+ View mCurrentSelection;
+ GridSizeAdapter mAdapter;
+ InvariantDeviceProfile.GridSize mCurrentSize;
+
+ Dialog mDialog;
+
+ int mCustomGridRows = 0;
+ int mCustomGridColumns = 0;
+
+ View.OnClickListener mSettingsItemListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCurrentSize = InvariantDeviceProfile.GridSize.getModeForValue((Integer) v.getTag());
+
+ setCleared(mCurrentSelection);
+ setSelected(v);
+ mCurrentSelection = v;
+
+ if (mCurrentSize == InvariantDeviceProfile.GridSize.Custom) {
+ showNumberPicker();
+ }
+
+ ((GridSizeAdapter) mListView.getAdapter()).notifyDataSetChanged();
+
+ mAdapter.notifyDataSetInvalidated();
+ updateGridMetrics();
+ }
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.dynamic_grid_size_screen, container, false);
+ mDynamicGrid = (GridSizeView) v.findViewById(R.id.dynamic_grid_size_image);
+ mListView = (ListView) v.findViewById(R.id.dynamic_grid_list);
+
+ Launcher launcher = (Launcher) getActivity();
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+ mListView.getLayoutParams();
+ lp.bottomMargin = ((FrameLayout.LayoutParams) launcher.getOverviewPanel()
+ .findViewById(R.id.settings_container).getLayoutParams()).bottomMargin;
+ mListView.setLayoutParams(lp);
+
+ LinearLayout titleLayout = (LinearLayout) v.findViewById(R.id.dynamic_grid_title);
+ titleLayout.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setSize();
+ }
+ });
+
+ mCurrentSize = InvariantDeviceProfile.GridSize.getModeForValue(
+ SettingsProvider.getIntCustomDefault(getActivity(),
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0));
+
+ InvariantDeviceProfile grid = getInvariantDeviceProfile();
+ mCustomGridRows = grid.numRows;
+ mCustomGridColumns = grid.numColumns;
+
+ updateGridMetrics();
+
+ Resources res = getResources();
+ int[] valueResIds = {
+ R.string.grid_size_comfortable,
+ R.string.grid_size_cozy,
+ R.string.grid_size_condensed,
+ R.string.grid_size_custom
+ };
+ mAdapter = new GridSizeAdapter(getActivity(), valueResIds);
+ mListView.setAdapter(mAdapter);
+
+ // RTL
+ ImageView navPrev = (ImageView) v.findViewById(R.id.nav_prev);
+ Configuration config = getResources().getConfiguration();
+ if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ navPrev.setImageResource(R.drawable.ic_navigation_next);
+ }
+
+ return v;
+ }
+
+ private void updateGridMetrics() {
+ if (mCurrentSize == InvariantDeviceProfile.GridSize.Custom) {
+ mDynamicGrid.setMetrics(mCustomGridRows, mCustomGridColumns);
+ } else {
+ InvariantDeviceProfile grid = getInvariantDeviceProfile();
+ mDynamicGrid.setMetrics(grid.numRowsBase + mCurrentSize.getValue(),
+ grid.numColumnsBase + mCurrentSize.getValue());
+ }
+ }
+
+ @Override
+ public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
+ if (enter) {
+ DisplayMetrics displaymetrics = new DisplayMetrics();
+ getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
+ int width = displaymetrics.widthPixels;
+ Configuration config = getResources().getConfiguration();
+ final ObjectAnimator anim;
+ if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ anim = ObjectAnimator.ofFloat(this, "translationX", -width, 0);
+ } else {
+ anim = ObjectAnimator.ofFloat(this, "translationX", width, 0);
+ }
+
+ final View darkPanel = ((Launcher) getActivity()).getDarkPanel();
+ darkPanel.setVisibility(View.VISIBLE);
+ ObjectAnimator anim2 = ObjectAnimator.ofFloat(darkPanel, "alpha", 0.0f, 0.3f);
+ anim2.start();
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd (Animator animation) {
+ darkPanel.setVisibility(View.GONE);
+ }
+ });
+
+ return anim;
+ } else {
+ return super.onCreateAnimator(transit, enter, nextAnim);
+ }
+ }
+
+ public void setSize() {
+ ((Launcher) getActivity()).setDynamicGridSize(mCurrentSize);
+ }
+
+ private void setSelected(View v) {
+ v.setBackgroundColor(Color.WHITE);
+ TextView t = (TextView) v.findViewById(R.id.item_name);
+ t.setTextColor(getResources().getColor(R.color.settings_bg_color));
+ }
+
+ private void setCleared(View v) {
+ v.setBackgroundColor(getResources().getColor(R.color.settings_bg_color));
+ TextView t = (TextView) v.findViewById(R.id.item_name);
+ t.setTextColor(Color.WHITE);
+ }
+
+ private void showNumberPicker() {
+ mDialog = new Dialog(getActivity());
+ mDialog.setTitle(getResources().getString(
+ R.string.preferences_interface_homescreen_custom));
+ mDialog.setContentView(R.layout.custom_grid_size_dialog);
+
+ NumberPicker nPRows = (NumberPicker) mDialog.findViewById(R.id.custom_rows);
+ NumberPicker nPColumns = (NumberPicker) mDialog.findViewById(R.id.custom_columns);
+
+ InvariantDeviceProfile grid = getInvariantDeviceProfile();
+ int rows = grid.numRowsBase;
+ int columns = grid.numColumnsBase;
+
+ nPRows.setMinValue(Math.max(MIN_DYNAMIC_GRID_ROWS, rows - InvariantDeviceProfile.GRID_SIZE_MIN));
+ nPRows.setMaxValue(rows + InvariantDeviceProfile.GRID_SIZE_MAX);
+ nPRows.setValue(mCustomGridRows);
+ nPRows.setWrapSelectorWheel(false);
+ nPRows.setOnValueChangedListener(this);
+ nPRows.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ nPColumns.setMinValue(Math.max(MIN_DYNAMIC_GRID_COLUMNS,
+ columns - InvariantDeviceProfile.GRID_SIZE_MIN));
+ nPColumns.setMaxValue(columns + InvariantDeviceProfile.GRID_SIZE_MAX);
+ nPColumns.setValue(mCustomGridColumns);
+ nPColumns.setWrapSelectorWheel(false);
+ nPColumns.setOnValueChangedListener(this);
+ nPColumns.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ Button button = (Button) mDialog.findViewById(R.id.dialog_confirm_button);
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+ });
+
+ mDialog.setOnDismissListener(this);
+ mDialog.show();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+
+ @Override
+ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+ if (picker.getId() == R.id.custom_rows) {
+ mCustomGridRows = newVal;
+ } else if (picker.getId() == R.id.custom_columns) {
+ mCustomGridColumns = newVal;
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ SettingsProvider.putInt(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, mCustomGridRows);
+ SettingsProvider.putInt(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, mCustomGridColumns);
+
+ mAdapter.notifyDataSetInvalidated();
+ mDynamicGrid.setMetrics(mCustomGridRows, mCustomGridColumns);
+ }
+
+ private class GridSizeAdapter extends BaseAdapter {
+ Context mContext;
+ int[] mTitleResIds;
+
+ public GridSizeAdapter(Context context, int[] resIds) {
+ mContext = context;
+ mTitleResIds = resIds;
+ }
+
+ @Override
+ public int getCount() {
+ return mTitleResIds.length;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mContext.getString(mTitleResIds[position]);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ LayoutInflater inflater = (LayoutInflater)
+ mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = inflater.inflate(R.layout.settings_pane_list_item, parent, false);
+ }
+
+ TextView textView = (TextView) convertView.findViewById(R.id.item_name);
+
+ // RTL
+ Configuration config = getResources().getConfiguration();
+ if (config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ textView.setGravity(Gravity.RIGHT);
+ }
+
+ // Set selected state
+ if (position == mCurrentSize.getValue()) {
+ if (mCurrentSelection != null) {
+ setCleared(mCurrentSelection);
+ }
+ mCurrentSelection = convertView;
+ setSelected(mCurrentSelection);
+ }
+
+ if (position == InvariantDeviceProfile.GridSize.Custom.getValue()) {
+ InvariantDeviceProfile grid = getInvariantDeviceProfile();
+
+ int rows = SettingsProvider.getIntCustomDefault(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, grid.numRowsBase);
+ int columns = SettingsProvider.getIntCustomDefault(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, grid.numColumnsBase);
+ textView.setText(mContext.getString(mTitleResIds[position], rows, columns));
+ } else {
+ textView.setText(mTitleResIds[position]);
+ }
+
+ convertView.setOnClickListener(mSettingsItemListener);
+ convertView.setTag(position);
+ return convertView;
+ }
+ }
+
+ private InvariantDeviceProfile getInvariantDeviceProfile() {
+ LauncherAppState app = LauncherAppState.getInstance();
+ return app.getInvariantDeviceProfile();
+ }
+
+ private static class GridSizeView extends View {
+ private int mRows = 0, mColumns = 0;
+ private Paint mForegroundPaint;
+ private int mBackgroundColor;
+
+ public GridSizeView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ Resources res = context.getResources();
+
+ mForegroundPaint = new Paint();
+ mForegroundPaint.setColor(res.getColor(R.color.dynamic_grid_preview_foreground));
+ mBackgroundColor = res.getColor(R.color.dynamic_grid_preview_background);
+ }
+
+ public void setMetrics(int rows, int columns) {
+ mRows = rows;
+ mColumns = columns;
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ float width = getWidth() - getPaddingLeft() - getPaddingRight();
+ float height = getHeight() - getPaddingTop() - getPaddingBottom();
+ float xOffset = getPaddingLeft();
+ float yOffset = getPaddingTop();
+
+ canvas.drawColor(mBackgroundColor);
+
+ // Draw rows
+ for (int i = 1; i < mRows; i++) {
+ float yPos = yOffset + height / mRows * i;
+ canvas.drawLine(xOffset, yPos, xOffset + width, yPos, mForegroundPaint);
+ }
+
+ // Draw columns
+ for (int j = 1; j < mColumns; j++) {
+ float xPos = xOffset + width / mColumns * j;
+ canvas.drawLine(xPos, yOffset, xPos, yOffset + height, mForegroundPaint);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/InsettableLinearLayout.java b/src/com/android/launcher3/InsettableLinearLayout.java
new file mode 100644
index 000000000..8f64713e5
--- /dev/null
+++ b/src/com/android/launcher3/InsettableLinearLayout.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod 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.launcher3;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+public class InsettableLinearLayout extends LinearLayout implements
+ ViewGroup.OnHierarchyChangeListener, Insettable {
+
+ protected Rect mInsets = new Rect();
+
+ public InsettableLinearLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnHierarchyChangeListener(this);
+ }
+
+ public void setLinearLayoutChildInsets(View child, Rect newInsets, Rect oldInsets) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (child instanceof Insettable) {
+ ((Insettable) child).setInsets(newInsets);
+ } else if (!lp.ignoreInsets) {
+ if (!lp.ignoreTopInsets) {
+ lp.topMargin += (newInsets.top - oldInsets.top);
+ }
+ lp.leftMargin += (newInsets.left - oldInsets.left);
+ lp.rightMargin += (newInsets.right - oldInsets.right);
+ if (!lp.ignoreBottomInsets) {
+ lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
+ }
+ }
+ child.setLayoutParams(lp);
+ }
+
+ @Override
+ public void setInsets(Rect insets) {
+ final int n = getChildCount();
+ for (int i = 0; i < n; i++) {
+ final View child = getChildAt(i);
+ setLinearLayoutChildInsets(child, insets, mInsets);
+ }
+ mInsets.set(insets);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ }
+
+ // Override to allow type-checking of LayoutParams.
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
+ @Override
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ public static class LayoutParams extends LinearLayout.LayoutParams {
+ boolean ignoreInsets = false;
+ boolean ignoreTopInsets = false;
+ boolean ignoreBottomInsets = false;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ TypedArray a = c.obtainStyledAttributes(attrs,
+ R.styleable.InsettableLinearLayout_Layout);
+ ignoreInsets = a.getBoolean(
+ R.styleable.InsettableLinearLayout_Layout_layout_ignoreInsets, false);
+ ignoreTopInsets = a.getBoolean(
+ R.styleable.InsettableLinearLayout_Layout_layout_ignoreTopInsets, false);
+ ignoreBottomInsets = a.getBoolean(
+ R.styleable.InsettableLinearLayout_Layout_layout_ignoreBottomInsets, false);
+ a.recycle();
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams lp) {
+ super(lp);
+ }
+ }
+
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ setLinearLayoutChildInsets(child, mInsets, new Rect());
+ }
+
+ @Override
+ public void onChildViewRemoved(View parent, View child) {
+ }
+
+}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 6d4d95292..a03cc31f2 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -33,6 +33,38 @@ import java.util.Comparator;
public class InvariantDeviceProfile {
+ public enum GridSize {
+ Comfortable(0),
+ Cozy(1),
+ Condensed(2),
+ Custom(3);
+
+ private final int mValue;
+ GridSize(int value) {
+ mValue = value;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+
+ public static GridSize getModeForValue(int value) {
+ switch (value) {
+ case 1:
+ return Cozy;
+ case 2:
+ return Condensed;
+ case 3:
+ return Custom;
+ default :
+ return Comfortable;
+ }
+ }
+ }
+
+ public final static int GRID_SIZE_MAX = 3;
+ public final static int GRID_SIZE_MIN = 2;
+
// This is a static that we use for the default icon size on a 4/5-inch phone
private static float DEFAULT_ICON_SIZE_DP = 60;
@@ -56,6 +88,8 @@ public class InvariantDeviceProfile {
*/
public int numRows;
public int numColumns;
+ public int numRowsBase;
+ public int numColumnsBase;
/**
* The minimum number of predicted apps in all apps.
@@ -148,6 +182,29 @@ public class InvariantDeviceProfile {
numFolderColumns = closestProfile.numFolderColumns;
minAllAppsPredictionColumns = closestProfile.minAllAppsPredictionColumns;
+ numRowsBase = numRows;
+ int gridResize = SettingsProvider.getIntCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0);
+ if (GridSize.getModeForValue(gridResize) != GridSize.Custom) {
+ numRows += gridResize;
+ } else {
+ int iTempNumberOfRows = SettingsProvider.getIntCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, numRows);
+ if (iTempNumberOfRows > 0) {
+ numRows = iTempNumberOfRows;
+ }
+ }
+ numColumnsBase = numColumns;
+ if (GridSize.getModeForValue(gridResize) != GridSize.Custom) {
+ numColumns += gridResize;
+ } else {
+ int iTempNumberOfColumns = SettingsProvider.getIntCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, numColumns);
+ if (iTempNumberOfColumns > 0) {
+ numColumns = iTempNumberOfColumns;
+ }
+ }
+
iconSize = interpolatedDeviceProfileOut.iconSize;
iconBitmapSize = Utilities.pxFromDp(iconSize, dm);
iconTextSize = interpolatedDeviceProfileOut.iconTextSize;
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index f7e0ea488..c7729ffe6 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -115,6 +115,12 @@ public class ItemInfo {
public CharSequence contentDescription;
/**
+ * Indicates that this item has had it's position changed
+ * because the grid size was made smaller and it could no longer fit.
+ */
+ public boolean wasMovedDueToReducedSpace = false;
+
+ /**
* The position of the item in a drag-and-drop operation.
*/
public int[] dropPos = null;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 15373c20b..8f3bbf578 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -32,7 +32,6 @@ import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
-import android.app.Dialog;
import android.app.SearchManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
@@ -258,6 +257,7 @@ public class Launcher extends Activity
private DragController mDragController;
private View mWeightWatcher;
protected HiddenFolderFragment mHiddenFolderFragment;
+ private DynamicGridSizeFragment mDynamicGridSizeFragment;
private AppWidgetManagerCompat mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost;
@@ -273,6 +273,7 @@ public class Launcher extends Activity
@Thunk Hotseat mHotseat;
private ViewGroup mOverviewPanel;
+ private View mDarkPanel;
OverviewSettingsPanel mOverviewSettingsPanel;
private View mAllAppsButton;
@@ -369,6 +370,20 @@ public class Launcher extends Activity
private BubbleTextView mWaitingForResume;
private boolean mReloadLauncher;
+ private boolean mResizeGridRequired;
+
+ public Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator arg0) {}
+ @Override
+ public void onAnimationRepeat(Animator arg0) {}
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ mDarkPanel.setVisibility(View.GONE);
+ }
+ @Override
+ public void onAnimationCancel(Animator arg0) {}
+ };
// Preferences
private boolean mHideIconLabels;
@@ -1120,6 +1135,13 @@ public class Launcher extends Activity
mLauncherCallbacks.onResume();
}
+ // Close out fragments
+ Fragment gridFragment = getFragmentManager().findFragmentByTag(
+ DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT);
+ if (gridFragment != null) {
+ mDynamicGridSizeFragment.setSize();
+ }
+
reloadLauncherIfNeeded();
//Close out Fragments
@@ -1439,6 +1461,8 @@ public class Launcher extends Activity
mOverviewSettingsPanel = new OverviewSettingsPanel(this);
mOverviewSettingsPanel.initializeAdapter();
+ mDarkPanel = mOverviewPanel.findViewById(R.id.dark_panel);
+
mWidgetsButton = findViewById(R.id.widget_button);
mWidgetsButton.setOnClickListener(new OnClickListener() {
@Override
@@ -1759,11 +1783,13 @@ public class Launcher extends Activity
}
/**
- * Sets the reload launcher flag to true, which will reload the launcher at the next appropriate
- * time.
+ * Sets the reload launcher flag to true and the resize grid flag to the parameter value,
+ * which will reload the launcher/grid size at the next appropriate time.
+ * @param shouldResizeGrid Indicates whether the grid needs to be resized.
*/
- public void setReloadLauncher() {
+ public void setReloadLauncher(boolean shouldResizeGrid) {
mReloadLauncher = true;
+ mResizeGridRequired = shouldResizeGrid;
}
/**
@@ -1774,6 +1800,7 @@ public class Launcher extends Activity
if (mReloadLauncher) {
reloadLauncher(mWorkspace.getCurrentPage());
mReloadLauncher = false;
+ mResizeGridRequired = false;
return true;
}
@@ -1797,12 +1824,76 @@ public class Launcher extends Activity
// Reload
mModel.resetLoadedState(true, true);
- mModel.startLoader(page, LauncherModel.LOADER_FLAG_NONE);
+ int flag = mResizeGridRequired ? LauncherModel.LOADER_FLAG_RESIZE_GRID :
+ LauncherModel.LOADER_FLAG_NONE;
+ mModel.startLoader(page, flag);
mWorkspace.updateCustomContentVisibility();
mAppsView.reset();
}
+ /**
+ * Replaces currently added fragments in the launcher layout with a
+ * {@link DynamicGridSizeFragment}.
+ */
+ public void onClickDynamicGridSizeButton() {
+ FragmentManager fragmentManager = getFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+ mDynamicGridSizeFragment = new DynamicGridSizeFragment();
+ fragmentTransaction.replace(R.id.launcher, mDynamicGridSizeFragment,
+ DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT);
+ fragmentTransaction.commit();
+ }
+
+ /**
+ * If the new grid size is different from the current grid size, the launcher will be reloaded
+ * and the overview settings panel updated with the new grid size value.
+ * @param size The new grid size to set the workspace to.
+ */
+ public void setDynamicGridSize(InvariantDeviceProfile.GridSize size) {
+ int gridSize = SettingsProvider.getIntCustomDefault(this,
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0);
+ boolean customValuesChanged = false;
+ if (gridSize == size.getValue() && size == InvariantDeviceProfile.GridSize.Custom) {
+ int tempRows = SettingsProvider.getIntCustomDefault(this,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, mDeviceProfile.inv.numRows);
+ int tempColumns = SettingsProvider.getIntCustomDefault(this,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, mDeviceProfile.inv.numColumns);
+ if (tempColumns != mDeviceProfile.inv.numColumns ||
+ tempRows != mDeviceProfile.inv.numRows) {
+ customValuesChanged = true;
+ }
+ }
+
+ if (gridSize != size.getValue() || customValuesChanged) {
+ SettingsProvider.putInt(this,
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, size.getValue());
+
+ setReloadLauncher(true);
+ }
+
+ mOverviewSettingsPanel.notifyDataSetInvalidated();
+
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ Configuration config = getResources().getConfiguration();
+ if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ fragmentTransaction
+ .setCustomAnimations(0, R.anim.exit_out_left);
+ } else {
+ fragmentTransaction
+ .setCustomAnimations(0, R.anim.exit_out_right);
+ }
+ fragmentTransaction
+ .remove(mDynamicGridSizeFragment).commit();
+
+ mDarkPanel.setVisibility(View.VISIBLE);
+ ObjectAnimator anim = ObjectAnimator.ofFloat(
+ mDarkPanel, "alpha", 0.3f, 0.0f);
+ anim.start();
+ anim.addListener(mAnimatorListener);
+ }
+
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -2000,6 +2091,10 @@ public class Launcher extends Activity
return mOverviewPanel;
}
+ public View getDarkPanel() {
+ return mDarkPanel;
+ }
+
public SearchDropTargetBar getSearchDropTargetBar() {
return mSearchDropTargetBar;
}
@@ -2627,7 +2722,14 @@ public class Launcher extends Activity
} else if (isWidgetsViewVisible()) {
showOverviewMode(true);
} else if (mWorkspace.isInOverviewMode()) {
- showWorkspace(true);
+ Fragment gridFragment = getFragmentManager().findFragmentByTag(
+ DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT);
+ if (gridFragment != null) {
+ mDynamicGridSizeFragment.setSize();
+ }
+ else {
+ showWorkspace(true);
+ }
} else if (mWorkspace.getOpenFolder() != null) {
Folder openFolder = mWorkspace.getOpenFolder();
if (openFolder.isEditingName()) {
@@ -3516,6 +3618,8 @@ public class Launcher extends Activity
}
void showWorkspace(int snapToPage, boolean animated, Runnable onCompleteRunnable) {
+ reloadLauncherIfNeeded();
+
boolean changed = mState != State.WORKSPACE ||
mWorkspace.getState() != Workspace.State.NORMAL;
if (changed) {
@@ -3544,6 +3648,8 @@ public class Launcher extends Activity
}
void showOverviewMode(boolean animated) {
+ reloadLauncherIfNeeded();
+
mWorkspace.setVisibility(View.VISIBLE);
mStateTransitionAnimation.startAnimationToWorkspace(mState, mWorkspace.getState(),
Workspace.State.OVERVIEW,
@@ -4293,6 +4399,10 @@ public class Launcher extends Activity
if (mLauncherCallbacks != null) {
mLauncherCallbacks.finishBindingItems(false);
}
+
+ if (mWorkspace.isInOverviewMode()) {
+ reloadLauncherIfNeeded();
+ }
}
private void sendLoadingCompleteBroadcastIfNecessary() {
@@ -4978,14 +5088,6 @@ public class Launcher extends Activity
AnimationDrawable frameAnimation = (AnimationDrawable) mAnimatedArrow.getBackground();
frameAnimation.start();
-
- /*if (mLauncher.updateGridIfNeeded()) {
- Workspace workspace = mLauncher.getWorkspace();
- if (workspace.isInOverviewMode()) {
- workspace.setChildrenOutlineAlpha(1.0f);
- mLauncher.mSearchDropTargetBar.hideSearchBar(false);
- }
- }*/
}
@Override
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index c3ad6a8a1..4f2491f8d 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1112,7 +1112,7 @@ public class LauncherModel extends BroadcastReceiver
/**
* Removes the specified items from the database
* @param context
- * @param item
+ * @param items
*/
static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
final ContentResolver cr = context.getContentResolver();
@@ -1644,7 +1644,7 @@ public class LauncherModel extends BroadcastReceiver
// check & update map of what's occupied; used to discard overlapping/invalid items
private boolean checkItemPlacement(LongArrayMap<ItemInfo[][]> occupied, ItemInfo item,
- ArrayList<Long> workspaceScreens) {
+ ArrayList<Long> workspaceScreens, boolean shouldResizeAndUpdateDB) {
LauncherAppState app = LauncherAppState.getInstance();
InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
final int countX = profile.numColumns;
@@ -1700,26 +1700,67 @@ public class LauncherModel extends BroadcastReceiver
return true;
}
- if (!occupied.containsKey(item.screenId)) {
- ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];
- occupied.put(item.screenId, items);
+ // If the current item's position lies outside of the bounds
+ // of the current grid size, attempt to place it in the next
+ // available position.
+ if (item.cellX < 0 || item.cellY < 0 || item.cellX + item.spanX > countX
+ || item.cellY + item.spanY > countY) {
+ // If we won't be resizing the grid, then just return, this item does not fit.
+ if (!shouldResizeAndUpdateDB) {
+ Log.e(TAG, "Error loading shortcut " + item
+ + " into cell (" + containerIndex + "-" + item.screenId + ":"
+ + item.cellX + "," + item.cellY
+ + ") out of screen bounds ( " + countX + "x" + countY + ")");
+ return false;
+ }
+
+ if (item.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+ // Place the item at 0 0 of screen 1
+ // if items overlap here, they will be moved later on
+ item.cellX = 0;
+ item.cellY = 0;
+ item.screenId = 1;
+ item.wasMovedDueToReducedSpace = true;
+ item.requiresDbUpdate = true;
+ } else {
+ // see if widget can be shrunk to fit a screen, if not, just remove it
+ if (item.minSpanX > countX || item.minSpanY > countY) {
+ return false;
+ }
+ // if the widget is larger than the grid, shrink it down
+ if (item.cellX + item.spanX > countX) {
+ item.cellX = 0;
+ item.spanY = (item.spanY / 2) > 0 ? item.spanY / 2 : 1;
+ item.spanX = item.minSpanX;
+ item.requiresDbUpdate = true;
+ item.wasMovedDueToReducedSpace = true;
+ }
+ if (item.cellY + item.spanY > countY) {
+ item.cellY = 0;
+ item.spanY = countY;
+ item.requiresDbUpdate = true;
+ item.wasMovedDueToReducedSpace = true;
+ }
+ if (item.cellY + item.spanY == countY && item.cellX + item.spanX == countX) {
+ // if the widget is the size of the grid, make a screen all it's own.
+ item.screenId = sBgWorkspaceScreens.size() + 1;
+ }
+ }
+ } else {
+ item.wasMovedDueToReducedSpace = false;
+ item.requiresDbUpdate = true;
}
- final ItemInfo[][] screens = occupied.get(item.screenId);
- if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- item.cellX < 0 || item.cellY < 0 ||
- item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
- Log.e(TAG, "Error loading shortcut " + item
- + " into cell (" + containerIndex + "-" + item.screenId + ":"
- + item.cellX + "," + item.cellY
- + ") out of screen bounds ( " + countX + "x" + countY + ")");
- return false;
+ if (!occupied.containsKey(item.screenId)) {
+ ItemInfo[][] items = new ItemInfo[countX][countY];
+ occupied.put(item.screenId, items);
}
+ ItemInfo[][] screens = occupied.get(item.screenId);
// Check if any workspace icons overlap with each other
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- if (screens[x][y] != null) {
+ if (!shouldResizeAndUpdateDB && screens[x][y] != null) {
Log.e(TAG, "Error loading shortcut " + item
+ " into cell (" + containerIndex + "-" + item.screenId + ":"
+ x + "," + y
@@ -1732,6 +1773,16 @@ public class LauncherModel extends BroadcastReceiver
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
screens[x][y] = item;
+ if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+ && shouldResizeAndUpdateDB) {
+ // fill up the entire grid where the widget technically is
+ for (int spanX = x; spanX < item.spanX; spanX++) {
+ screens[spanX][y] = item;
+ for (int spanY = y; spanY < item.spanX; spanY++) {
+ screens[spanX][spanY] = item;
+ }
+ }
+ }
}
}
@@ -1765,6 +1816,8 @@ public class LauncherModel extends BroadcastReceiver
int countX = profile.numColumns;
int countY = profile.numRows;
+ boolean shouldResize = ((mFlags & LOADER_FLAG_RESIZE_GRID) != 0);
+
if (MigrateFromRestoreTask.ENABLED && MigrateFromRestoreTask.shouldRunTask(mContext)) {
long migrationStartTime = System.currentTimeMillis();
Log.v(TAG, "Starting workspace migration after restore");
@@ -2076,7 +2129,8 @@ public class LauncherModel extends BroadcastReceiver
}
// check & update map of what's occupied
- if (!checkItemPlacement(occupied, info, sBgWorkspaceScreens)) {
+ if (!checkItemPlacement(occupied, info, sBgWorkspaceScreens,
+ shouldResize)) {
itemsToRemove.add(id);
break;
}
@@ -2127,7 +2181,8 @@ public class LauncherModel extends BroadcastReceiver
folderInfo.options = c.getInt(optionsIndex);
// check & update map of what's occupied
- if (!checkItemPlacement(occupied, folderInfo, sBgWorkspaceScreens)) {
+ if (!checkItemPlacement(occupied, folderInfo, sBgWorkspaceScreens,
+ shouldResize)) {
itemsToRemove.add(id);
break;
}
@@ -2254,7 +2309,8 @@ public class LauncherModel extends BroadcastReceiver
appWidgetInfo.container = container;
// check & update map of what's occupied
- if (!checkItemPlacement(occupied, appWidgetInfo, sBgWorkspaceScreens)) {
+ if (!checkItemPlacement(occupied, appWidgetInfo,
+ sBgWorkspaceScreens, shouldResize)) {
itemsToRemove.add(id);
break;
}
@@ -2359,6 +2415,17 @@ public class LauncherModel extends BroadcastReceiver
updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
}
+ // If any items have been shifted and require a DB update, update them in the DB.
+ if (shouldResize) {
+ for (ItemInfo info : sBgWorkspaceItems) {
+ if (info != null && info.requiresDbUpdate) {
+ info.requiresDbUpdate = false;
+ LauncherModel.modifyItemInDatabase(mContext, info, info.container,
+ info.screenId, info.cellX, info.cellY, info.spanX, info.spanY);
+ }
+ }
+ }
+
if (DEBUG_LOADERS) {
Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
Log.d(TAG, "workspace layout: ");
diff --git a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java
index 1dcc91db6..533e64d20 100644
--- a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java
+++ b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java
@@ -16,6 +16,8 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.OverviewSettingsPanel;
import com.android.launcher3.R;
@@ -88,7 +90,6 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
Resources res = mLauncher.getResources();
-
boolean current;
String state;
@@ -119,9 +120,9 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
: res.getString(R.string.setting_state_off);
((TextView) v.findViewById(R.id.item_state)).setText(state);
break;
- /*case 3:
+ case 3:
updateDynamicGridSizeSettingsItem(v);
- break;*/
+ break;
default:
((TextView) v.findViewById(R.id.item_state)).setText("");
}
@@ -173,8 +174,8 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
return mPinnedHeaderCount;
}
- /*public void updateDynamicGridSizeSettingsItem(View v) {
- DeviceProfile.GridSize gridSize = DeviceProfile.GridSize.getModeForValue(
+ public void updateDynamicGridSizeSettingsItem(View v) {
+ InvariantDeviceProfile.GridSize gridSize = InvariantDeviceProfile.GridSize.getModeForValue(
SettingsProvider.getIntCustomDefault(mLauncher,
SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0));
String state = "";
@@ -198,7 +199,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
break;
}
((TextView) v.findViewById(R.id.item_state)).setText(state);
- }*/
+ }
OnClickListener mSettingsItemListener = new OnClickListener() {
@@ -212,23 +213,23 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
switch (position) {
case 0:
updateSearchBarVisibility(v);
- mLauncher.setReloadLauncher();
+ mLauncher.setReloadLauncher(false);
break;
case 1:
onIconLabelsBooleanChanged(v,
SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS,
R.bool.preferences_interface_homescreen_hide_icon_labels_default);
- mLauncher.setReloadLauncher();
+ mLauncher.setReloadLauncher(false);
break;
case 2:
onSettingsBooleanChanged(v,
SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL,
R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default);
- mLauncher.setReloadLauncher();
+ mLauncher.setReloadLauncher(false);
break;
- /*case 3:
+ case 3:
mLauncher.onClickDynamicGridSizeButton();
- break;*/
+ break;
}
break;
case OverviewSettingsPanel.DRAWER_SETTINGS_POSITION:
@@ -237,7 +238,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
onIconLabelsBooleanChanged(v,
SettingsProvider.SETTINGS_UI_DRAWER_HIDE_ICON_LABELS,
R.bool.preferences_interface_drawer_hide_icon_labels_default);
- mLauncher.setReloadLauncher();
+ mLauncher.setReloadLauncher(false);
break;
}
break;
@@ -247,7 +248,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
onSettingsBooleanChanged(v,
SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE,
R.bool.preferences_interface_general_icons_large_default);
- mLauncher.setReloadLauncher();
+ mLauncher.setReloadLauncher(false);
break;
/*case 1:
Intent intent = new Intent();