Defining various modes for CellLayout: Workspace, Hotseat & Folder

> Moving the definition of modes to xml
> Defining attributes in xml

Change-Id: I7a569fdbeb833d569eeeef2f2cbc8214e608ad11
This commit is contained in:
Sunny Goyal 2016-11-18 23:44:48 -08:00
parent aa8a871e33
commit c13403c612
13 changed files with 114 additions and 91 deletions

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.launcher3.CellLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hapticFeedbackEnabled="false"
android:importantForAccessibility="no"
launcher:containerType="folder" />

View File

@ -20,5 +20,6 @@
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center" />
android:layout_gravity="center"
launcher:containerType="hotseat" />
</com.android.launcher3.Hotseat>

View File

@ -19,4 +19,5 @@
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hapticFeedbackEnabled="false" />
android:hapticFeedbackEnabled="false"
launcher:containerType="workspace" />

View File

@ -112,4 +112,12 @@
<attr name="defaultLayoutId" format="reference" />
</declare-styleable>
<declare-styleable name="CellLayout">
<attr name="containerType" format="integer">
<enum name="workspace" value="0" />
<enum name="hotseat" value="1" />
<enum name="folder" value="2" />
</attr>
</declare-styleable>
</resources>

View File

@ -24,6 +24,7 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@ -35,6 +36,7 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Build;
import android.os.Parcelable;
import android.support.annotation.IntDef;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
@ -60,6 +62,8 @@ import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Thunk;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -145,8 +149,16 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
private TimeInterpolator mEaseOutInterpolator;
private ShortcutAndWidgetContainer mShortcutsAndWidgets;
private boolean mIsHotseat = false;
private float mHotseatScale = 1f;
@Retention(RetentionPolicy.SOURCE)
@IntDef({WORKSPACE, HOTSEAT, FOLDER})
public @interface ContainerType{}
public static final int WORKSPACE = 0;
public static final int HOTSEAT = 1;
public static final int FOLDER = 2;
@ContainerType private final int mContainerType;
private final float mChildScale;
public static final int MODE_SHOW_REORDER_HINT = 0;
public static final int MODE_DRAG_OVER = 1;
@ -158,7 +170,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
private static final float REORDER_PREVIEW_MAGNITUDE = 0.12f;
private static final int REORDER_ANIMATION_DURATION = 150;
@Thunk float mReorderPreviewAnimationMagnitude;
@Thunk final float mReorderPreviewAnimationMagnitude;
private ArrayList<View> mIntersectingViews = new ArrayList<View>();
private Rect mOccupiedRect = new Rect();
@ -184,6 +196,9 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
public CellLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0);
mContainerType = a.getInteger(R.styleable.CellLayout_containerType, WORKSPACE);
a.recycle();
// A ViewGroup usually does not draw, but CellLayout needs to draw a rectangle to show
// the user where a dragged item will land when dropped.
@ -207,9 +222,10 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mFolderLeaveBehind.delegateCellX = -1;
mFolderLeaveBehind.delegateCellY = -1;
mChildScale = mContainerType == HOTSEAT ? grid.inv.hotseatScale : 1f;
setAlwaysDrawnWithCacheEnabled(false);
final Resources res = getResources();
mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx;
mBackground = (TransitionDrawable) res.getDrawable(
FeatureFlags.LAUNCHER3_LEGACY_WORKSPACE_DND ? R.drawable.bg_screenpanel
@ -217,8 +233,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mBackground.setCallback(this);
mBackground.setAlpha((int) (mBackgroundAlpha * 255));
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE *
grid.iconSizePx);
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * grid.iconSizePx);
// Initialize the data structures used for the drag visualization.
mEaseOutInterpolator = new DecelerateInterpolator(2.5f); // Quint ease out
@ -276,7 +291,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mDragOutlineAnims[i] = anim;
}
mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context);
mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context, mContainerType);
mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
@ -355,10 +370,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mShortcutsAndWidgets.buildLayer();
}
public float getChildrenScale() {
return mIsHotseat ? mHotseatScale : 1.0f;
}
public void setCellDimensions(int width, int height) {
mFixedCellWidth = mCellWidth = width;
mFixedCellHeight = mCellHeight = height;
@ -603,15 +614,8 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
return mCountY;
}
public void setIsHotseat(boolean isHotseat) {
mIsHotseat = isHotseat;
mShortcutsAndWidgets.setContainerType(isHotseat
? ShortcutAndWidgetContainer.HOTSEAT
: ShortcutAndWidgetContainer.DEFAULT);
}
public boolean isHotseat() {
return mIsHotseat;
public boolean acceptsWidget() {
return mContainerType == WORKSPACE;
}
public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params,
@ -621,11 +625,11 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
// Hotseat icons - remove text
if (child instanceof BubbleTextView) {
BubbleTextView bubbleChild = (BubbleTextView) child;
bubbleChild.setTextVisibility(!mIsHotseat);
bubbleChild.setTextVisibility(mContainerType != HOTSEAT);
}
child.setScaleX(getChildrenScale());
child.setScaleY(getChildrenScale());
child.setScaleX(mChildScale);
child.setScaleY(mChildScale);
// Generate an id for each view, this assumes we have at most 256x256 cells
// per workspace screen
@ -1061,24 +1065,26 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
r.set(left, top, left + dragOutline.getWidth(), top + dragOutline.getHeight());
}
Utilities.scaleRectAboutCenter(r, getChildrenScale());
Utilities.scaleRectAboutCenter(r, mChildScale);
mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline);
mDragOutlineAnims[mDragOutlineCurrent].animateIn();
if (dragObject.stateAnnouncer != null) {
String msg;
if (isHotseat()) {
msg = getContext().getString(R.string.move_to_hotseat_position,
Math.max(cellX, cellY) + 1);
} else {
msg = getContext().getString(R.string.move_to_empty_cell,
cellY + 1, cellX + 1);
}
dragObject.stateAnnouncer.announce(msg);
dragObject.stateAnnouncer.announce(getItemMoveDescription(cellX, cellY));
}
}
}
public String getItemMoveDescription(int cellX, int cellY) {
if (mContainerType == HOTSEAT) {
return getContext().getString(R.string.move_to_hotseat_position,
Math.max(cellX, cellY) + 1);
} else {
return getContext().getString(R.string.move_to_empty_cell,
cellY + 1, cellX + 1);
}
}
public void clearDragOutlines() {
final int oldIndex = mDragOutlineCurrent;
mDragOutlineAnims[oldIndex].animateOut();
@ -2011,7 +2017,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
this.mode = mode;
initDeltaX = child.getTranslationX();
initDeltaY = child.getTranslationY();
finalScale = getChildrenScale() - 4.0f / child.getWidth();
finalScale = mChildScale - 4.0f / child.getWidth();
initScale = child.getScaleX();
this.child = child;
}
@ -2061,7 +2067,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
// We make sure to end only after a full period
initDeltaX = 0;
initDeltaY = 0;
initScale = getChildrenScale();
initScale = mChildScale;
repeating = true;
}
});
@ -2081,8 +2087,8 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
}
a = new LauncherViewPropertyAnimator(child)
.scaleX(getChildrenScale())
.scaleY(getChildrenScale())
.scaleX(mChildScale)
.scaleY(mChildScale)
.translationX(0)
.translationY(0)
.setDuration(REORDER_ANIMATION_DURATION);
@ -2104,7 +2110,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
long screenId = mLauncher.getWorkspace().getIdForScreen(this);
int container = Favorites.CONTAINER_DESKTOP;
if (mLauncher.isHotseatLayout(this)) {
if (mContainerType == HOTSEAT) {
screenId = -1;
container = Favorites.CONTAINER_HOTSEAT;
}
@ -2127,7 +2133,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
info.spanY = lp.cellVSpan;
if (requiresDbUpdate) {
LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId,
LauncherModel.modifyItemInDatabase(getContext(), info, container, screenId,
info.cellX, info.cellY, info.spanX, info.spanY);
}
}

View File

@ -29,6 +29,7 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.config.FeatureFlags;
import java.util.ArrayList;
@ -610,6 +611,19 @@ public class DeviceProfile {
: Math.max(widthPx, heightPx);
}
public int getCellHeight(@ContainerType int containerType) {
switch (containerType) {
case CellLayout.WORKSPACE:
return cellHeightPx;
case CellLayout.FOLDER:
return folderCellHeightPx;
case CellLayout.HOTSEAT:
return hotseatCellHeightPx;
default:
// ??
return 0;
}
}
/**
* @return the left/right paddings for all containers.

View File

@ -113,12 +113,11 @@ public class Hotseat extends FrameLayout
super.onFinishInflate();
DeviceProfile grid = mLauncher.getDeviceProfile();
mContent = (CellLayout) findViewById(R.id.layout);
if (grid.isLandscape && !grid.isLargeTablet) {
mContent.setGridSize(1, (int) grid.inv.numHotseatIcons);
if (grid.isVerticalBarLayout()) {
mContent.setGridSize(1, grid.inv.numHotseatIcons);
} else {
mContent.setGridSize((int) grid.inv.numHotseatIcons, 1);
mContent.setGridSize(grid.inv.numHotseatIcons, 1);
}
mContent.setIsHotseat(true);
resetLayout();
}

View File

@ -85,6 +85,7 @@ public class InvariantDeviceProfile {
*/
public int numHotseatIcons;
float hotseatIconSize;
public float hotseatScale;
int defaultLayoutId;
DeviceProfile landscapeProfile;
@ -117,6 +118,8 @@ public class InvariantDeviceProfile {
numHotseatIcons = hs;
hotseatIconSize = his;
defaultLayoutId = dlId;
hotseatScale = hotseatIconSize / iconSize;
}
@TargetApi(23)
@ -158,6 +161,8 @@ public class InvariantDeviceProfile {
// Supported overrides: numRows, numColumns, iconSize
applyPartnerDeviceProfileOverrides(context, dm);
hotseatScale = hotseatIconSize / iconSize;
Point realSize = new Point();
display.getRealSize(realSize);
// The real size never changes. smallSide and largeSide will remain the

View File

@ -2784,6 +2784,7 @@ public class Launcher extends Activity
}
boolean isHotseatLayout(View layout) {
// TODO: Remove this method
return mHotseat != null && layout != null &&
(layout instanceof CellLayout) && (layout == mHotseat.getLayout());
}

View File

@ -19,29 +19,19 @@ package com.android.launcher3;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.IntDef;
import android.view.View;
import android.view.ViewGroup;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.android.launcher3.CellLayout.ContainerType;
public class ShortcutAndWidgetContainer extends ViewGroup {
static final String TAG = "ShortcutAndWidgetContainer";
@Retention(RetentionPolicy.SOURCE)
@IntDef({DEFAULT, HOTSEAT, FOLDER})
public @interface ContainerType{}
public static final int DEFAULT = 0;
public static final int HOTSEAT = 1;
public static final int FOLDER = 2;
private int mContainerType = DEFAULT;
// These are temporary variables to prevent having to allocate a new object just to
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private final int[] mTmpCellXY = new int[2];
@ContainerType private final int mContainerType;
private final WallpaperManager mWallpaperManager;
private int mCellWidth;
@ -50,13 +40,13 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
private int mCountX;
private Launcher mLauncher;
private boolean mInvertIfRtl = false;
public ShortcutAndWidgetContainer(Context context) {
public ShortcutAndWidgetContainer(Context context, @ContainerType int containerType) {
super(context);
mLauncher = Launcher.getLauncher(context);
mWallpaperManager = WallpaperManager.getInstance(context);
mContainerType = containerType;
}
public void setCellDimensions(int cellWidth, int cellHeight, int countX, int countY) {
@ -104,19 +94,9 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
mInvertIfRtl = invert;
}
public void setContainerType(@ContainerType int containerType) {
mContainerType = containerType;
}
int getCellContentHeight() {
final DeviceProfile grid = mLauncher.getDeviceProfile();
int cellContentHeight = grid.cellHeightPx;
if (mContainerType == HOTSEAT) {
cellContentHeight = grid.hotseatCellHeightPx;
} else if (mContainerType == FOLDER) {
cellContentHeight = grid.folderCellHeightPx;
}
return Math.min(getMeasuredHeight(), cellContentHeight);
return Math.min(getMeasuredHeight(),
mLauncher.getDeviceProfile().getCellHeight(mContainerType));
}
public void measureChild(View child) {

View File

@ -57,7 +57,7 @@ public class WorkspaceAccessibilityHelper extends DragAndDropAccessibilityDelega
int y = id / mCountX;
LauncherAccessibilityDelegate.DragInfo dragInfo = mDelegate.getDragInfo();
if (dragInfo.dragType == DragType.WIDGET && mView.isHotseat()) {
if (dragInfo.dragType == DragType.WIDGET && !mView.acceptsWidget()) {
return INVALID_POSITION;
}
@ -161,11 +161,7 @@ public class WorkspaceAccessibilityHelper extends DragAndDropAccessibilityDelega
View child = mView.getChildAt(x, y);
if (child == null || child == dragInfo.item) {
if (mView.isHotseat()) {
return mContext.getString(R.string.move_to_hotseat_position, id + 1);
} else {
return mContext.getString(R.string.move_to_empty_cell, y + 1, x + 1);
}
return mView.getItemMoveDescription(x, y);
} else {
return getDescriptionForDropOver(child, mContext);
}

View File

@ -253,11 +253,9 @@ public class FolderPagedView extends PagedView {
private CellLayout createAndAddNewPage() {
DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
CellLayout page = new CellLayout(getContext());
CellLayout page = (CellLayout) mInflater.inflate(R.layout.folder_page, this, false);
page.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx);
page.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
page.getShortcutsAndWidgets().setContainerType(ShortcutAndWidgetContainer.FOLDER);
page.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
page.setInvertIfRtl(true);
page.setGridSize(mGridCountX, mGridCountY);

View File

@ -29,11 +29,9 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.SimpleOnStylusPressListener;
import com.android.launcher3.R;
import com.android.launcher3.SimpleOnStylusPressListener;
import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest;
@ -182,14 +180,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
ensurePreview();
}
public int getActualItemWidth() {
ItemInfo info = (ItemInfo) getTag();
int[] size = getPreviewSize();
int cellWidth = mLauncher.getDeviceProfile().cellWidthPx;
return Math.min(size[0], info.spanX * cellWidth);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = super.onTouchEvent(ev);