diff options
-rw-r--r-- | res/drawable/default_widget_preview.9.png | bin | 3976 -> 634 bytes | |||
-rw-r--r-- | res/drawable/widget_divider.png | bin | 0 -> 115 bytes | |||
-rw-r--r-- | res/layout-xlarge-land/customization_drawer.xml | 22 | ||||
-rw-r--r-- | res/layout-xlarge-port/customization_drawer.xml | 22 | ||||
-rw-r--r-- | res/layout-xlarge/customize_paged_view_widget.xml | 74 | ||||
-rw-r--r-- | res/layout-xlarge/launcher.xml | 2 | ||||
-rw-r--r-- | res/values-xlarge/dimens.xml | 2 | ||||
-rw-r--r-- | res/values/attrs.xml | 7 | ||||
-rw-r--r-- | src/com/android/launcher2/CustomizePagedView.java | 355 | ||||
-rw-r--r-- | src/com/android/launcher2/DragController.java | 31 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 3 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedView.java | 59 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedViewCellLayout.java | 59 |
13 files changed, 417 insertions, 219 deletions
diff --git a/res/drawable/default_widget_preview.9.png b/res/drawable/default_widget_preview.9.png Binary files differindex b3ddada4..5fedcc88 100644 --- a/res/drawable/default_widget_preview.9.png +++ b/res/drawable/default_widget_preview.9.png diff --git a/res/drawable/widget_divider.png b/res/drawable/widget_divider.png Binary files differnew file mode 100644 index 00000000..1b453c5f --- /dev/null +++ b/res/drawable/widget_divider.png diff --git a/res/layout-xlarge-land/customization_drawer.xml b/res/layout-xlarge-land/customization_drawer.xml new file mode 100644 index 00000000..4fcf761d --- /dev/null +++ b/res/layout-xlarge-land/customization_drawer.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> +<com.android.launcher2.CustomizePagedView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" + + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:widgetCellCountX="16" />
\ No newline at end of file diff --git a/res/layout-xlarge-port/customization_drawer.xml b/res/layout-xlarge-port/customization_drawer.xml new file mode 100644 index 00000000..6e4bc4c2 --- /dev/null +++ b/res/layout-xlarge-port/customization_drawer.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> +<com.android.launcher2.CustomizePagedView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" + + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:widgetCellCountX="12" />
\ No newline at end of file diff --git a/res/layout-xlarge/customize_paged_view_widget.xml b/res/layout-xlarge/customize_paged_view_widget.xml index da5342b0..4d70a126 100644 --- a/res/layout-xlarge/customize_paged_view_widget.xml +++ b/res/layout-xlarge/customize_paged_view_widget.xml @@ -13,20 +13,62 @@ See the License for the specific language governing permissions and limitations under the License. --> - -<TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/name" - android:layout_width="match_parent" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" android:layout_height="match_parent" - android:gravity="center_horizontal" - android:paddingTop="2dip" - - android:textColor="#FFFFFFFF" - android:textSize="14sp" - android:shadowColor="#FF000000" - android:shadowDx="0.0" - android:shadowDy="1.0" - android:shadowRadius="1.0" - - android:maxLines="2" - android:fadingEdge="horizontal" /> + android:paddingLeft="12.5dp" + android:paddingRight="12.5dp" + android:paddingTop="40dp" + android:paddingBottom="50dp" + android:gravity="top" + android:orientation="vertical"> + + <!-- The icon of the widget. --> + <ImageView + android:id="@+id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1.0" + android:scaleType="fitStart" /> + + <!-- The divider image. --> + <ImageView + android:id="@+id/divider" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="10dp" + android:paddingBottom="10dp" + android:src="@drawable/widget_divider" /> + + <!-- The name of the widget. --> + <TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="left" + + android:textColor="#FFFFFFFF" + android:textSize="14sp" + android:shadowColor="#FF000000" + android:shadowDx="0.0" + android:shadowDy="1.0" + android:shadowRadius="1.0" + + android:maxLines="2" + android:fadingEdge="horizontal" /> + + <!-- The original dimensions of the widget (can't be the same text as above due to different + style. --> + <TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/dims" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="left" + + android:textColor="#FF999999" + android:textSize="14sp" + android:shadowColor="#99000000" + android:shadowDx="0.0" + android:shadowDy="1.0" + android:shadowRadius="1.0" /> +</LinearLayout> diff --git a/res/layout-xlarge/launcher.xml b/res/layout-xlarge/launcher.xml index a3c7558e..c6acec39 100644 --- a/res/layout-xlarge/launcher.xml +++ b/res/layout-xlarge/launcher.xml @@ -128,7 +128,7 @@ <TabHost android:id="@android:id/tabhost" android:layout_width="match_parent" - android:layout_height="550dip" + android:layout_height="500dip" android:layout_gravity="bottom"> <LinearLayout android:orientation="vertical" diff --git a/res/values-xlarge/dimens.xml b/res/values-xlarge/dimens.xml index 9c658977..4662aad9 100644 --- a/res/values-xlarge/dimens.xml +++ b/res/values-xlarge/dimens.xml @@ -23,7 +23,7 @@ <dimen name="smallScreenExtraSpacing">0dip</dimen> <!-- vertical spacing between edge of screen and mini screen thumbnails --> - <dimen name="smallScreenVerticalMargin">20dip</dimen> + <dimen name="smallScreenVerticalMargin">60dip</dimen> <dimen name="toolbar_padding">10dip</dimen> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 09fb0dac..8aa6efbf 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -64,6 +64,13 @@ <attr name="cellCountY" /> </declare-styleable> + <!-- CustomizePagedView specific attributes. These attributes are used to customize + a CustomizePagedView view in XML files. --> + <declare-styleable name="CustomizePagedView"> + <!-- The number of horizontal cells for the widget tab --> + <attr name="widgetCellCountX" format="integer" /> + </declare-styleable> + <!-- DeleteZone specific attributes. These attributes are used to customize a DeleteZone view in XML files. --> <declare-styleable name="DeleteZone"> diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java index 786300bf..d3d11db9 100644 --- a/src/com/android/launcher2/CustomizePagedView.java +++ b/src/com/android/launcher2/CustomizePagedView.java @@ -28,7 +28,9 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; @@ -38,8 +40,13 @@ import android.graphics.drawable.Drawable; import android.provider.LiveFolders; import android.util.AttributeSet; import android.util.Log; +import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher.R; @@ -55,6 +62,27 @@ public class CustomizePagedView extends PagedView WallpaperCustomization } + /** + * The linear layout used strictly for the widget tab of the customization tray + */ + private class WidgetLayout extends LinearLayout { + public WidgetLayout(Context context) { + super(context); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + // We eat up the touch events here, since the PagedView (which uses the same swiping + // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when + // the user is scrolling between pages. This means that if the pages themselves don't + // handle touch events, it gets forwarded up to PagedView itself, and it's own + // onTouchEvent() handling will prevent further intercept touch events from being called + // (it's the same view in that case). This is not ideal, but to prevent more changes, + // we just always mark the touch event as handled. + return super.onTouchEvent(event) || true; + } + } + private static final String TAG = "CustomizeWorkspace"; private static final boolean DEBUG = false; @@ -64,33 +92,57 @@ public class CustomizePagedView extends PagedView private CustomizationType mCustomizationType; - private PagedViewCellLayout mTmpWidgetLayout; - private ArrayList<ArrayList<PagedViewCellLayout.LayoutParams>> mWidgetPages; + // The layout used to emulate the workspace in resolve the cell dimensions of a widget + private PagedViewCellLayout mWorkspaceWidgetLayout; + + // The mapping between the pages and the widgets that will be laid out on them + private ArrayList<ArrayList<AppWidgetProviderInfo>> mWidgetPages; + + // The max dimensions for the ImageView we use for displaying the widget + private int mMaxWidgetWidth; + + // The max number of widget cells to take a "page" of widget + private int mMaxWidgetsCellHSpan; + + // The raw sources of data for each of the different tabs of the customization page private List<AppWidgetProviderInfo> mWidgetList; private List<ResolveInfo> mFolderList; private List<ResolveInfo> mShortcutList; - private int mCellCountX; - private int mCellCountY; + private static final int sCellCountX = 8; + private static final int sCellCountY = 4; + private static final int sMinWidgetCellHSpan = 2; + private static final int sMaxWidgetCellHSpan = 4; + + // The scale factor for widget previews inside the widget drawer + private static final float sScaleFactor = 0.75f; private final Canvas mCanvas = new Canvas(); private final LayoutInflater mInflater; public CustomizePagedView(Context context) { - this(context, null); + this(context, null, 0); } public CustomizePagedView(Context context, AttributeSet attrs) { - super(context, attrs); - mCellCountX = 8; - mCellCountY = 4; + this(context, attrs, 0); + } + + public CustomizePagedView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomizePagedView, + defStyle, 0); mCustomizationType = CustomizationType.WidgetCustomization; - mWidgetPages = new ArrayList<ArrayList<PagedViewCellLayout.LayoutParams>>(); - mTmpWidgetLayout = new PagedViewCellLayout(context); + mWidgetPages = new ArrayList<ArrayList<AppWidgetProviderInfo>>(); + mWorkspaceWidgetLayout = new PagedViewCellLayout(context); mInflater = LayoutInflater.from(context); - setupPage(mTmpWidgetLayout); + mMaxWidgetsCellHSpan = a.getInt(R.styleable.CustomizePagedView_widgetCellCountX, 8); + a.recycle(); + setVisibility(View.GONE); setSoundEffectsEnabled(false); + setupWorkspaceLayout(); } public void setLauncher(Launcher launcher) { @@ -139,6 +191,7 @@ public class CustomizePagedView extends PagedView // reset the icon cache mPageViewIconCache.clear(); + // Refresh all the tabs invalidatePageData(); } @@ -166,26 +219,22 @@ public class CustomizePagedView extends PagedView final View animView = v; switch (mCustomizationType) { case WidgetCustomization: - // We assume that the view v is a TextView with a compound drawable on top, and that the - // whole text view is centered horizontally and top aligned. We get a more precise - // drag point using this information - final TextView textView = (TextView) animView; - final Drawable[] drawables = textView.getCompoundDrawables(); - final Drawable icon = drawables[1]; - int dragPointOffsetX = 0; - int dragPointOffsetY = 0; - Rect bounds = null; - if (icon != null) { - bounds = icon.getBounds(); - bounds.left = (v.getWidth() - bounds.right) / 2; - bounds.right += bounds.left; - } + // Get the icon as the drag representation + final LinearLayout l = (LinearLayout) animView; + final Drawable icon = ((ImageView) l.findViewById(R.id.icon)).getDrawable(); + Bitmap b = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + icon.draw(c); AppWidgetProviderInfo appWidgetInfo = (AppWidgetProviderInfo) v.getTag(); LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(appWidgetInfo.provider); dragInfo.minWidth = appWidgetInfo.minWidth; dragInfo.minHeight = appWidgetInfo.minHeight; - mDragController.startDrag(v, this, dragInfo, DragController.DRAG_ACTION_COPY, bounds); + mDragController.startDrag(v, b, this, dragInfo, DragController.DRAG_ACTION_COPY, null); + + // Cleanup the icon + b.recycle(); return true; case FolderCustomization: // animate some feedback to the long press @@ -236,80 +285,50 @@ public class CustomizePagedView extends PagedView return false; } + /** + * Pre-processes the layout of the different widget pages. + * @return the number of pages of widgets that we have + */ private int relayoutWidgets() { - final int widgetCount = mWidgetList.size(); - if (widgetCount == 0) return 0; + if (mWidgetList.isEmpty()) return 0; + // create a new page for the first set of widgets + ArrayList<AppWidgetProviderInfo> newPage = new ArrayList<AppWidgetProviderInfo>(); mWidgetPages.clear(); - ArrayList<PagedViewCellLayout.LayoutParams> page = - new ArrayList<PagedViewCellLayout.LayoutParams>(); - mWidgetPages.add(page); - int rowOffsetX = 0; - int rowOffsetY = 0; - int curRowHeight = 0; - // we only get the cell dims this way for the layout calculations because - // we know that we aren't going to change the dims when we construct it - // afterwards - for (int i = 0; i < widgetCount; ++i) { - AppWidgetProviderInfo info = mWidgetList.get(i); - PagedViewCellLayout.LayoutParams params; - - final int cellSpanX = mTmpWidgetLayout.estimateCellHSpan(info.minWidth); - final int cellSpanY = mTmpWidgetLayout.estimateCellVSpan(info.minHeight); + mWidgetPages.add(newPage); - if (((rowOffsetX + cellSpanX) <= mCellCountX) && - ((rowOffsetY + cellSpanY) <= mCellCountY)) { - // just add to end of current row - params = new PagedViewCellLayout.LayoutParams(rowOffsetX, rowOffsetY, - cellSpanX, cellSpanY); + // do this until we have no more widgets to lay out + final int maxNumCellsPerRow = mMaxWidgetsCellHSpan; + final int widgetCount = mWidgetList.size(); + int numCellsInRow = 0; + for (int i = 0; i < widgetCount; ++i) { + final AppWidgetProviderInfo info = mWidgetList.get(i); - rowOffsetX += cellSpanX; - curRowHeight = Math.max(curRowHeight, cellSpanY); - } else { - /* - // fix all the items in this last row to be bottom aligned - int prevRowOffsetX = rowOffsetX; - for (int j = page.size() - 1; j >= 0; --j) { - PagedViewCellLayout.LayoutParams params = page.get(j); - // skip once we get to the previous row - if (params.cellX > prevRowOffsetX) - break; - - params.cellY += curRowHeight - params.cellVSpan; - prevRowOffsetX = params.cellX; - } - */ - - // doesn't fit on current row, see if we can start a new row on - // this page - if ((rowOffsetY + curRowHeight + cellSpanY) > mCellCountY) { - // start a new page and add this item to it - page = new ArrayList<PagedViewCellLayout.LayoutParams>(); - mWidgetPages.add(page); - - params = new PagedViewCellLayout.LayoutParams(0, 0, cellSpanX, cellSpanY); - rowOffsetX = cellSpanX; - rowOffsetY = 0; - curRowHeight = cellSpanY; - } else { - // add it to the current page on this new row - params = new PagedViewCellLayout.LayoutParams(0, rowOffsetY + curRowHeight, - cellSpanX, cellSpanY); + // determine the size of the current widget + int cellSpanX = Math.max(sMinWidgetCellHSpan, Math.min(sMaxWidgetCellHSpan, + mWorkspaceWidgetLayout.estimateCellHSpan(info.minWidth))); - rowOffsetX = cellSpanX; - rowOffsetY += curRowHeight; - curRowHeight = cellSpanY; - } + // create a new page if necessary + if ((numCellsInRow + cellSpanX) > maxNumCellsPerRow) { + numCellsInRow = 0; + newPage = new ArrayList<AppWidgetProviderInfo>(); + mWidgetPages.add(newPage); } - params.setTag(info); - page.add(params); + // add the item to the current page + newPage.add(info); + numCellsInRow += cellSpanX; } + return mWidgetPages.size(); } - private Drawable getWidgetIcon(PagedViewCellLayout.LayoutParams params, - AppWidgetProviderInfo info) { + /** + * This method will extract the preview image specified by the widget developer (if it exists), + * otherwise, it will try to generate a default image preview with the widget's package icon. + * @return the drawable will be used and sized in the ImageView to represent the widget + */ + private Drawable getWidgetIcon(AppWidgetProviderInfo info) { PackageManager packageManager = mLauncher.getPackageManager(); String packageName = info.provider.getPackageName(); Drawable drawable = null; @@ -327,15 +346,11 @@ public class CustomizePagedView extends PagedView if (drawable == null) { Resources resources = mLauncher.getResources(); - // Determine the size the widget will take in the layout // Create a new bitmap to hold the widget preview - int[] dims = mTmpWidgetLayout.estimateCellDimensions(getMeasuredWidth(), - getMeasuredHeight(), params.cellHSpan, params.cellVSpan); - final int width = dims[0]; - final int height = dims[1] - 35; - // TEMP - // TEMP: HACK ABOVE TO GET TEXT TO SHOW - // TEMP + final int minDim = mWorkspaceWidgetLayout.estimateCellWidth(1); + final int maxDim = mWorkspaceWidgetLayout.estimateCellWidth(3); + int width = (int) (Math.max(minDim, Math.min(maxDim, info.minWidth)) * sScaleFactor); + int height = (int) (Math.max(minDim, Math.min(maxDim, info.minHeight)) * sScaleFactor); Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); mCanvas.setBitmap(bitmap); // For some reason, we must re-set the clip rect here, otherwise it will be wrong @@ -349,19 +364,16 @@ public class CustomizePagedView extends PagedView try { Rect tmpRect = new Rect(); Drawable icon = null; - if (info.icon != 0) { + if (info.icon > 0) { icon = packageManager.getDrawable(packageName, info.icon, null); } else { icon = resources.getDrawable(R.drawable.ic_launcher_application); } background.getPadding(tmpRect); - final int iconSize = Math.min( - Math.min(icon.getIntrinsicWidth(), width - tmpRect.left - tmpRect.right), - Math.min(icon.getIntrinsicHeight(), height - tmpRect.top - tmpRect.bottom)); - final int left = (width / 2) - (iconSize / 2); - final int top = (height / 2) - (iconSize / 2); - icon.setBounds(new Rect(left, top, left + iconSize, top + iconSize)); + final int iconSize = minDim / 2; + final int offset = iconSize / 4; + icon.setBounds(new Rect(offset, offset, offset + iconSize, offset + iconSize)); icon.draw(mCanvas); } catch (Resources.NotFoundException e) { // if we can't find the icon, then just don't draw it @@ -374,62 +386,77 @@ public class CustomizePagedView extends PagedView } private void setupPage(PagedViewCellLayout layout) { - layout.setCellCount(mCellCountX, mCellCountY); + layout.setCellCount(sCellCountX, sCellCountY); layout.setPadding(20, 10, 20, 0); } + private void setupWorkspaceLayout() { + mWorkspaceWidgetLayout.setCellCount(sCellCountX, sCellCountY); + mWorkspaceWidgetLayout.setPadding(20, 10, 20, 0); + + mMaxWidgetWidth = mWorkspaceWidgetLayout.estimateCellWidth(sMaxWidgetCellHSpan); + } + private void syncWidgetPages() { if (mWidgetList == null) return; - // calculate the layout for all the widget pages first and ensure that - // we have the right number of pages + // we need to repopulate with the LinearLayout layout for the widget pages + removeAllViews(); int numPages = relayoutWidgets(); - int curNumPages = getChildCount(); - // remove any extra pages after the "last" page - int extraPageDiff = curNumPages - numPages; - for (int i = 0; i < extraPageDiff; ++i) { - removeViewAt(numPages); - } - // add any necessary pages - for (int i = curNumPages; i < numPages; ++i) { - PagedViewCellLayout layout = new PagedViewCellLayout(getContext()); - setupPage(layout); - addView(layout); + for (int i = 0; i < numPages; ++i) { + LinearLayout layout = new WidgetLayout(getContext()); + layout.setGravity(Gravity.CENTER_HORIZONTAL); + + // Temporary change to prevent the last page from being too small (and items bleeding + // onto it). We can remove this once we properly fix the fading algorithm + if (i < numPages - 1) { + addView(layout, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.MATCH_PARENT)); + } else { + addView(layout, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT)); + } } } private void syncWidgetPageItems(int page) { // ensure that we have the right number of items on the pages - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page); - final ArrayList<PagedViewCellLayout.LayoutParams> list = mWidgetPages.get(page); + LinearLayout layout = (LinearLayout) getChildAt(page); + final ArrayList<AppWidgetProviderInfo> list = mWidgetPages.get(page); final int count = list.size(); layout.removeAllViews(); for (int i = 0; i < count; ++i) { - PagedViewCellLayout.LayoutParams params = list.get(i); - AppWidgetProviderInfo info = (AppWidgetProviderInfo) params.getTag(); - final Drawable icon = getWidgetIcon(params, info); - TextView text = (TextView) mInflater.inflate(R.layout.customize_paged_view_widget, - layout, false); - text.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null); - text.setText(info.label); - text.setTag(info); - text.setOnLongClickListener(this); - - layout.addViewToCellLayout(text, -1, mWidgetList.indexOf(info), params); + AppWidgetProviderInfo info = (AppWidgetProviderInfo) list.get(i); + LinearLayout l = (LinearLayout) mInflater.inflate( + R.layout.customize_paged_view_widget, layout, false); + l.setTag(info); + l.setOnLongClickListener(this); + + final Drawable icon = getWidgetIcon(info); + final int hSpan = mWorkspaceWidgetLayout.estimateCellHSpan(info.minWidth); + final int vSpan = mWorkspaceWidgetLayout.estimateCellHSpan(info.minHeight); + + ImageView image = (ImageView) l.findViewById(R.id.icon); + image.setMaxWidth(mMaxWidgetWidth); + image.setImageDrawable(icon); + TextView name = (TextView) l.findViewById(R.id.name); + name.setText(info.label); + TextView dims = (TextView) l.findViewById(R.id.dims); + dims.setText("" + hSpan + " x " + vSpan); + + layout.addView(l); } } private void syncListPages(List<ResolveInfo> list) { + // we need to repopulate with PagedViewCellLayouts + removeAllViews(); + // ensure that we have the right number of pages - int numPages = (int) Math.ceil((float) list.size() / (mCellCountX * mCellCountY)); - int curNumPages = getChildCount(); - // remove any extra pages after the "last" page - int extraPageDiff = curNumPages - numPages; - for (int i = 0; i < extraPageDiff; ++i) { - removeViewAt(numPages); - } - // add any necessary pages - for (int i = curNumPages; i < numPages; ++i) { + int numPages = (int) Math.ceil((float) list.size() / (sCellCountX * sCellCountY)); + for (int i = 0; i < numPages; ++i) { PagedViewCellLayout layout = new PagedViewCellLayout(getContext()); setupPage(layout); addView(layout); @@ -438,7 +465,7 @@ public class CustomizePagedView extends PagedView private void syncListPageItems(int page, List<ResolveInfo> list) { // ensure that we have the right number of items on the pages - int numCells = mCellCountX * mCellCountY; + int numCells = sCellCountX * sCellCountY; int startIndex = page * numCells; int endIndex = Math.min(startIndex + numCells, list.size()); PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page); @@ -452,24 +479,22 @@ public class CustomizePagedView extends PagedView icon.setOnLongClickListener(this); final int index = i - startIndex; - final int x = index % mCellCountX; - final int y = index / mCellCountX; + final int x = index % sCellCountX; + final int y = index / sCellCountX; + setupPage(layout); layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1)); } } private void syncWallpaperPages() { // NOT CURRENTLY IMPLEMENTED - // ensure that we have the right number of pages - int numPages = 1; - int curNumPages = getChildCount(); - // remove any extra pages after the "last" page - int extraPageDiff = curNumPages - numPages; - for (int i = 0; i < extraPageDiff; ++i) { - removeViewAt(numPages); - } + + // we need to repopulate with PagedViewCellLayouts + removeAllViews(); + // add any necessary pages - for (int i = curNumPages; i < numPages; ++i) { + int numPages = 1; + for (int i = 0; i < numPages; ++i) { PagedViewCellLayout layout = new PagedViewCellLayout(getContext()); setupPage(layout); addView(layout); @@ -485,23 +510,28 @@ public class CustomizePagedView extends PagedView // NOTE: this is just place holder text until MikeJurka implements wallpaper picker text.setText("Wallpaper customization coming soon!"); + setupPage(layout); layout.addViewToCellLayout(text, -1, 0, new PagedViewCellLayout.LayoutParams(0, 0, 3, 1)); } @Override public void syncPages() { + boolean centerPagedViewCellLayouts = false; switch (mCustomizationType) { case WidgetCustomization: syncWidgetPages(); break; case FolderCustomization: syncListPages(mFolderList); + centerPagedViewCellLayouts = true; break; case ShortcutCustomization: syncListPages(mShortcutList); + centerPagedViewCellLayouts = true; break; case WallpaperCustomization: syncWallpaperPages(); + centerPagedViewCellLayouts = true; break; default: removeAllViews(); @@ -511,13 +541,15 @@ public class CustomizePagedView extends PagedView // only try and center the page if there is one page final int childCount = getChildCount(); - if (childCount == 1) { - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(0); - layout.enableCenteredContent(true); - } else { - for (int i = 0; i < childCount; ++i) { - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); - layout.enableCenteredContent(false); + if (centerPagedViewCellLayouts) { + if (childCount == 1) { + PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(0); + layout.enableCenteredContent(true); + } else { + for (int i = 0; i < childCount; ++i) { + PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); + layout.enableCenteredContent(false); + } } } @@ -542,4 +574,11 @@ public class CustomizePagedView extends PagedView break; } } + + protected int getAssociatedLowerPageBound(int page) { + return 0; + } + protected int getAssociatedUpperPageBound(int page) { + return getChildCount(); + } } diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java index e18470ab..7fc905bb 100644 --- a/src/com/android/launcher2/DragController.java +++ b/src/com/android/launcher2/DragController.java @@ -134,7 +134,7 @@ public class DragController { void onDragStart(DragSource source, Object info, int dragAction); /** - * The drag has eneded + * The drag has ended */ void onDragEnd(); } @@ -202,6 +202,35 @@ public class DragController { /** * Starts a drag. * + * @param v The view that is being dragged + * @param bmp The bitmap that represents the view being dragged + * @param source An object representing where the drag originated + * @param dragInfo The data associated with the object that is being dragged + * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or + * {@link #DRAG_ACTION_COPY} + * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. + * Makes dragging feel more precise, e.g. you can clip out a transparent border + */ + public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction, + Rect dragRegion) { + mOriginator = v; + + int[] loc = mCoordinatesTemp; + v.getLocationOnScreen(loc); + int screenX = loc[0]; + int screenY = loc[1]; + + startDrag(bmp, screenX, screenY, 0, 0, bmp.getWidth(), bmp.getHeight(), + source, dragInfo, dragAction, dragRegion); + + if (dragAction == DRAG_ACTION_MOVE) { + v.setVisibility(View.GONE); + } + } + + /** + * Starts a drag. + * * @param b The bitmap to display as the drag image. It will be re-scaled to the * enlarged size. * @param screenX The x position on screen of the left-top of the bitmap. diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index c5450f34..8eece960 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -281,7 +281,8 @@ public final class Launcher extends Activity mHomeCustomizationDrawer.setup(); // share the same customization workspace across all the tabs - mCustomizePagedView = new CustomizePagedView(this); + mCustomizePagedView = (CustomizePagedView) mInflater.inflate( + R.layout.customization_drawer, mHomeCustomizationDrawer, false); TabContentFactory contentFactory = new TabContentFactory() { public View createTabContent(String tag) { return mCustomizePagedView; diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 1e0dad4a..0772c0a6 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -16,7 +16,8 @@ package com.android.launcher2; -import com.android.launcher.R; +import java.util.ArrayList; +import java.util.HashMap; import android.content.Context; import android.graphics.Bitmap; @@ -25,6 +26,7 @@ import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; +import android.util.Log; import android.view.ActionMode; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -33,13 +35,13 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.Animation; -import android.view.animation.AnimationUtils; import android.view.animation.Animation.AnimationListener; +import android.view.animation.AnimationUtils; import android.widget.Checkable; +import android.widget.LinearLayout; import android.widget.Scroller; -import java.util.ArrayList; -import java.util.HashMap; +import com.android.launcher.R; /** * An abstraction of the original Workspace which supports browsing through a @@ -345,7 +347,7 @@ public abstract class PagedView extends ViewGroup { final int childCount = getChildCount(); int childLeft = 0; if (childCount > 0) { - childLeft = (getMeasuredWidth() - getChildAt(0).getMeasuredWidth()) / 2; + childLeft = getRelativeChildOffset(0); } for (int i = 0; i < childCount; i++) { @@ -360,11 +362,12 @@ public abstract class PagedView extends ViewGroup { } } - @Override - protected void dispatchDraw(Canvas canvas) { + protected void updateAdjacentPagesAlpha() { if (mFadeInAdjacentScreens) { if (mDirtyPageAlpha || (mTouchState == TOUCH_STATE_SCROLLING) || !mScroller.isFinished()) { - int screenCenter = mScrollX + (getMeasuredWidth() / 2); + int halfScreenSize = getMeasuredWidth() / 2; + int screenCenter = mScrollX + halfScreenSize; + final int childCount = getChildCount(); for (int i = 0; i < childCount; ++i) { View layout = (View) getChildAt(i); @@ -389,9 +392,13 @@ public abstract class PagedView extends ViewGroup { mDirtyPageAlpha = false; } } + } - // Find out which screens are visible; as an optimization we only call draw on them + @Override + protected void dispatchDraw(Canvas canvas) { + updateAdjacentPagesAlpha(); + // Find out which screens are visible; as an optimization we only call draw on them // As an optimization, this code assumes that all pages have the same width as the 0th // page. final int pageCount = getChildCount(); @@ -591,11 +598,11 @@ public abstract class PagedView extends ViewGroup { if ((mTouchState != TOUCH_STATE_PREV_PAGE) && (mTouchState != TOUCH_STATE_NEXT_PAGE)) { if (getChildCount() > 0) { - int relativeChildLeft = getChildOffset(0); - int relativeChildRight = relativeChildLeft + getChildAt(0).getMeasuredWidth(); - if (x < relativeChildLeft) { + int width = getMeasuredWidth(); + int offset = getRelativeChildOffset(mCurrentPage); + if (x < offset) { mTouchState = TOUCH_STATE_PREV_PAGE; - } else if (x > relativeChildRight) { + } else if (x > (width - offset)) { mTouchState = TOUCH_STATE_NEXT_PAGE; } } @@ -842,6 +849,19 @@ public abstract class PagedView extends ViewGroup { } } + protected int getChildIndexForRelativeOffset(int relativeOffset) { + final int childCount = getChildCount(); + int left = getRelativeChildOffset(0); + for (int i = 0; i < childCount; ++i) { + final int right = (left + getChildAt(i).getMeasuredWidth()); + if (left <= relativeOffset && relativeOffset <= right) { + return i; + } + left = right; + } + return -1; + } + protected int getRelativeChildOffset(int index) { return (getMeasuredWidth() - getChildAt(index).getMeasuredWidth()) / 2; } @@ -889,7 +909,6 @@ public abstract class PagedView extends ViewGroup { protected void snapToPage(int whichPage, int duration) { whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1)); - int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage); final int sX = getScrollX(); final int delta = newX - sX; @@ -1015,8 +1034,8 @@ public abstract class PagedView extends ViewGroup { if (mContentIsRefreshable) { final int count = getChildCount(); if (page < count) { - int lowerPageBound = Math.max(0, page - 1); - int upperPageBound = Math.min(page + 1, count - 1); + int lowerPageBound = getAssociatedLowerPageBound(page); + int upperPageBound = getAssociatedUpperPageBound(page); for (int i = 0; i < count; ++i) { final ViewGroup layout = (ViewGroup) getChildAt(i); final int childCount = layout.getChildCount(); @@ -1036,6 +1055,14 @@ public abstract class PagedView extends ViewGroup { } } + protected int getAssociatedLowerPageBound(int page) { + return Math.max(0, page - 1); + } + protected int getAssociatedUpperPageBound(int page) { + final int count = getChildCount(); + return Math.min(page + 1, count - 1); + } + protected void startChoiceMode(int mode, ActionMode.Callback callback) { if (isChoiceMode(CHOICE_MODE_NONE)) { mChoiceMode = mode; diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java index 219a3620..b247a065 100644 --- a/src/com/android/launcher2/PagedViewCellLayout.java +++ b/src/com/android/launcher2/PagedViewCellLayout.java @@ -252,6 +252,16 @@ public class PagedViewCellLayout extends ViewGroup { requestLayout(); } + public void setCellDimensions(int width, int height) { + mCellWidth = width; + mCellHeight = height; + requestLayout(); + } + + public int getDefaultCellDimensions() { + return sDefaultCellDimensions; + } + private void setChildrenAlpha(float alpha) { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -281,37 +291,36 @@ public class PagedViewCellLayout extends ViewGroup { lp.isDragging = true; } + /** + * Estimates the number of cells that the specified width would take up. + */ public int estimateCellHSpan(int width) { + // TODO: we need to take widthGap into effect return (width + mCellWidth) / mCellWidth; } + + /** + * Estimates the number of cells that the specified height would take up. + */ public int estimateCellVSpan(int height) { + // TODO: we need to take heightGap into effect return (height + mCellHeight) / mCellHeight; } - public int[] estimateCellDimensions(int approxWidth, int approxHeight, - int cellHSpan, int cellVSpan) { - // NOTE: we are disabling this until we find a good way to approximate this without fully - // measuring - /* - // we may want to use this before any measuring/layout happens, so we pass in an approximate - // size for the layout - int numWidthGaps = mCellCountX - 1; - int numHeightGaps = mCellCountY - 1; - int hSpaceLeft = approxWidth - mPaddingLeft - - mPaddingRight - (mCellWidth * mCellCountX); - int vSpaceLeft = approxHeight - mPaddingTop - - mPaddingBottom - (mCellHeight * mCellCountY); - int widthGap = hSpaceLeft / numWidthGaps; - int heightGap = vSpaceLeft / numHeightGaps; - int minGap = Math.min(widthGap, heightGap); - return new int[] { - (cellHSpan * mCellWidth) + ((cellHSpan - 1) * minGap), - (cellVSpan * mCellHeight) + ((cellVSpan - 1) * minGap) - }; - */ - return new int[] { - (cellHSpan * mCellWidth), - (cellVSpan * mCellHeight) - }; + + /** + * Estimates the width that the number of vSpan cells will take up. + */ + public int estimateCellWidth(int hSpan) { + // TODO: we need to take widthGap into effect + return hSpan * mCellWidth; + } + + /** + * Estimates the height that the number of vSpan cells will take up. + */ + public int estimateCellHeight(int vSpan) { + // TODO: we need to take heightGap into effect + return vSpan * mCellHeight; } @Override |