From d0d43010c7a091b6ade407d30e490527a8d16120 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Sun, 26 Sep 2010 17:26:45 -0700 Subject: Adding tap-to-add behaviour to the customization drawer. Change-Id: I5a0863a8df2a0b4855112eb29b40b6e7dd550db9 --- .../all_apps_paged_view_application.xml | 2 +- res/layout-xlarge/customize_paged_view_item.xml | 12 +- .../customize_paged_view_wallpaper_placeholder.xml | 6 +- res/layout-xlarge/customize_paged_view_widget.xml | 18 ++- res/values/attrs.xml | 9 ++ src/com/android/launcher2/CustomizePagedView.java | 148 +++++++++++++++---- .../launcher2/HolographicOutlineHelper.java | 2 - src/com/android/launcher2/PagedView.java | 4 +- src/com/android/launcher2/PagedViewWidgetIcon.java | 156 +++++++++++++++++++++ 9 files changed, 314 insertions(+), 43 deletions(-) create mode 100644 src/com/android/launcher2/PagedViewWidgetIcon.java diff --git a/res/layout-xlarge/all_apps_paged_view_application.xml b/res/layout-xlarge/all_apps_paged_view_application.xml index bee13d694..8e53e0656 100644 --- a/res/layout-xlarge/all_apps_paged_view_application.xml +++ b/res/layout-xlarge/all_apps_paged_view_application.xml @@ -23,7 +23,7 @@ launcher:checkedBlurColor="#FFBBE83C" launcher:checkedOutlineColor="#FF8CD2FF" - android:id="@+id/name" + android:id="@+id/application_icon" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" diff --git a/res/layout-xlarge/customize_paged_view_item.xml b/res/layout-xlarge/customize_paged_view_item.xml index 55779e50f..e42734506 100644 --- a/res/layout-xlarge/customize_paged_view_item.xml +++ b/res/layout-xlarge/customize_paged_view_item.xml @@ -14,8 +14,16 @@ limitations under the License. --> - - - + android:orientation="vertical" + + launcher:checkedBlurColor="#FFDAFF71" + launcher:checkedOutlineColor="#FFCFFF9C"> - + diff --git a/res/values/attrs.xml b/res/values/attrs.xml index bb1b85f3b..3e2a8e9d7 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -68,6 +68,15 @@ + + + + + + + + diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java index 79b3e6f21..f6cff05ed 100644 --- a/src/com/android/launcher2/CustomizePagedView.java +++ b/src/com/android/launcher2/CustomizePagedView.java @@ -36,10 +36,15 @@ import android.graphics.drawable.Drawable; import android.provider.LiveFolders; import android.util.AttributeSet; import android.util.Log; +import android.view.ActionMode; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; +import android.widget.Checkable; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -51,7 +56,7 @@ import java.util.List; public class CustomizePagedView extends PagedView implements View.OnLongClickListener, View.OnClickListener, - DragSource { + DragSource, ActionMode.Callback { public enum CustomizationType { WidgetCustomization, @@ -313,6 +318,9 @@ public class CustomizePagedView extends PagedView mCustomizationType = filterType; setCurrentPage(0); invalidatePageData(); + + // End the current choice mode so that we don't carry selections across tabs + endChoiceMode(); } @Override @@ -326,15 +334,43 @@ public class CustomizePagedView extends PagedView return; } - final View animView = v; + // On certain pages, we allow single tap to mark items as selected so that they can be + // dropped onto the mini workspaces + switch (mCustomizationType) { + case WidgetCustomization: + case ApplicationCustomization: + case FolderCustomization: + case ShortcutCustomization: + if (isChoiceMode(CHOICE_MODE_NONE)) { + startChoiceMode(CHOICE_MODE_SINGLE, this); + } + + if (v instanceof Checkable) { + final Checkable c = (Checkable) v; + final boolean wasChecked = c.isChecked(); + resetCheckedGrandchildren(); + c.setChecked(!wasChecked); + + // End the current choice mode when we have no items selected + if (!c.isChecked()) { + endChoiceMode(); + } + } + return; + default: + break; + } + + // Otherwise, we just handle the single click here switch (mCustomizationType) { case WallpaperCustomization: // animate some feedback to the long press + final View clickView = v; animateClickFeedback(v, new Runnable() { @Override public void run() { // add the shortcut - ResolveInfo info = (ResolveInfo) animView.getTag(); + ResolveInfo info = (ResolveInfo) clickView.getTag(); Intent createWallpapersIntent = new Intent(Intent.ACTION_SET_WALLPAPER); ComponentName name = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); @@ -342,6 +378,9 @@ public class CustomizePagedView extends PagedView mLauncher.processWallpaper(createWallpapersIntent); } }); + break; + default: + break; } } @@ -351,46 +390,43 @@ public class CustomizePagedView extends PagedView return false; } - final View animView = v; - PendingAddItemInfo createItemInfo = new PendingAddItemInfo(); + // End the current choice mode before we start dragging anything + if (isChoiceMode(CHOICE_MODE_SINGLE)) { + endChoiceMode(); + } + + PendingAddItemInfo createItemInfo; switch (mCustomizationType) { case WidgetCustomization: // Get the icon as the drag representation - final LinearLayout l = (LinearLayout) animView; - final Drawable icon = ((ImageView) l.findViewById(R.id.icon)).getDrawable(); + final LinearLayout l = (LinearLayout) v; + final Drawable icon = ((ImageView) l.findViewById(R.id.widget_preview)).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(); - createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET; - createItemInfo.componentName = appWidgetInfo.provider; - mDragController.startDrag(v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY, null); + createItemInfo = (PendingAddItemInfo) v.getTag(); + mDragController.startDrag(v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY, + null); // Cleanup the icon b.recycle(); return true; case FolderCustomization: - ResolveInfo resolveInfo = (ResolveInfo) animView.getTag(); - if (resolveInfo.labelRes == R.string.group_folder) { - UserFolderInfo folderInfo = new UserFolderInfo(); - folderInfo.title = getResources().getText(R.string.folder_name); + if (v.getTag() instanceof UserFolderInfo) { + // The UserFolderInfo tag is only really used for live folders + UserFolderInfo folderInfo = (UserFolderInfo) v.getTag(); mDragController.startDrag( v, this, folderInfo, DragController.DRAG_ACTION_COPY, null); } else { - createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER; - createItemInfo.componentName = new ComponentName( - resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name); + createItemInfo = (PendingAddItemInfo) v.getTag(); mDragController.startDrag( v, this, createItemInfo, DragController.DRAG_ACTION_COPY, null); } return true; case ShortcutCustomization: - ResolveInfo info = (ResolveInfo) animView.getTag(); - createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; - createItemInfo.componentName = new ComponentName( - info.activityInfo.packageName, info.activityInfo.name); + createItemInfo = (PendingAddItemInfo) v.getTag(); mDragController.startDrag( v, this, createItemInfo, DragController.DRAG_ACTION_COPY, null); return true; @@ -550,21 +586,26 @@ public class CustomizePagedView extends PagedView layout.removeAllViews(); for (int i = 0; i < count; ++i) { AppWidgetProviderInfo info = (AppWidgetProviderInfo) list.get(i); + PendingAddItemInfo createItemInfo = new PendingAddItemInfo(); + createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET; + createItemInfo.componentName = info.provider; + LinearLayout l = (LinearLayout) mInflater.inflate( R.layout.customize_paged_view_widget, layout, false); - l.setTag(info); + l.setTag(createItemInfo); + l.setOnClickListener(this); 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); + ImageView image = (ImageView) l.findViewById(R.id.widget_preview); image.setMaxWidth(mMaxWidgetWidth); image.setImageDrawable(icon); - TextView name = (TextView) l.findViewById(R.id.name); + TextView name = (TextView) l.findViewById(R.id.widget_name); name.setText(info.label); - TextView dims = (TextView) l.findViewById(R.id.dims); + TextView dims = (TextView) l.findViewById(R.id.widget_dims); dims.setText(mContext.getString(R.string.widget_dims_format, hSpan, vSpan)); layout.addView(l); @@ -594,13 +635,39 @@ public class CustomizePagedView extends PagedView layout.removeAllViews(); for (int i = startIndex; i < endIndex; ++i) { ResolveInfo info = list.get(i); + PendingAddItemInfo createItemInfo = new PendingAddItemInfo(); + PagedViewIcon icon = (PagedViewIcon) mInflater.inflate( R.layout.customize_paged_view_item, layout, false); icon.applyFromResolveInfo(info, mPackageManager, mPageViewIconCache); - if (mCustomizationType == CustomizationType.WallpaperCustomization) { + switch (mCustomizationType) { + case WallpaperCustomization: + icon.setOnClickListener(this); + break; + case FolderCustomization: + if (info.labelRes != R.string.group_folder) { + createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER; + createItemInfo.componentName = new ComponentName(info.activityInfo.packageName, + info.activityInfo.name); + icon.setTag(createItemInfo); + } else { + UserFolderInfo folderInfo = new UserFolderInfo(); + folderInfo.title = getResources().getText(R.string.folder_name); + icon.setTag(folderInfo); + } icon.setOnClickListener(this); - } else { icon.setOnLongClickListener(this); + break; + case ShortcutCustomization: + createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; + createItemInfo.componentName = new ComponentName(info.activityInfo.packageName, + info.activityInfo.name); + icon.setTag(createItemInfo); + icon.setOnClickListener(this); + icon.setOnLongClickListener(this); + break; + default: + break; } final int index = i - startIndex; @@ -641,6 +708,7 @@ public class CustomizePagedView extends PagedView PagedViewIcon icon = (PagedViewIcon) mInflater.inflate( R.layout.all_apps_paged_view_application, layout, false); icon.applyFromApplicationInfo(info, mPageViewIconCache); + icon.setOnClickListener(this); icon.setOnLongClickListener(this); final int index = i - startIndex; @@ -719,10 +787,34 @@ public class CustomizePagedView extends PagedView } } + @Override protected int getAssociatedLowerPageBound(int page) { return 0; } + @Override protected int getAssociatedUpperPageBound(int page) { return getChildCount(); } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + mode.setTitle(R.string.cab_selection_text); + return true; + } + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + endChoiceMode(); + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return false; + } + } diff --git a/src/com/android/launcher2/HolographicOutlineHelper.java b/src/com/android/launcher2/HolographicOutlineHelper.java index 597a725fa..9e61b79d0 100644 --- a/src/com/android/launcher2/HolographicOutlineHelper.java +++ b/src/com/android/launcher2/HolographicOutlineHelper.java @@ -35,8 +35,6 @@ public class HolographicOutlineHelper { private static final BlurMaskFilter mThickInnerBlurMaskFilter = new BlurMaskFilter(4.0f, BlurMaskFilter.Blur.NORMAL); - public static float DEFAULT_STROKE_WIDTH = 6.0f; - HolographicOutlineHelper() { mHolographicPaint.setFilterBitmap(true); mHolographicPaint.setAntiAlias(true); diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 9dbe61d11..17d18f8bf 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -1097,7 +1097,7 @@ public abstract class PagedView extends ViewGroup { ArrayList checked = new ArrayList(); final int childCount = getChildCount(); for (int i = 0; i < childCount; ++i) { - final PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); + final ViewGroup layout = (ViewGroup) getChildAt(i); final int grandChildCount = layout.getChildCount(); for (int j = 0; j < grandChildCount; ++j) { final View v = layout.getChildAt(j); @@ -1117,7 +1117,7 @@ public abstract class PagedView extends ViewGroup { if (mChoiceMode == CHOICE_MODE_SINGLE) { final int childCount = getChildCount(); for (int i = 0; i < childCount; ++i) { - final PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); + final ViewGroup layout = (ViewGroup) getChildAt(i); final int grandChildCount = layout.getChildCount(); for (int j = 0; j < grandChildCount; ++j) { final View v = layout.getChildAt(j); diff --git a/src/com/android/launcher2/PagedViewWidgetIcon.java b/src/com/android/launcher2/PagedViewWidgetIcon.java new file mode 100644 index 000000000..f285dab7f --- /dev/null +++ b/src/com/android/launcher2/PagedViewWidgetIcon.java @@ -0,0 +1,156 @@ +/* + * 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. + */ + +package com.android.launcher2; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.util.AttributeSet; +import android.view.View; +import android.widget.Checkable; +import android.widget.LinearLayout; + +import com.android.launcher.R; + +/** + * An widget icon for use specifically in the CustomizePagedView. In class form so that + * we can add logic for how it will look when checked/unchecked. + */ +public class PagedViewWidgetIcon extends LinearLayout implements Checkable { + private static final String TAG = "PagedViewIcon"; + + // Holographic outline + private final Paint mPaint = new Paint(); + private static HolographicOutlineHelper sHolographicOutlineHelper; + private final Paint mErasePaint = new Paint(); + private Bitmap mCheckedOutline; + private Canvas mHolographicOutlineCanvas; + private boolean mIsHolographicUpdatePass; + + private int mAlpha; + + private boolean mIsChecked; + + // Highlight colours + private int mCheckedBlurColor; + private int mCheckedOutlineColor; + + + public PagedViewWidgetIcon(Context context) { + this(context, null); + } + + public PagedViewWidgetIcon(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PagedViewWidgetIcon(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewWidgetIcon, + defStyle, 0); + mCheckedBlurColor = a.getColor(R.styleable.PagedViewWidgetIcon_checkedBlurColor, 0); + mCheckedOutlineColor = a.getColor(R.styleable.PagedViewWidgetIcon_checkedOutlineColor, 0); + mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + mErasePaint.setFilterBitmap(true); + a.recycle(); + + if (sHolographicOutlineHelper == null) { + sHolographicOutlineHelper = new HolographicOutlineHelper(); + } + + setWillNotDraw(false); + } + + public void invalidateCheckedImage() { + if (mCheckedOutline != null) { + mCheckedOutline.recycle(); + mCheckedOutline = null; + } + } + + @Override + protected void onDraw(Canvas canvas) { + // Draw the view itself + if (mIsHolographicUpdatePass) { + canvas.save(); + final float alpha = getAlpha(); + super.setAlpha(1.0f); + super.onDraw(canvas); + super.setAlpha(alpha); + canvas.restore(); + } else { + if (mAlpha > 0) { + super.onDraw(canvas); + } + } + + // Draw the holographic checked overlay if necessary + if (!mIsHolographicUpdatePass) { + if (mCheckedOutline != null) { + mPaint.setAlpha(255); + canvas.drawBitmap(mCheckedOutline, 0, 0, mPaint); + } + } + } + + @Override + public boolean isChecked() { + return mIsChecked; + } + + @Override + public void setChecked(boolean checked) { + if (mIsChecked != checked) { + mIsChecked = checked; + + if (mIsChecked) { + // set a flag to indicate that we are going to draw the view at full alpha + mIsHolographicUpdatePass = true; + final int width = getMeasuredWidth(); + final int height = getMeasuredHeight(); + mCheckedOutline = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + mHolographicOutlineCanvas = new Canvas(mCheckedOutline); + mHolographicOutlineCanvas.concat(getMatrix()); + draw(mHolographicOutlineCanvas); + sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(mCheckedOutline, + mHolographicOutlineCanvas, mCheckedBlurColor, mCheckedOutlineColor); + + // Unlike PagedViewIcon, we can't seem to properly set the clip rect for all the + // children to respect when drawing... so for now, we erase over those parts in the + // checked highlight image + mHolographicOutlineCanvas.drawRect(0, findViewById(R.id.divider).getTop(), + width, height, mErasePaint); + + mIsHolographicUpdatePass = false; + mHolographicOutlineCanvas = null; + } else { + invalidateCheckedImage(); + } + + invalidate(); + } + } + + @Override + public void toggle() { + setChecked(!mIsChecked); + } +} -- cgit v1.2.3