From b99ff3e83270e113f6182e337c4f7b0223bad92b Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Thu, 23 Apr 2015 15:17:50 -0700 Subject: Add drop animation / Toast to widgettray - show instruction toast on clicking the widget - Add animation when widget drops on the workspace. Added WidgetHostViewLoader to handle short press and assign widget host view to enable animation b/19897708 Change-Id: Iec36d72cb21bf09343d0beeb31a09bf8b0cb5e0d --- .../android/launcher3/AppWidgetResizeFrame.java | 2 +- src/com/android/launcher3/Launcher.java | 3 +- src/com/android/launcher3/widget/WidgetCell.java | 212 ++++++--------------- .../launcher3/widget/WidgetHostViewLoader.java | 197 +++++++++++++++++++ .../launcher3/widget/WidgetsContainerView.java | 67 ++++--- .../launcher3/widget/WidgetsListAdapter.java | 5 - 6 files changed, 294 insertions(+), 192 deletions(-) create mode 100644 src/com/android/launcher3/widget/WidgetHostViewLoader.java (limited to 'src/com/android/launcher3') diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index 240250750..3c698c014 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -349,7 +349,7 @@ public class AppWidgetResizeFrame extends FrameLayout { mTmpRect.right, mTmpRect.bottom); } - static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) { + public static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) { if (rect == null) { rect = new Rect(); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7364a9f20..c708b3c8e 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -104,6 +104,7 @@ import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddWidgetInfo; +import com.android.launcher3.widget.WidgetHostViewLoader; import com.android.launcher3.widget.WidgetsContainerView; import java.io.DataInputStream; @@ -3953,7 +3954,7 @@ public class Launcher extends Activity pendingInfo.minSpanX = item.minSpanX; pendingInfo.minSpanY = item.minSpanY; Bundle options = null; - // AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo); + WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo); int newWidgetId = mAppWidgetHost.allocateAppWidgetId(); boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index 1ae75c3cc..0bc7333ec 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -24,8 +24,6 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; -import android.util.TypedValue; -import android.view.MotionEvent; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.widget.ImageView; @@ -43,7 +41,7 @@ import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest; import com.android.launcher3.compat.AppWidgetManagerCompat; /** - * The linear layout used strictly for the widget tray. + * Represents the individual cell of the widget inside the widget tray. */ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { @@ -53,14 +51,12 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { private static final int FADE_IN_DURATION_MS = 70; private int mPresetPreviewSize; - private static WidgetCell sShortpressTarget = null; - + private ImageView mWidgetImage; + private TextView mWidgetName; + private TextView mWidgetDims; private final Rect mOriginalImagePadding = new Rect(); private String mDimensionsFormatString; - private CheckForShortPress mPendingCheckForShortPress = null; - private ShortPressListener mShortPressListener = null; - private boolean mShortPressTriggered = false; private boolean mIsAppWidget; private Object mInfo; @@ -92,57 +88,27 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { protected void onFinishInflate() { super.onFinishInflate(); - final ImageView image = (ImageView) findViewById(R.id.widget_preview); - mOriginalImagePadding.left = image.getPaddingLeft(); - mOriginalImagePadding.top = image.getPaddingTop(); - mOriginalImagePadding.right = image.getPaddingRight(); - mOriginalImagePadding.bottom = image.getPaddingBottom(); + mWidgetImage = (ImageView) findViewById(R.id.widget_preview); + mOriginalImagePadding.left = mWidgetImage.getPaddingLeft(); + mOriginalImagePadding.top = mWidgetImage.getPaddingTop(); + mOriginalImagePadding.right = mWidgetImage.getPaddingRight(); + mOriginalImagePadding.bottom = mWidgetImage.getPaddingBottom(); // Ensure we are using the right text size - LauncherAppState app = LauncherAppState.getInstance(); - DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - TextView name = (TextView) findViewById(R.id.widget_name); - if (name != null) { - name.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); - } - TextView dims = (TextView) findViewById(R.id.widget_dims); - if (dims != null) { - dims.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); - } - } - - @Override - protected void onDetachedFromWindow() { - if (DEBUG) { - Log.d(TAG, String.format("[tag=%s] onDetachedFromWindow", getTagToString())); - } - super.onDetachedFromWindow(); - deletePreview(false); + DeviceProfile profile = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile(); + mWidgetName = ((TextView) findViewById(R.id.widget_name)); + mWidgetDims = ((TextView) findViewById(R.id.widget_dims)); } public void reset() { - ImageView image = (ImageView) findViewById(R.id.widget_preview); - final TextView name = (TextView) findViewById(R.id.widget_name); - final TextView dims = (TextView) findViewById(R.id.widget_dims); - image.setImageDrawable(null); - name.setText(null); - dims.setText(null); - } - - public void deletePreview(boolean recycleImage) { - if (recycleImage) { - final ImageView image = (ImageView) findViewById(R.id.widget_preview); - if (image != null) { - image.setImageDrawable(null); - } - } - - if (mActiveRequest != null) { - mActiveRequest.cancel(recycleImage); - mActiveRequest = null; - } + mWidgetImage.setImageDrawable(null); + mWidgetName.setText(null); + mWidgetDims.setText(null); } + /** + * Apply the widget provider info to the view. + */ public void applyFromAppWidgetProviderInfo(LauncherAppWidgetProviderInfo info, int maxWidth, WidgetPreviewLoader loader) { LauncherAppState app = LauncherAppState.getInstance(); @@ -150,37 +116,41 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { mIsAppWidget = true; mInfo = info; - final ImageView image = (ImageView) findViewById(R.id.widget_preview); if (maxWidth > -1) { - image.setMaxWidth(maxWidth); - } - final TextView name = (TextView) findViewById(R.id.widget_name); - name.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info)); - final TextView dims = (TextView) findViewById(R.id.widget_dims); - if (dims != null) { - int hSpan = Math.min(info.spanX, (int) grid.numColumns); - int vSpan = Math.min(info.spanY, (int) grid.numRows); - dims.setText(String.format(mDimensionsFormatString, hSpan, vSpan)); + mWidgetImage.setMaxWidth(maxWidth); } + // TODO(hyunyoungs): setup a cache for these labels. + mWidgetName.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info)); + int hSpan = Math.min(info.spanX, (int) grid.numColumns); + int vSpan = Math.min(info.spanY, (int) grid.numRows); + mWidgetDims.setText(String.format(mDimensionsFormatString, hSpan, vSpan)); mWidgetPreviewLoader = loader; } + /** + * Apply the resolve info to the view. + */ public void applyFromResolveInfo( PackageManager pm, ResolveInfo info, WidgetPreviewLoader loader) { mIsAppWidget = false; mInfo = info; CharSequence label = info.loadLabel(pm); - final TextView name = (TextView) findViewById(R.id.widget_name); - name.setText(label); - final TextView dims = (TextView) findViewById(R.id.widget_dims); - if (dims != null) { - dims.setText(String.format(mDimensionsFormatString, 1, 1)); - } + mWidgetName.setText(label); + mWidgetDims.setText(String.format(mDimensionsFormatString, 1, 1)); mWidgetPreviewLoader = loader; } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + deletePreview(false); + + if (DEBUG) { + Log.d(TAG, String.format("[tag=%s] onDetachedFromWindow", getTagToString())); + } + } + public int[] getPreviewSize() { - final ImageView i = (ImageView) findViewById(R.id.widget_preview); int[] maxSize = new int[2]; maxSize[0] = mPresetPreviewSize; maxSize[1] = mPresetPreviewSize; @@ -189,110 +159,28 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { public void applyPreview(Bitmap bitmap) { FastBitmapDrawable preview = new FastBitmapDrawable(bitmap); - final WidgetImageView image = - (WidgetImageView) findViewById(R.id.widget_preview); if (DEBUG) { Log.d(TAG, String.format("[tag=%s] applyPreview preview: %s", getTagToString(), preview)); } if (preview != null) { - image.mAllowRequestLayout = false; - image.setImageDrawable(preview); + mWidgetImage.setImageDrawable(preview); if (mIsAppWidget) { // center horizontally int[] imageSize = getPreviewSize(); int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2; - image.setPadding(mOriginalImagePadding.left + centerAmount, + mWidgetImage.setPadding(mOriginalImagePadding.left + centerAmount, mOriginalImagePadding.top, mOriginalImagePadding.right, mOriginalImagePadding.bottom); } - image.setAlpha(0f); - image.animate().alpha(1.0f).setDuration(FADE_IN_DURATION_MS); - image.mAllowRequestLayout = true; - image.requestLayout(); - } - } - - void setShortPressListener(ShortPressListener listener) { - mShortPressListener = listener; - } - - interface ShortPressListener { - void onShortPress(View v); - void cleanUpShortPress(View v); - } - - class CheckForShortPress implements Runnable { - public void run() { - if (sShortpressTarget != null) return; - if (mShortPressListener != null) { - mShortPressListener.onShortPress(WidgetCell.this); - sShortpressTarget = WidgetCell.this; - } - mShortPressTriggered = true; + mWidgetImage.setAlpha(0f); + mWidgetImage.animate().alpha(1.0f).setDuration(FADE_IN_DURATION_MS); + // TODO(hyunyoungs): figure out why this has to be called explicitly. + mWidgetImage.requestLayout(); } } - private void checkForShortPress() { - if (sShortpressTarget != null) return; - if (mPendingCheckForShortPress == null) { - mPendingCheckForShortPress = new CheckForShortPress(); - } - postDelayed(mPendingCheckForShortPress, 120); - } - - /** - * Remove the longpress detection timer. - */ - private void removeShortPressCallback() { - if (mPendingCheckForShortPress != null) { - removeCallbacks(mPendingCheckForShortPress); - } - } - - private void cleanUpShortPress() { - removeShortPressCallback(); - if (mShortPressTriggered) { - if (mShortPressListener != null) { - mShortPressListener.cleanUpShortPress(WidgetCell.this); - } - mShortPressTriggered = false; - } - } - - static void resetShortPressTarget() { - sShortpressTarget = null; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - - switch (event.getAction()) { - case MotionEvent.ACTION_UP: - cleanUpShortPress(); - break; - case MotionEvent.ACTION_DOWN: - checkForShortPress(); - break; - case MotionEvent.ACTION_CANCEL: - cleanUpShortPress(); - break; - case MotionEvent.ACTION_MOVE: - break; - } - - // 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 true; - } - public void ensurePreview() { if (mActiveRequest != null) { return; @@ -331,6 +219,16 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { return Math.min(size[0], info.spanX * cellWidth); } + + private void deletePreview(boolean recycleImage) { + mWidgetImage.setImageDrawable(null); + + if (mActiveRequest != null) { + mActiveRequest.cancel(recycleImage); + mActiveRequest = null; + } + } + /** * Helper method to get the string info of the tag. */ diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java new file mode 100644 index 000000000..d65455053 --- /dev/null +++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java @@ -0,0 +1,197 @@ +package com.android.launcher3.widget; + +import android.appwidget.AppWidgetHostView; +import android.appwidget.AppWidgetManager; +import android.content.Context; +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.View; + +import com.android.launcher3.AppWidgetResizeFrame; +import com.android.launcher3.DragLayer; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.compat.AppWidgetManagerCompat; + +public class WidgetHostViewLoader { + + private static final boolean DEBUG = false; + private static final String TAG = "WidgetHostViewLoader"; + + /* constants used for widget loading state. */ + private static final int WIDGET_NO_CLEANUP_REQUIRED = -1; + private static final int WIDGET_PRELOAD_PENDING = 0; + private static final int WIDGET_BOUND = 1; + private static final int WIDGET_INFLATED = 2; + + int mState = WIDGET_NO_CLEANUP_REQUIRED; + + /* Runnables to handle inflation and binding. */ + private Runnable mInflateWidgetRunnable = null; + private Runnable mBindWidgetRunnable = null; + + /* Id of the widget being handled. */ + int mWidgetLoadingId = -1; + PendingAddWidgetInfo mCreateWidgetInfo = null; + + // TODO: technically, this class should not have to know the existence of the launcher. + private Launcher mLauncher; + private Handler mHandler; + + public WidgetHostViewLoader(Launcher launcher) { + mLauncher = launcher; + mHandler = new Handler(); + } + + /** + * Start loading the widget. + */ + public void load(View v) { + if (mCreateWidgetInfo != null) { + // Just in case the cleanup process wasn't properly executed. + finish(false); + } + boolean status = false; + if (v.getTag() instanceof PendingAddWidgetInfo) { + mCreateWidgetInfo = new PendingAddWidgetInfo((PendingAddWidgetInfo) v.getTag()); + status = preloadWidget(v, mCreateWidgetInfo); + } + if (DEBUG) { + Log.d(TAG, String.format("load started on [state=%d, status=%s]", mState, status)); + } + } + + + /** + * Clean up according to what the last known state was. + * @param widgetIdUsed {@code true} if the widgetId was consumed which can happen only + * when view is fully inflated + */ + public void finish(boolean widgetIdUsed) { + if (DEBUG) { + Log.d(TAG, String.format("cancel on state [%d] widgetId=[%d]", + mState, mWidgetLoadingId)); + } + + // If the widget was not added, we may need to do further cleanup. + PendingAddWidgetInfo info = mCreateWidgetInfo; + mCreateWidgetInfo = null; + + if (mState == WIDGET_PRELOAD_PENDING) { + // We never did any preloading, so just remove pending callbacks to do so + mHandler.removeCallbacks(mBindWidgetRunnable); + mHandler.removeCallbacks(mInflateWidgetRunnable); + } else if (mState == WIDGET_BOUND) { + // Delete the widget id which was allocated + if (mWidgetLoadingId != -1 && !info.isCustomWidget()) { + mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId); + } + + // We never got around to inflating the widget, so remove the callback to do so. + mHandler.removeCallbacks(mInflateWidgetRunnable); + } else if (mState == WIDGET_INFLATED && !widgetIdUsed) { + // Delete the widget id which was allocated + if (mWidgetLoadingId != -1 && !info.isCustomWidget()) { + mLauncher.getAppWidgetHost().deleteAppWidgetId(mWidgetLoadingId); + } + + // The widget was inflated and added to the DragLayer -- remove it. + AppWidgetHostView widget = info.boundWidget; + mLauncher.getDragLayer().removeView(widget); + } + setState(WIDGET_NO_CLEANUP_REQUIRED); + mWidgetLoadingId = -1; + } + + private boolean preloadWidget(final View v, final PendingAddWidgetInfo info) { + final LauncherAppWidgetProviderInfo pInfo = info.info; + + final Bundle options = pInfo.isCustomWidget ? null : + getDefaultOptionsForWidget(mLauncher, info); + + // If there is a configuration activity, do not follow thru bound and inflate. + if (pInfo.configure != null) { + info.bindOptions = options; + return false; + } + setState(WIDGET_PRELOAD_PENDING); + mBindWidgetRunnable = new Runnable() { + @Override + public void run() { + if (pInfo.isCustomWidget) { + setState(WIDGET_BOUND); + return; + } + + mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId(); + if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed( + mWidgetLoadingId, pInfo, options)) { + setState(WIDGET_BOUND); + } + } + }; + mHandler.post(mBindWidgetRunnable); + + mInflateWidgetRunnable = new Runnable() { + @Override + public void run() { + if (mState != WIDGET_BOUND) { + return; + } + AppWidgetHostView hostView = mLauncher.getAppWidgetHost().createView( + (Context) mLauncher, mWidgetLoadingId, pInfo); + info.boundWidget = hostView; + setState(WIDGET_INFLATED); + hostView.setVisibility(View.INVISIBLE); + int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(info, false); + + // We want the first widget layout to be the correct size. This will be important + // for width size reporting to the AppWidgetManager. + DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0], + unScaledSize[1]); + lp.x = lp.y = 0; + lp.customPosition = true; + hostView.setLayoutParams(lp); + mLauncher.getDragLayer().addView(hostView); + v.setTag(info); + } + }; + mHandler.post(mInflateWidgetRunnable); + return true; + } + + public static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) { + Bundle options = null; + Rect rect = new Rect(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, rect); + Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher, + info.componentName, null); + + float density = launcher.getResources().getDisplayMetrics().density; + int xPaddingDips = (int) ((padding.left + padding.right) / density); + int yPaddingDips = (int) ((padding.top + padding.bottom) / density); + + options = new Bundle(); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, + rect.left - xPaddingDips); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, + rect.top - yPaddingDips); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, + rect.right - xPaddingDips); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, + rect.bottom - yPaddingDips); + } + return options; + } + + private void setState(int state) { + if (DEBUG) { + Log.d(TAG, String.format(" state [%d -> %d]", mState, state)); + } + mState = state; + } +} diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java index 292a5de20..27a3ea13d 100644 --- a/src/com/android/launcher3/widget/WidgetsContainerView.java +++ b/src/com/android/launcher3/widget/WidgetsContainerView.java @@ -30,6 +30,7 @@ import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.Toast; import com.android.launcher3.CellLayout; import com.android.launcher3.DeleteDropTarget; @@ -54,15 +55,17 @@ import java.util.ArrayList; /** * The widgets list view container. */ -public class WidgetsContainerView extends FrameLayout implements Insettable, View.OnTouchListener, - View.OnLongClickListener, DragSource{ +public class WidgetsContainerView extends FrameLayout implements Insettable, + View.OnLongClickListener, View.OnClickListener, DragSource{ - private static final String TAG = "WidgetContainerView"; + private static final String TAG = "WidgetsContainerView"; private static final boolean DEBUG = false; /* {@link RecyclerView} will keep following # of views in cache, before recycling. */ private static final int WIDGET_CACHE_SIZE = 2; + private static final int SPRING_MODE_DELAY_MS = 150; + /* Global instances that are used inside this container. */ private Launcher mLauncher; private DragController mDragController; @@ -75,12 +78,13 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie private RecyclerView mView; private WidgetsListAdapter mAdapter; - /* Dragging related. */ - private boolean mDraggingWidget = false; // TODO(hyunyoungs): seems not needed? check! - private Point mLastTouchDownPos = new Point(); + /* Touch handling related member variables. */ + private Toast mWidgetInstructionToast; /* Rendering related. */ private WidgetPreviewLoader mWidgetPreviewLoader; + private WidgetHostViewLoader mWidgetHostViewLoader; + private Rect mPadding = new Rect(); public WidgetsContainerView(Context context) { @@ -95,8 +99,8 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie super(context, attrs, defStyleAttr); mLauncher = (Launcher) context; mDragController = mLauncher.getDragController(); - - mAdapter = new WidgetsListAdapter(context, this, mLauncher, this, mLauncher); + mWidgetHostViewLoader = new WidgetHostViewLoader(mLauncher); + mAdapter = new WidgetsListAdapter(context, this, this, mLauncher); mWidgets = new WidgetsModel(context, mAdapter); mAdapter.setWidgetsModel(mWidgets); mIconCache = (LauncherAppState.getInstance()).getIconCache(); @@ -146,12 +150,27 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie // Touch related handling. // + @Override + public void onClick(View v) { + // When we have exited widget tray or are in transition, disregard clicks + if (!mLauncher.isWidgetsViewVisible() + || mLauncher.getWorkspace().isSwitchingState() + || !(v instanceof WidgetCell)) return; + + // Let the user know that they have to long press to add a widget + if (mWidgetInstructionToast != null) { + mWidgetInstructionToast.cancel(); + } + mWidgetInstructionToast = Toast.makeText(getContext(),R.string.long_press_widget_to_add, + Toast.LENGTH_SHORT); + mWidgetInstructionToast.show(); + } + @Override public boolean onLongClick(View v) { if (DEBUG) { Log.d(TAG, String.format("onLonglick [v=%s]", v)); } - // Return early if this is not initiated from a touch if (!v.isInTouchMode()) return false; // When we have exited all apps or are in transition, disregard long clicks @@ -161,7 +180,11 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie Log.d(TAG, String.format("onLonglick dragging enabled?.", v)); if (!mLauncher.isDraggingEnabled()) return false; - return beginDragging(v); + boolean status = beginDragging(v); + if (status) { + mWidgetHostViewLoader.load(v); + } + return status; } private boolean beginDragging(View v) { @@ -174,7 +197,7 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie } // We delay entering spring-loaded mode slightly to make sure the UI - // thready is free of any work. + // thread is free of any work. postDelayed(new Runnable() { @Override public void run() { @@ -184,13 +207,12 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie mLauncher.enterSpringLoadedDragMode(); } } - }, 150); + }, SPRING_MODE_DELAY_MS); return true; } private boolean beginDraggingWidget(WidgetCell v) { - mDraggingWidget = true; // Get the widget preview as the drag representation ImageView image = (ImageView) v.findViewById(R.id.widget_preview); PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag(); @@ -198,7 +220,6 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and // we abort the drag. if (image.getDrawable() == null) { - mDraggingWidget = false; return false; } @@ -259,19 +280,6 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie return true; } - /* - * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent) - */ - @Override - public boolean onTouch(View v, MotionEvent ev) { - Log.d(TAG, String.format("onTouch [MotionEvent=%s]", ev)); - if (ev.getAction() == MotionEvent.ACTION_DOWN || - ev.getAction() == MotionEvent.ACTION_MOVE) { - mLastTouchDownPos.set((int) ev.getX(), (int) ev.getY()); - } - return false; - } - // // Drag related handling methods that implement {@link DragSource} interface. // @@ -340,6 +348,10 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie } d.deferDragViewCleanupPostAnimation = false; } + //TODO(hyunyoungs): if drop fails, this call cleans up correctly. + // However, in rare corner case where drop succeeds but doesn't end up using the widget + // id created by the loader, this finish will leave dangling widget id. + mWidgetHostViewLoader.finish(success); } // @@ -368,5 +380,4 @@ public class WidgetsContainerView extends FrameLayout implements Insettable, Vie } return mWidgetPreviewLoader; } - } \ No newline at end of file diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java index afeb2d385..f6ab21eb4 100644 --- a/src/com/android/launcher3/widget/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java @@ -56,20 +56,16 @@ public class WidgetsListAdapter extends Adapter { private WidgetsModel mWidgetsModel; private WidgetPreviewLoader mWidgetPreviewLoader; - private View.OnTouchListener mTouchListener; private View.OnClickListener mIconClickListener; private View.OnLongClickListener mIconLongClickListener; - public WidgetsListAdapter(Context context, - View.OnTouchListener touchListener, View.OnClickListener iconClickListener, View.OnLongClickListener iconLongClickListener, Launcher launcher) { mLayoutInflater = LayoutInflater.from(context); mContext = context; - mTouchListener = touchListener; mIconClickListener = iconClickListener; mIconLongClickListener = iconLongClickListener; @@ -109,7 +105,6 @@ public class WidgetsListAdapter extends Adapter { // set up touch. widget.setOnClickListener(mIconClickListener); widget.setOnLongClickListener(mIconLongClickListener); - widget.setOnTouchListener(mTouchListener); row.addView(widget); } } else if (diff < 0) { -- cgit v1.2.3