1d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenpackage com.android.launcher2; 2d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 3d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.AnimatorSet; 4d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.ObjectAnimator; 5d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.PropertyValuesHolder; 6d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.ValueAnimator; 7d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener; 80cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohenimport android.appwidget.AppWidgetHostView; 9d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.appwidget.AppWidgetProviderInfo; 10d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.content.Context; 110cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohenimport android.graphics.Rect; 12d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.view.Gravity; 13d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.widget.FrameLayout; 14d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.widget.ImageView; 15d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 16d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport com.android.launcher.R; 17d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 18d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenpublic class AppWidgetResizeFrame extends FrameLayout { 19d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 20d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private ItemInfo mItemInfo; 21d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private LauncherAppWidgetHostView mWidgetView; 22d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private CellLayout mCellLayout; 236788269814a678af976dfc7d6135993e172ce586Adam Cohen private DragLayer mDragLayer; 246788269814a678af976dfc7d6135993e172ce586Adam Cohen private Workspace mWorkspace; 25d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private ImageView mLeftHandle; 26d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private ImageView mRightHandle; 271b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen private ImageView mTopHandle; 28d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private ImageView mBottomHandle; 29d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 30d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private boolean mLeftBorderActive; 31d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private boolean mRightBorderActive; 32d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private boolean mTopBorderActive; 33d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private boolean mBottomBorderActive; 34d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 3537b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen private int mWidgetPaddingLeft; 3637b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen private int mWidgetPaddingRight; 3737b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen private int mWidgetPaddingTop; 3837b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen private int mWidgetPaddingBottom; 3937b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen 40d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mBaselineWidth; 41d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mBaselineHeight; 42d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mBaselineX; 43d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mBaselineY; 44d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mResizeMode; 453cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen 46d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mRunningHInc; 47d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mRunningVInc; 48d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mMinHSpan; 49d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mMinVSpan; 50d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mDeltaX; 51d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mDeltaY; 521b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen 533cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen private int mBackgroundPadding; 543cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen private int mTouchTargetWidth; 55d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 56d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private int mExpandability[] = new int[4]; 57d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 58d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen final int SNAP_DURATION = 150; 593cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen final int BACKGROUND_PADDING = 24; 60e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen final float DIMMED_HANDLE_ALPHA = 0f; 61e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen final float RESIZE_THRESHOLD = 0.66f; 62d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 631b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen public static final int LEFT = 0; 641b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen public static final int TOP = 1; 651b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen public static final int RIGHT = 2; 661b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen public static final int BOTTOM = 3; 671b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen 68cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen private Launcher mLauncher; 69cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen 70d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public AppWidgetResizeFrame(Context context, ItemInfo itemInfo, 716788269814a678af976dfc7d6135993e172ce586Adam Cohen LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) { 72d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 73d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen super(context); 74cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen mLauncher = (Launcher) context; 75d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mItemInfo = itemInfo; 76d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mCellLayout = cellLayout; 77d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mWidgetView = widgetView; 7827c09b05d3ed2a4ce9d53140216aba998727a569Adam Cohen mResizeMode = widgetView.getAppWidgetInfo().resizeMode; 796788269814a678af976dfc7d6135993e172ce586Adam Cohen mDragLayer = dragLayer; 806788269814a678af976dfc7d6135993e172ce586Adam Cohen mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace); 813cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen 82d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo(); 83cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen int[] result = mLauncher.getMinResizeSpanForWidget(info, null); 84d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mMinHSpan = result[0]; 85d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mMinVSpan = result[1]; 86d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 873cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen setBackgroundResource(R.drawable.widget_resize_frame_holo); 88d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen setPadding(0, 0, 0, 0); 89d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 90d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen LayoutParams lp; 91d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mLeftHandle = new ImageView(context); 923cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left); 93d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 94d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen Gravity.LEFT | Gravity.CENTER_VERTICAL); 95d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen addView(mLeftHandle, lp); 96d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 97d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRightHandle = new ImageView(context); 983cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mRightHandle.setImageResource(R.drawable.widget_resize_handle_right); 99d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 100d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen Gravity.RIGHT | Gravity.CENTER_VERTICAL); 101d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen addView(mRightHandle, lp); 102d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 103d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mTopHandle = new ImageView(context); 1043cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mTopHandle.setImageResource(R.drawable.widget_resize_handle_top); 105d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 106d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen Gravity.CENTER_HORIZONTAL | Gravity.TOP); 107d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen addView(mTopHandle, lp); 108d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 109d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBottomHandle = new ImageView(context); 1103cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom); 111d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 112d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); 113d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen addView(mBottomHandle, lp); 114d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 1150cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohen Rect p = AppWidgetHostView.getDefaultPaddingForWidget(context, 1160cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohen widgetView.getAppWidgetInfo().provider, null); 11782ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen mWidgetPaddingLeft = p.left; 11882ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen mWidgetPaddingTop = p.top; 11982ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen mWidgetPaddingRight = p.right; 12082ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen mWidgetPaddingBottom = p.bottom; 12137b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen 122d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) { 123d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mTopHandle.setVisibility(GONE); 124d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBottomHandle.setVisibility(GONE); 125d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) { 126d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mLeftHandle.setVisibility(GONE); 127d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRightHandle.setVisibility(GONE); 1283cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen } 1293cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen 130cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen final float density = mLauncher.getResources().getDisplayMetrics().density; 1313cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING); 1323cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mTouchTargetWidth = 2 * mBackgroundPadding; 133d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 134d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 135d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public boolean beginResizeIfPointInRegion(int x, int y) { 136d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0; 137d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0; 1383cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mLeftBorderActive = (x < mTouchTargetWidth) && horizontalActive; 1393cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && horizontalActive; 1403cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mTopBorderActive = (y < mTouchTargetWidth) && verticalActive; 1413cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mBottomBorderActive = (y > getHeight() - mTouchTargetWidth) && verticalActive; 142d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 143d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen boolean anyBordersActive = mLeftBorderActive || mRightBorderActive 144d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen || mTopBorderActive || mBottomBorderActive; 145d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 146d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBaselineWidth = getMeasuredWidth(); 147d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBaselineHeight = getMeasuredHeight(); 148d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBaselineX = getLeft(); 149d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBaselineY = getTop(); 150d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRunningHInc = 0; 151d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRunningVInc = 0; 152d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 153d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (anyBordersActive) { 1543cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mLeftHandle.setAlpha(mLeftBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA); 1553cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mRightHandle.setAlpha(mRightBorderActive ? 1.0f :DIMMED_HANDLE_ALPHA); 1563cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mTopHandle.setAlpha(mTopBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA); 1573cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA); 158d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 159d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mCellLayout.getExpandabilityArrayForView(mWidgetView, mExpandability); 1603cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen 161d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen return anyBordersActive; 162d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 163d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 1641b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen /** 1651b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen * Here we bound the deltas such that the frame cannot be stretched beyond the extents 1661b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen * of the CellLayout, and such that the frame's borders can't cross. 1671b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen */ 168d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public void updateDeltas(int deltaX, int deltaY) { 169d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mLeftBorderActive) { 170d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mDeltaX = Math.max(-mBaselineX, deltaX); 1713cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX); 172d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mRightBorderActive) { 1736788269814a678af976dfc7d6135993e172ce586Adam Cohen mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX); 1743cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX); 175d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 176d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 177d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mTopBorderActive) { 178d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mDeltaY = Math.max(-mBaselineY, deltaY); 1793cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY); 180d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mBottomBorderActive) { 1816788269814a678af976dfc7d6135993e172ce586Adam Cohen mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY); 1823cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY); 183d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 184d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 185d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 1861b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen /** 1871b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen * Based on the deltas, we resize the frame, and, if needed, we resize the widget. 1881b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen */ 189d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public void visualizeResizeForDelta(int deltaX, int deltaY) { 190d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen updateDeltas(deltaX, deltaY); 1916788269814a678af976dfc7d6135993e172ce586Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 1926788269814a678af976dfc7d6135993e172ce586Adam Cohen 193d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mLeftBorderActive) { 194d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.x = mBaselineX + mDeltaX; 195d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.width = mBaselineWidth - mDeltaX; 196d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mRightBorderActive) { 197d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.width = mBaselineWidth + mDeltaX; 198d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 199d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 200d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mTopBorderActive) { 201d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.y = mBaselineY + mDeltaY; 202d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.height = mBaselineHeight - mDeltaY; 203d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mBottomBorderActive) { 204d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.height = mBaselineHeight + mDeltaY; 205d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 206d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 207d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen resizeWidgetIfNeeded(); 208d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen requestLayout(); 209d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 210d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 2111b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen /** 2121b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen * Based on the current deltas, we determine if and how to resize the widget. 2131b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen */ 214d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen private void resizeWidgetIfNeeded() { 215d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap(); 216d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap(); 217d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 218e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen float hSpanIncF = 1.0f * mDeltaX / xThreshold - mRunningHInc; 219e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen float vSpanIncF = 1.0f * mDeltaY / yThreshold - mRunningVInc; 220e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen 221e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen int hSpanInc = 0; 222e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen int vSpanInc = 0; 223d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen int cellXInc = 0; 224d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen int cellYInc = 0; 225d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 226e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen if (Math.abs(hSpanIncF) > RESIZE_THRESHOLD) { 227e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen hSpanInc = Math.round(hSpanIncF); 228e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen } 229e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen if (Math.abs(vSpanIncF) > RESIZE_THRESHOLD) { 230e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen vSpanInc = Math.round(vSpanIncF); 231e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen } 232e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen 233d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (hSpanInc == 0 && vSpanInc == 0) return; 234d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 235d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen // Before we change the widget, we clear the occupied cells associated with it. 236d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen // The new set of occupied cells is marked below, once the layout params are updated. 237d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mCellLayout.markCellsAsUnoccupiedForView(mWidgetView); 238d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 239d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams(); 2401b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen 2411b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen // For each border, we bound the resizing based on the minimum width, and the maximum 2421b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen // expandability. 243d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mLeftBorderActive) { 2441b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen cellXInc = Math.max(-mExpandability[LEFT], hSpanInc); 245d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc); 246d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen hSpanInc *= -1; 2471b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen hSpanInc = Math.min(mExpandability[LEFT], hSpanInc); 248d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc); 249d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRunningHInc -= hSpanInc; 250d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mRightBorderActive) { 2511b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen hSpanInc = Math.min(mExpandability[RIGHT], hSpanInc); 252d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc); 253d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRunningHInc += hSpanInc; 254d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 255d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 256d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mTopBorderActive) { 2571b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen cellYInc = Math.max(-mExpandability[TOP], vSpanInc); 258d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc); 259d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen vSpanInc *= -1; 2601b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen vSpanInc = Math.min(mExpandability[TOP], vSpanInc); 261d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc); 262d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRunningVInc -= vSpanInc; 263d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mBottomBorderActive) { 2641b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen vSpanInc = Math.min(mExpandability[BOTTOM], vSpanInc); 265d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc); 266d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRunningVInc += vSpanInc; 267d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 268d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 269d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen // Update the widget's dimensions and position according to the deltas computed above 270d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mLeftBorderActive || mRightBorderActive) { 271d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.cellHSpan += hSpanInc; 272d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.cellX += cellXInc; 273d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 274d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 275d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mTopBorderActive || mBottomBorderActive) { 276d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.cellVSpan += vSpanInc; 277d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.cellY += cellYInc; 278d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 279d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 2801b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen // Update the expandability array, as we have changed the widget's size. 2813cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen mCellLayout.getExpandabilityArrayForView(mWidgetView, mExpandability); 282d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 283d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen // Update the cells occupied by this widget 284d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mCellLayout.markCellsAsOccupiedForView(mWidgetView); 2856788269814a678af976dfc7d6135993e172ce586Adam Cohen mWidgetView.requestLayout(); 286d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 287d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 2881b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen /** 2891b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen * This is the final step of the resize. Here we save the new widget size and position 2901b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen * to LauncherModel and animate the resize frame. 2911b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen */ 292d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public void commitResizeForDelta(int deltaX, int deltaY) { 293d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen visualizeResizeForDelta(deltaX, deltaY); 294d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 295d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams(); 296d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen LauncherModel.resizeItemInDatabase(getContext(), mItemInfo, lp.cellX, lp.cellY, 297d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.cellHSpan, lp.cellVSpan); 298d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mWidgetView.requestLayout(); 299d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 300d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen // Once our widget resizes (hence the post), we want to snap the resize frame to it 301d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen post(new Runnable() { 302d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public void run() { 303d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen snapToWidget(true); 304d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 305d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen }); 306d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 307d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 308d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public void snapToWidget(boolean animate) { 3096788269814a678af976dfc7d6135993e172ce586Adam Cohen final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 3104b825dcd5f64a5ebb60271844fbc5257374422bcWinson Chung int xOffset = mCellLayout.getLeft() + mCellLayout.getPaddingLeft() - mWorkspace.getScrollX(); 3114b825dcd5f64a5ebb60271844fbc5257374422bcWinson Chung int yOffset = mCellLayout.getTop() + mCellLayout.getPaddingTop() - mWorkspace.getScrollY(); 312d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 31337b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft - 31437b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen mWidgetPaddingRight; 31537b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop - 31637b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen mWidgetPaddingBottom; 31737b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen 31837b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset + mWidgetPaddingLeft; 31937b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset + mWidgetPaddingTop; 3203cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen 3213cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen // We need to make sure the frame stays within the bounds of the CellLayout 3223cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen if (newY < 0) { 3233cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen newHeight -= -newY; 3243cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen newY = 0; 3253cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen } 3266788269814a678af976dfc7d6135993e172ce586Adam Cohen if (newY + newHeight > mDragLayer.getHeight()) { 3276788269814a678af976dfc7d6135993e172ce586Adam Cohen newHeight -= newY + newHeight - mDragLayer.getHeight(); 3283cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen } 3293cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen 330d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (!animate) { 331d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.width = newWidth; 332d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.height = newHeight; 333d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.x = newX; 334d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen lp.y = newY; 335d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mLeftHandle.setAlpha(1.0f); 336d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mRightHandle.setAlpha(1.0f); 337d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mTopHandle.setAlpha(1.0f); 338d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen mBottomHandle.setAlpha(1.0f); 339d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen requestLayout(); 340d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else { 341d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", lp.width, newWidth); 3421b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", lp.height, 3431b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen newHeight); 344d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX); 345d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY); 346d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y); 347d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen ObjectAnimator leftOa = ObjectAnimator.ofFloat(mLeftHandle, "alpha", 1.0f); 348d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen ObjectAnimator rightOa = ObjectAnimator.ofFloat(mRightHandle, "alpha", 1.0f); 349d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen ObjectAnimator topOa = ObjectAnimator.ofFloat(mTopHandle, "alpha", 1.0f); 350d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen ObjectAnimator bottomOa = ObjectAnimator.ofFloat(mBottomHandle, "alpha", 1.0f); 351d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen oa.addUpdateListener(new AnimatorUpdateListener() { 352d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen public void onAnimationUpdate(ValueAnimator animation) { 353d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen requestLayout(); 354d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 355d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen }); 356d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen AnimatorSet set = new AnimatorSet(); 357d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) { 358d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen set.playTogether(oa, topOa, bottomOa); 359d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) { 360d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen set.playTogether(oa, leftOa, rightOa); 361d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } else { 362d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen set.playTogether(oa, leftOa, rightOa, topOa, bottomOa); 363d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 364d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen 365d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen set.setDuration(SNAP_DURATION); 366d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen set.start(); 367d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 368d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen } 369d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen} 370