blob: 882468624997da94a5c075d9e952d14dcae17170 [file] [log] [blame]
Adam Cohend4844c32011-02-18 19:25:06 -08001package com.android.launcher2;
2
3import android.animation.AnimatorSet;
4import android.animation.ObjectAnimator;
5import android.animation.PropertyValuesHolder;
6import android.animation.ValueAnimator;
7import android.animation.ValueAnimator.AnimatorUpdateListener;
Adam Cohen0cf2a7c2011-11-08 15:07:01 -08008import android.appwidget.AppWidgetHostView;
Adam Cohend4844c32011-02-18 19:25:06 -08009import android.appwidget.AppWidgetProviderInfo;
10import android.content.Context;
Adam Cohen0cf2a7c2011-11-08 15:07:01 -080011import android.graphics.Rect;
Adam Cohend4844c32011-02-18 19:25:06 -080012import android.view.Gravity;
13import android.widget.FrameLayout;
14import android.widget.ImageView;
15
16import com.android.launcher.R;
17
18public class AppWidgetResizeFrame extends FrameLayout {
Adam Cohend4844c32011-02-18 19:25:06 -080019 private LauncherAppWidgetHostView mWidgetView;
20 private CellLayout mCellLayout;
Adam Cohen67882692011-03-11 15:29:03 -080021 private DragLayer mDragLayer;
22 private Workspace mWorkspace;
Adam Cohend4844c32011-02-18 19:25:06 -080023 private ImageView mLeftHandle;
24 private ImageView mRightHandle;
Adam Cohen1b607ed2011-03-03 17:26:50 -080025 private ImageView mTopHandle;
Adam Cohend4844c32011-02-18 19:25:06 -080026 private ImageView mBottomHandle;
27
28 private boolean mLeftBorderActive;
29 private boolean mRightBorderActive;
30 private boolean mTopBorderActive;
31 private boolean mBottomBorderActive;
32
Adam Cohen37b59ff2011-06-13 17:13:42 -070033 private int mWidgetPaddingLeft;
34 private int mWidgetPaddingRight;
35 private int mWidgetPaddingTop;
36 private int mWidgetPaddingBottom;
37
Adam Cohend4844c32011-02-18 19:25:06 -080038 private int mBaselineWidth;
39 private int mBaselineHeight;
40 private int mBaselineX;
41 private int mBaselineY;
42 private int mResizeMode;
Adam Cohen3cba7222011-03-02 19:03:11 -080043
Adam Cohend4844c32011-02-18 19:25:06 -080044 private int mRunningHInc;
45 private int mRunningVInc;
46 private int mMinHSpan;
47 private int mMinVSpan;
48 private int mDeltaX;
49 private int mDeltaY;
Adam Cohenbebf0422012-04-11 18:06:28 -070050 private int mDeltaXAddOn;
51 private int mDeltaYAddOn;
Adam Cohen1b607ed2011-03-03 17:26:50 -080052
Adam Cohen3cba7222011-03-02 19:03:11 -080053 private int mBackgroundPadding;
54 private int mTouchTargetWidth;
Adam Cohend4844c32011-02-18 19:25:06 -080055
Adam Cohenbebf0422012-04-11 18:06:28 -070056 int[] mDirectionVector = new int[2];
Adam Cohend4844c32011-02-18 19:25:06 -080057
Adam Cohend4844c32011-02-18 19:25:06 -080058 final int SNAP_DURATION = 150;
Adam Cohen3cba7222011-03-02 19:03:11 -080059 final int BACKGROUND_PADDING = 24;
Adam Cohene4b77292011-03-08 18:35:52 -080060 final float DIMMED_HANDLE_ALPHA = 0f;
61 final float RESIZE_THRESHOLD = 0.66f;
Adam Cohend4844c32011-02-18 19:25:06 -080062
Adam Cohen1b607ed2011-03-03 17:26:50 -080063 public static final int LEFT = 0;
64 public static final int TOP = 1;
65 public static final int RIGHT = 2;
66 public static final int BOTTOM = 3;
67
Adam Cohencbf47e32011-09-16 17:32:37 -070068 private Launcher mLauncher;
69
Michael Jurka3a9fced2012-04-13 14:44:29 -070070 public AppWidgetResizeFrame(Context context,
Adam Cohen67882692011-03-11 15:29:03 -080071 LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
Adam Cohend4844c32011-02-18 19:25:06 -080072
73 super(context);
Adam Cohencbf47e32011-09-16 17:32:37 -070074 mLauncher = (Launcher) context;
Adam Cohend4844c32011-02-18 19:25:06 -080075 mCellLayout = cellLayout;
76 mWidgetView = widgetView;
Adam Cohen27c09b02011-02-28 14:45:11 -080077 mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
Adam Cohen67882692011-03-11 15:29:03 -080078 mDragLayer = dragLayer;
79 mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
Adam Cohen3cba7222011-03-02 19:03:11 -080080
Adam Cohend4844c32011-02-18 19:25:06 -080081 final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
Adam Cohen2f093b62012-04-30 18:59:53 -070082 int[] result = Launcher.getMinSpanForWidget(mLauncher, info);
Adam Cohend4844c32011-02-18 19:25:06 -080083 mMinHSpan = result[0];
84 mMinVSpan = result[1];
85
Adam Cohen3cba7222011-03-02 19:03:11 -080086 setBackgroundResource(R.drawable.widget_resize_frame_holo);
Adam Cohend4844c32011-02-18 19:25:06 -080087 setPadding(0, 0, 0, 0);
88
89 LayoutParams lp;
90 mLeftHandle = new ImageView(context);
Adam Cohen3cba7222011-03-02 19:03:11 -080091 mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left);
Adam Cohend4844c32011-02-18 19:25:06 -080092 lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
93 Gravity.LEFT | Gravity.CENTER_VERTICAL);
94 addView(mLeftHandle, lp);
95
96 mRightHandle = new ImageView(context);
Adam Cohen3cba7222011-03-02 19:03:11 -080097 mRightHandle.setImageResource(R.drawable.widget_resize_handle_right);
Adam Cohend4844c32011-02-18 19:25:06 -080098 lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
99 Gravity.RIGHT | Gravity.CENTER_VERTICAL);
100 addView(mRightHandle, lp);
101
102 mTopHandle = new ImageView(context);
Adam Cohen3cba7222011-03-02 19:03:11 -0800103 mTopHandle.setImageResource(R.drawable.widget_resize_handle_top);
Adam Cohend4844c32011-02-18 19:25:06 -0800104 lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
105 Gravity.CENTER_HORIZONTAL | Gravity.TOP);
106 addView(mTopHandle, lp);
107
108 mBottomHandle = new ImageView(context);
Adam Cohen3cba7222011-03-02 19:03:11 -0800109 mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom);
Adam Cohend4844c32011-02-18 19:25:06 -0800110 lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
111 Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
112 addView(mBottomHandle, lp);
113
Adam Cohen0cf2a7c2011-11-08 15:07:01 -0800114 Rect p = AppWidgetHostView.getDefaultPaddingForWidget(context,
115 widgetView.getAppWidgetInfo().provider, null);
Adam Cohen82ebbd22011-09-30 15:05:40 -0700116 mWidgetPaddingLeft = p.left;
117 mWidgetPaddingTop = p.top;
118 mWidgetPaddingRight = p.right;
119 mWidgetPaddingBottom = p.bottom;
Adam Cohen37b59ff2011-06-13 17:13:42 -0700120
Adam Cohend4844c32011-02-18 19:25:06 -0800121 if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
122 mTopHandle.setVisibility(GONE);
123 mBottomHandle.setVisibility(GONE);
124 } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
125 mLeftHandle.setVisibility(GONE);
126 mRightHandle.setVisibility(GONE);
Adam Cohen3cba7222011-03-02 19:03:11 -0800127 }
128
Adam Cohencbf47e32011-09-16 17:32:37 -0700129 final float density = mLauncher.getResources().getDisplayMetrics().density;
Adam Cohen3cba7222011-03-02 19:03:11 -0800130 mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING);
131 mTouchTargetWidth = 2 * mBackgroundPadding;
Adam Cohenbebf0422012-04-11 18:06:28 -0700132
133 // When we create the resize frame, we first mark all cells as unoccupied. The appropriate
134 // cells (same if not resized, or different) will be marked as occupied when the resize
135 // frame is dismissed.
136 mCellLayout.markCellsAsUnoccupiedForView(mWidgetView);
Adam Cohend4844c32011-02-18 19:25:06 -0800137 }
138
139 public boolean beginResizeIfPointInRegion(int x, int y) {
140 boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
141 boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
Adam Cohen3cba7222011-03-02 19:03:11 -0800142 mLeftBorderActive = (x < mTouchTargetWidth) && horizontalActive;
143 mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && horizontalActive;
144 mTopBorderActive = (y < mTouchTargetWidth) && verticalActive;
145 mBottomBorderActive = (y > getHeight() - mTouchTargetWidth) && verticalActive;
Adam Cohend4844c32011-02-18 19:25:06 -0800146
147 boolean anyBordersActive = mLeftBorderActive || mRightBorderActive
148 || mTopBorderActive || mBottomBorderActive;
149
150 mBaselineWidth = getMeasuredWidth();
151 mBaselineHeight = getMeasuredHeight();
152 mBaselineX = getLeft();
153 mBaselineY = getTop();
Adam Cohend4844c32011-02-18 19:25:06 -0800154
155 if (anyBordersActive) {
Adam Cohen3cba7222011-03-02 19:03:11 -0800156 mLeftHandle.setAlpha(mLeftBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
157 mRightHandle.setAlpha(mRightBorderActive ? 1.0f :DIMMED_HANDLE_ALPHA);
158 mTopHandle.setAlpha(mTopBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
159 mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
Adam Cohend4844c32011-02-18 19:25:06 -0800160 }
Adam Cohend4844c32011-02-18 19:25:06 -0800161 return anyBordersActive;
162 }
163
Adam Cohen1b607ed2011-03-03 17:26:50 -0800164 /**
165 * Here we bound the deltas such that the frame cannot be stretched beyond the extents
166 * of the CellLayout, and such that the frame's borders can't cross.
167 */
Adam Cohend4844c32011-02-18 19:25:06 -0800168 public void updateDeltas(int deltaX, int deltaY) {
169 if (mLeftBorderActive) {
170 mDeltaX = Math.max(-mBaselineX, deltaX);
Adam Cohen3cba7222011-03-02 19:03:11 -0800171 mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
Adam Cohend4844c32011-02-18 19:25:06 -0800172 } else if (mRightBorderActive) {
Adam Cohen67882692011-03-11 15:29:03 -0800173 mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
Adam Cohen3cba7222011-03-02 19:03:11 -0800174 mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
Adam Cohend4844c32011-02-18 19:25:06 -0800175 }
176
177 if (mTopBorderActive) {
178 mDeltaY = Math.max(-mBaselineY, deltaY);
Adam Cohen3cba7222011-03-02 19:03:11 -0800179 mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
Adam Cohend4844c32011-02-18 19:25:06 -0800180 } else if (mBottomBorderActive) {
Adam Cohen67882692011-03-11 15:29:03 -0800181 mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
Adam Cohen3cba7222011-03-02 19:03:11 -0800182 mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
Adam Cohend4844c32011-02-18 19:25:06 -0800183 }
184 }
185
Adam Cohenbebf0422012-04-11 18:06:28 -0700186 public void visualizeResizeForDelta(int deltaX, int deltaY) {
187 visualizeResizeForDelta(deltaX, deltaY, false);
188 }
189
Adam Cohen1b607ed2011-03-03 17:26:50 -0800190 /**
191 * Based on the deltas, we resize the frame, and, if needed, we resize the widget.
192 */
Adam Cohenbebf0422012-04-11 18:06:28 -0700193 private void visualizeResizeForDelta(int deltaX, int deltaY, boolean onDismiss) {
Adam Cohend4844c32011-02-18 19:25:06 -0800194 updateDeltas(deltaX, deltaY);
Adam Cohen67882692011-03-11 15:29:03 -0800195 DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
196
Adam Cohend4844c32011-02-18 19:25:06 -0800197 if (mLeftBorderActive) {
198 lp.x = mBaselineX + mDeltaX;
199 lp.width = mBaselineWidth - mDeltaX;
200 } else if (mRightBorderActive) {
201 lp.width = mBaselineWidth + mDeltaX;
202 }
203
204 if (mTopBorderActive) {
205 lp.y = mBaselineY + mDeltaY;
206 lp.height = mBaselineHeight - mDeltaY;
207 } else if (mBottomBorderActive) {
208 lp.height = mBaselineHeight + mDeltaY;
209 }
210
Adam Cohenbebf0422012-04-11 18:06:28 -0700211 resizeWidgetIfNeeded(onDismiss);
Adam Cohend4844c32011-02-18 19:25:06 -0800212 requestLayout();
213 }
214
Adam Cohen1b607ed2011-03-03 17:26:50 -0800215 /**
216 * Based on the current deltas, we determine if and how to resize the widget.
217 */
Adam Cohenbebf0422012-04-11 18:06:28 -0700218 private void resizeWidgetIfNeeded(boolean onDismiss) {
Adam Cohend4844c32011-02-18 19:25:06 -0800219 int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
220 int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
221
Adam Cohenbebf0422012-04-11 18:06:28 -0700222 int deltaX = mDeltaX + mDeltaXAddOn;
223 int deltaY = mDeltaY + mDeltaYAddOn;
224
225 float hSpanIncF = 1.0f * deltaX / xThreshold - mRunningHInc;
226 float vSpanIncF = 1.0f * deltaY / yThreshold - mRunningVInc;
Adam Cohene4b77292011-03-08 18:35:52 -0800227
228 int hSpanInc = 0;
229 int vSpanInc = 0;
Adam Cohend4844c32011-02-18 19:25:06 -0800230 int cellXInc = 0;
231 int cellYInc = 0;
232
Adam Cohenbebf0422012-04-11 18:06:28 -0700233 int countX = mCellLayout.getCountX();
234 int countY = mCellLayout.getCountY();
235
Adam Cohene4b77292011-03-08 18:35:52 -0800236 if (Math.abs(hSpanIncF) > RESIZE_THRESHOLD) {
237 hSpanInc = Math.round(hSpanIncF);
238 }
239 if (Math.abs(vSpanIncF) > RESIZE_THRESHOLD) {
240 vSpanInc = Math.round(vSpanIncF);
241 }
242
Adam Cohenbebf0422012-04-11 18:06:28 -0700243 if (!onDismiss && (hSpanInc == 0 && vSpanInc == 0)) return;
Adam Cohend4844c32011-02-18 19:25:06 -0800244
Adam Cohend4844c32011-02-18 19:25:06 -0800245
246 CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
Adam Cohen1b607ed2011-03-03 17:26:50 -0800247
Adam Cohenbebf0422012-04-11 18:06:28 -0700248 int spanX = lp.cellHSpan;
249 int spanY = lp.cellVSpan;
250 int cellX = lp.useTmpCoords ? lp.tmpCellX : lp.cellX;
251 int cellY = lp.useTmpCoords ? lp.tmpCellY : lp.cellY;
252
253 int hSpanDelta = 0;
254 int vSpanDelta = 0;
255
Adam Cohen1b607ed2011-03-03 17:26:50 -0800256 // For each border, we bound the resizing based on the minimum width, and the maximum
257 // expandability.
Adam Cohend4844c32011-02-18 19:25:06 -0800258 if (mLeftBorderActive) {
Adam Cohenbebf0422012-04-11 18:06:28 -0700259 cellXInc = Math.max(-cellX, hSpanInc);
Adam Cohend4844c32011-02-18 19:25:06 -0800260 cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc);
261 hSpanInc *= -1;
Adam Cohenbebf0422012-04-11 18:06:28 -0700262 hSpanInc = Math.min(cellX, hSpanInc);
Adam Cohend4844c32011-02-18 19:25:06 -0800263 hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
Adam Cohenbebf0422012-04-11 18:06:28 -0700264 hSpanDelta = -hSpanInc;
265
Adam Cohend4844c32011-02-18 19:25:06 -0800266 } else if (mRightBorderActive) {
Adam Cohenbebf0422012-04-11 18:06:28 -0700267 hSpanInc = Math.min(countX - (cellX + spanX), hSpanInc);
Adam Cohend4844c32011-02-18 19:25:06 -0800268 hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
Adam Cohenbebf0422012-04-11 18:06:28 -0700269 hSpanDelta = hSpanInc;
Adam Cohend4844c32011-02-18 19:25:06 -0800270 }
271
272 if (mTopBorderActive) {
Adam Cohenbebf0422012-04-11 18:06:28 -0700273 cellYInc = Math.max(-cellY, vSpanInc);
Adam Cohend4844c32011-02-18 19:25:06 -0800274 cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc);
275 vSpanInc *= -1;
Adam Cohenbebf0422012-04-11 18:06:28 -0700276 vSpanInc = Math.min(cellY, vSpanInc);
Adam Cohend4844c32011-02-18 19:25:06 -0800277 vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
Adam Cohenbebf0422012-04-11 18:06:28 -0700278 vSpanDelta = -vSpanInc;
Adam Cohend4844c32011-02-18 19:25:06 -0800279 } else if (mBottomBorderActive) {
Adam Cohenbebf0422012-04-11 18:06:28 -0700280 vSpanInc = Math.min(countY - (cellY + spanY), vSpanInc);
Adam Cohend4844c32011-02-18 19:25:06 -0800281 vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
Adam Cohenbebf0422012-04-11 18:06:28 -0700282 vSpanDelta = vSpanInc;
Adam Cohend4844c32011-02-18 19:25:06 -0800283 }
284
Adam Cohenbebf0422012-04-11 18:06:28 -0700285 mDirectionVector[0] = 0;
286 mDirectionVector[1] = 0;
Adam Cohend4844c32011-02-18 19:25:06 -0800287 // Update the widget's dimensions and position according to the deltas computed above
288 if (mLeftBorderActive || mRightBorderActive) {
Adam Cohenbebf0422012-04-11 18:06:28 -0700289 spanX += hSpanInc;
290 cellX += cellXInc;
291 mDirectionVector[0] = mLeftBorderActive ? -1 : 1;
Adam Cohend4844c32011-02-18 19:25:06 -0800292 }
293
294 if (mTopBorderActive || mBottomBorderActive) {
Adam Cohenbebf0422012-04-11 18:06:28 -0700295 spanY += vSpanInc;
296 cellY += cellYInc;
297 mDirectionVector[1] = mTopBorderActive ? -1 : 1;
Adam Cohend4844c32011-02-18 19:25:06 -0800298 }
299
Adam Cohenbebf0422012-04-11 18:06:28 -0700300 if (!onDismiss && vSpanDelta == 0 && hSpanDelta == 0) return;
Adam Cohend4844c32011-02-18 19:25:06 -0800301
Adam Cohenbebf0422012-04-11 18:06:28 -0700302 if (mCellLayout.createAreaForResize(cellX, cellY, spanX, spanY, mWidgetView,
303 mDirectionVector, onDismiss)) {
304 lp.tmpCellX = cellX;
305 lp.tmpCellY = cellY;
306 lp.cellHSpan = spanX;
307 lp.cellVSpan = spanY;
308 mRunningVInc += vSpanDelta;
309 mRunningHInc += hSpanDelta;
Adam Cohena897f392012-04-27 18:12:05 -0700310 if (!onDismiss) {
311 updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
312 }
Adam Cohenbebf0422012-04-11 18:06:28 -0700313 }
Adam Cohen67882692011-03-11 15:29:03 -0800314 mWidgetView.requestLayout();
Adam Cohend4844c32011-02-18 19:25:06 -0800315 }
316
Adam Cohena897f392012-04-27 18:12:05 -0700317 static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
318 int spanX, int spanY) {
319 Rect landMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.LANDSCAPE);
320 Rect portMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.PORTRAIT);
321 final float density = launcher.getResources().getDisplayMetrics().density;
322
323 // Compute landscape size
324 int cellWidth = landMetrics.left;
325 int cellHeight = landMetrics.top;
326 int widthGap = landMetrics.right;
327 int heightGap = landMetrics.bottom;
328 int landWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
329 int landHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
330
331 // Compute portrait size
332 cellWidth = portMetrics.left;
333 cellHeight = portMetrics.top;
334 widthGap = portMetrics.right;
335 heightGap = portMetrics.bottom;
336 int portWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
337 int portHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
338
339 widgetView.updateAppWidgetSize(null, portWidth, landHeight, landWidth, portHeight);
340 }
341
Adam Cohen1b607ed2011-03-03 17:26:50 -0800342 /**
343 * This is the final step of the resize. Here we save the new widget size and position
344 * to LauncherModel and animate the resize frame.
345 */
Adam Cohenbebf0422012-04-11 18:06:28 -0700346 public void commitResize() {
347 resizeWidgetIfNeeded(true);
348 requestLayout();
349 }
Adam Cohend4844c32011-02-18 19:25:06 -0800350
Adam Cohenbebf0422012-04-11 18:06:28 -0700351 public void onTouchUp() {
352 int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
353 int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
Adam Cohend4844c32011-02-18 19:25:06 -0800354
Adam Cohenbebf0422012-04-11 18:06:28 -0700355 mDeltaXAddOn = mRunningHInc * xThreshold;
356 mDeltaYAddOn = mRunningVInc * yThreshold;
357 mDeltaX = 0;
358 mDeltaY = 0;
359
Adam Cohend4844c32011-02-18 19:25:06 -0800360 post(new Runnable() {
Adam Cohenbebf0422012-04-11 18:06:28 -0700361 @Override
Adam Cohend4844c32011-02-18 19:25:06 -0800362 public void run() {
363 snapToWidget(true);
364 }
365 });
366 }
367
368 public void snapToWidget(boolean animate) {
Adam Cohen67882692011-03-11 15:29:03 -0800369 final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
Winson Chung4b825dcd2011-06-19 12:41:22 -0700370 int xOffset = mCellLayout.getLeft() + mCellLayout.getPaddingLeft() - mWorkspace.getScrollX();
371 int yOffset = mCellLayout.getTop() + mCellLayout.getPaddingTop() - mWorkspace.getScrollY();
Adam Cohend4844c32011-02-18 19:25:06 -0800372
Adam Cohen37b59ff2011-06-13 17:13:42 -0700373 int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft -
374 mWidgetPaddingRight;
375 int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop -
376 mWidgetPaddingBottom;
377
378 int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset + mWidgetPaddingLeft;
379 int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset + mWidgetPaddingTop;
Adam Cohen3cba7222011-03-02 19:03:11 -0800380
381 // We need to make sure the frame stays within the bounds of the CellLayout
382 if (newY < 0) {
383 newHeight -= -newY;
384 newY = 0;
385 }
Adam Cohen67882692011-03-11 15:29:03 -0800386 if (newY + newHeight > mDragLayer.getHeight()) {
387 newHeight -= newY + newHeight - mDragLayer.getHeight();
Adam Cohen3cba7222011-03-02 19:03:11 -0800388 }
389
Adam Cohend4844c32011-02-18 19:25:06 -0800390 if (!animate) {
391 lp.width = newWidth;
392 lp.height = newHeight;
393 lp.x = newX;
394 lp.y = newY;
395 mLeftHandle.setAlpha(1.0f);
396 mRightHandle.setAlpha(1.0f);
397 mTopHandle.setAlpha(1.0f);
398 mBottomHandle.setAlpha(1.0f);
399 requestLayout();
400 } else {
401 PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", lp.width, newWidth);
Adam Cohen1b607ed2011-03-03 17:26:50 -0800402 PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", lp.height,
403 newHeight);
Adam Cohend4844c32011-02-18 19:25:06 -0800404 PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX);
405 PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY);
406 ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
407 ObjectAnimator leftOa = ObjectAnimator.ofFloat(mLeftHandle, "alpha", 1.0f);
408 ObjectAnimator rightOa = ObjectAnimator.ofFloat(mRightHandle, "alpha", 1.0f);
409 ObjectAnimator topOa = ObjectAnimator.ofFloat(mTopHandle, "alpha", 1.0f);
410 ObjectAnimator bottomOa = ObjectAnimator.ofFloat(mBottomHandle, "alpha", 1.0f);
411 oa.addUpdateListener(new AnimatorUpdateListener() {
412 public void onAnimationUpdate(ValueAnimator animation) {
413 requestLayout();
414 }
415 });
416 AnimatorSet set = new AnimatorSet();
417 if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
418 set.playTogether(oa, topOa, bottomOa);
419 } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
420 set.playTogether(oa, leftOa, rightOa);
421 } else {
422 set.playTogether(oa, leftOa, rightOa, topOa, bottomOa);
423 }
424
425 set.setDuration(SNAP_DURATION);
426 set.start();
427 }
428 }
429}