Fixing widget resize visual / ux ugliness, Bug: 4082591

Change-Id: Ib258e02f52dd83418db0c0249efdc90d2424f059
This commit is contained in:
Adam Cohen 2011-03-11 15:29:03 -08:00
parent 5a0d66c36e
commit 6788269814
6 changed files with 175 additions and 161 deletions

View File

@ -20,7 +20,7 @@
public void setHoverAlpha(float);
}
-keep class com.android.launcher2.CellLayout$LayoutParams {
-keep class com.android.launcher2.DragLayer$LayoutParams {
public void setWidth(int);
public int getWidth();
public void setHeight(int);

View File

@ -18,6 +18,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
private ItemInfo mItemInfo;
private LauncherAppWidgetHostView mWidgetView;
private CellLayout mCellLayout;
private DragLayer mDragLayer;
private Workspace mWorkspace;
private ImageView mLeftHandle;
private ImageView mRightHandle;
private ImageView mTopHandle;
@ -57,7 +59,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
public static final int BOTTOM = 3;
public AppWidgetResizeFrame(Context context, ItemInfo itemInfo,
LauncherAppWidgetHostView widgetView, CellLayout cellLayout) {
LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
super(context);
mContext = context;
@ -65,6 +67,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
mCellLayout = cellLayout;
mWidgetView = widgetView;
mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
mDragLayer = dragLayer;
mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null);
@ -150,7 +154,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
mDeltaX = Math.max(-mBaselineX, deltaX);
mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
} else if (mRightBorderActive) {
mDeltaX = Math.min(mCellLayout.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
}
@ -158,7 +162,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
mDeltaY = Math.max(-mBaselineY, deltaY);
mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
} else if (mBottomBorderActive) {
mDeltaY = Math.min(mCellLayout.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
}
}
@ -168,7 +172,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
*/
public void visualizeResizeForDelta(int deltaX, int deltaY) {
updateDeltas(deltaX, deltaY);
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
if (mLeftBorderActive) {
lp.x = mBaselineX + mDeltaX;
lp.width = mBaselineWidth - mDeltaX;
@ -261,6 +266,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
// Update the cells occupied by this widget
mCellLayout.markCellsAsOccupiedForView(mWidgetView);
mWidgetView.requestLayout();
}
/**
@ -284,20 +290,22 @@ public class AppWidgetResizeFrame extends FrameLayout {
}
public void snapToWidget(boolean animate) {
final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
int xOffset = mCellLayout.getLeft() - mWorkspace.getScrollX();
int yOffset = mCellLayout.getTop() - mWorkspace.getScrollY();
int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding;
int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding;
int newX = mWidgetView.getLeft() - mBackgroundPadding;
int newY = mWidgetView.getTop() - mBackgroundPadding;
int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset;
int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset;
// We need to make sure the frame stays within the bounds of the CellLayout
if (newY < 0) {
newHeight -= -newY;
newY = 0;
}
if (newY + newHeight > mCellLayout.getHeight()) {
newHeight -= newY + newHeight - mCellLayout.getHeight();
if (newY + newHeight > mDragLayer.getHeight()) {
newHeight -= newY + newHeight - mDragLayer.getHeight();
}
if (!animate) {

View File

@ -1551,38 +1551,6 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
}
}
public void setWidth(int width) {
this.width = width;
}
public int getWidth() {
return width;
}
public void setHeight(int height) {
this.height = height;
}
public int getHeight() {
return height;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public String toString() {
return "(" + this.cellX + ", " + this.cellY + ")";
}

View File

@ -43,12 +43,6 @@ public class CellLayoutChildren extends ViewGroup {
private int mWidthGap;
private int mHeightGap;
// Variables relating to resizing widgets
private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
new ArrayList<AppWidgetResizeFrame>();
private AppWidgetResizeFrame mCurrentResizeFrame;
private int mXDown, mYDown;
public CellLayoutChildren(Context context) {
super(context);
mWallpaperManager = WallpaperManager.getInstance(context);
@ -176,95 +170,4 @@ public class CellLayoutChildren extends ViewGroup {
protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
super.setChildrenDrawnWithCacheEnabled(enabled);
}
public void clearAllResizeFrames() {
for (AppWidgetResizeFrame frame: mResizeFrames) {
removeView(frame);
}
mResizeFrames.clear();
}
public boolean hasResizeFrames() {
return mResizeFrames.size() > 0;
}
public boolean isWidgetBeingResized() {
return mCurrentResizeFrame != null;
}
private boolean handleTouchDown(MotionEvent ev) {
Rect hitRect = new Rect();
int x = (int) ev.getX();
int y = (int) ev.getY();
for (AppWidgetResizeFrame child: mResizeFrames) {
child.getHitRect(hitRect);
if (hitRect.contains(x, y)) {
if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
mCurrentResizeFrame = child;
mXDown = x;
mYDown = y;
requestDisallowInterceptTouchEvent(true);
return true;
}
}
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev)) {
return true;
}
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = false;
int action = ev.getAction();
int x = (int) ev.getX();
int y = (int) ev.getY();
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev)) {
return true;
}
}
}
if (mCurrentResizeFrame != null) {
handled = true;
switch (action) {
case MotionEvent.ACTION_MOVE:
mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
mCurrentResizeFrame = null;
}
}
return handled;
}
public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
CellLayout cellLayout) {
AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
itemInfo, widget, cellLayout);
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(-1, -1, -1, -1);
lp.isLockedToGrid = false;
addView(resizeFrame, lp);
mResizeFrames.add(resizeFrame);
resizeFrame.snapToWidget(false);
}
}

View File

@ -16,10 +16,11 @@
package com.android.launcher2;
import com.android.launcher.R;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@ -27,6 +28,8 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.android.launcher.R;
/**
* A ViewGroup that coordinates dragging across its descendants
*/
@ -34,6 +37,12 @@ public class DragLayer extends FrameLayout {
private DragController mDragController;
private int[] mTmpXY = new int[2];
// Variables relating to resizing widgets
private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
new ArrayList<AppWidgetResizeFrame>();
private AppWidgetResizeFrame mCurrentResizeFrame;
private int mXDown, mYDown;
/**
* Used to create a new DragLayer from XML.
*
@ -56,31 +65,66 @@ public class DragLayer extends FrameLayout {
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// If the current CellLayoutChildren has a resize frame, we need to detect if any touch
// event has occurred which doesn't result in resizing a widget. In this case, we
// dismiss any visible resize frames.
final Workspace w = (Workspace) findViewById(R.id.workspace);
if (w != null) {
final CellLayout currentPage = (CellLayout) w.getChildAt(w.getCurrentPage());
final CellLayoutChildren childrenLayout = currentPage.getChildrenLayout();
private boolean handleTouchDown(MotionEvent ev) {
Rect hitRect = new Rect();
int x = (int) ev.getX();
int y = (int) ev.getY();
if (childrenLayout.hasResizeFrames() && !childrenLayout.isWidgetBeingResized()) {
post(new Runnable() {
public void run() {
if (!childrenLayout.isWidgetBeingResized()) {
childrenLayout.clearAllResizeFrames();
}
}
});
for (AppWidgetResizeFrame child: mResizeFrames) {
child.getHitRect(hitRect);
if (hitRect.contains(x, y)) {
if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
mCurrentResizeFrame = child;
mXDown = x;
mYDown = y;
requestDisallowInterceptTouchEvent(true);
return true;
}
}
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev)) {
return true;
}
}
clearAllResizeFrames();
return mDragController.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = false;
int action = ev.getAction();
int x = (int) ev.getX();
int y = (int) ev.getY();
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev)) {
return true;
}
}
}
if (mCurrentResizeFrame != null) {
handled = true;
switch (action) {
case MotionEvent.ACTION_MOVE:
mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
mCurrentResizeFrame = null;
}
}
if (handled) return true;
return mDragController.onTouchEvent(ev);
}
@ -103,4 +147,94 @@ public class DragLayer extends FrameLayout {
v.getLocationOnScreen(mTmpXY);
return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
}
public static class LayoutParams extends FrameLayout.LayoutParams {
public int x, y;
public boolean customPosition = false;
/**
* {@inheritDoc}
*/
public LayoutParams(int width, int height) {
super(width, height);
}
public void setWidth(int width) {
this.width = width;
}
public int getWidth() {
return width;
}
public void setHeight(int height) {
this.height = height;
}
public int getHeight() {
return height;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
if (flp instanceof LayoutParams) {
final LayoutParams lp = (LayoutParams) flp;
if (lp.customPosition) {
child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
}
}
}
}
public void clearAllResizeFrames() {
if (mResizeFrames.size() > 0) {
for (AppWidgetResizeFrame frame: mResizeFrames) {
removeView(frame);
}
mResizeFrames.clear();
}
}
public boolean hasResizeFrames() {
return mResizeFrames.size() > 0;
}
public boolean isWidgetBeingResized() {
return mCurrentResizeFrame != null;
}
public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
CellLayout cellLayout) {
AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
itemInfo, widget, cellLayout, this);
LayoutParams lp = new LayoutParams(-1, -1);
lp.customPosition = true;
addView(resizeFrame, lp);
mResizeFrames.add(resizeFrame);
resizeFrame.snapToWidget(false);
}
}

View File

@ -1800,8 +1800,8 @@ public class Workspace extends SmoothPagedView
}
public void exitWidgetResizeMode() {
final CellLayout currentLayout = (CellLayout) getChildAt(getCurrentPage());
currentLayout.getChildrenLayout().clearAllResizeFrames();
DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
dragLayer.clearAllResizeFrames();
}
void unshrink(boolean animated) {
@ -2353,7 +2353,6 @@ public class Workspace extends SmoothPagedView
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
if (cell instanceof LauncherAppWidgetHostView) {
final CellLayoutChildren children = dropTargetLayout.getChildrenLayout();
final CellLayout cellLayout = dropTargetLayout;
// We post this call so that the widget has a chance to be placed
// in its final location
@ -2363,7 +2362,9 @@ public class Workspace extends SmoothPagedView
if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
post(new Runnable() {
public void run() {
children.addResizeFrame(info, hostView,
DragLayer dragLayer = (DragLayer)
mLauncher.findViewById(R.id.drag_layer);
dragLayer.addResizeFrame(info, hostView,
cellLayout);
}
});