Merge "Refactoring folder content" into ub-launcher3-burnaby
This commit is contained in:
+35
-26
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||
<!--
|
||||
Copyright (C) 2008 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.
|
||||
@@ -14,42 +15,50 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.android.launcher3.Folder
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.android.launcher3.Folder 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:orientation="vertical"
|
||||
android:background="@drawable/quantum_panel">
|
||||
android:background="@drawable/quantum_panel"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scroll_view"
|
||||
<FrameLayout
|
||||
android:id="@+id/folder_content_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.android.launcher3.CellLayout
|
||||
android:id="@+id/folder_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:cacheColorHint="#ff333333"
|
||||
android:hapticFeedbackEnabled="false" />
|
||||
</ScrollView>
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
<!-- Actual size of the indicator doesn't matter as it is scaled to match the view size -->
|
||||
|
||||
<com.android.launcher3.FocusIndicatorView
|
||||
android:id="@+id/focus_indicator"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp" />
|
||||
|
||||
<com.android.launcher3.FolderCellLayout
|
||||
android:id="@+id/folder_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:cacheColorHint="#ff333333"
|
||||
android:hapticFeedbackEnabled="false" />
|
||||
</FrameLayout>
|
||||
|
||||
<com.android.launcher3.FolderEditText
|
||||
android:id="@+id/folder_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:paddingTop="@dimen/folder_name_padding"
|
||||
android:paddingBottom="@dimen/folder_name_padding"
|
||||
android:background="#00000000"
|
||||
android:hint="@string/folder_hint_text"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#ff777777"
|
||||
android:textColorHint="#ff808080"
|
||||
android:textColorHighlight="#ffCCCCCC"
|
||||
android:textCursorDrawable="@null"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:gravity="center_horizontal"
|
||||
android:singleLine="true"
|
||||
android:hint="@string/folder_hint_text"
|
||||
android:imeOptions="flagNoExtractUi"
|
||||
android:fontFamily="sans-serif-condensed"/>
|
||||
</com.android.launcher3.Folder>
|
||||
android:paddingBottom="@dimen/folder_name_padding"
|
||||
android:paddingTop="@dimen/folder_name_padding"
|
||||
android:singleLine="true"
|
||||
android:textColor="#ff777777"
|
||||
android:textColorHighlight="#ffCCCCCC"
|
||||
android:textColorHint="#ff808080"
|
||||
android:textCursorDrawable="@null"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</com.android.launcher3.Folder>
|
||||
@@ -22,7 +22,6 @@ import android.view.KeyEvent;
|
||||
import android.view.SoundEffectConstants;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import com.android.launcher3.util.FocusLogic;
|
||||
|
||||
@@ -398,8 +397,7 @@ public class FocusHelper {
|
||||
// Initialize the variables.
|
||||
ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
|
||||
final CellLayout layout = (CellLayout) parent.getParent();
|
||||
final ScrollView scrollView = (ScrollView) layout.getParent();
|
||||
final Folder folder = (Folder) scrollView.getParent();
|
||||
final Folder folder = (Folder) layout.getParent().getParent();
|
||||
View title = folder.mFolderName;
|
||||
Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
|
||||
final int countX = layout.getCountX();
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TabWidget;
|
||||
|
||||
public class FocusOnlyTabWidget extends TabWidget {
|
||||
public FocusOnlyTabWidget(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public View getSelectedTab() {
|
||||
final int count = getTabCount();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
View v = getChildTabViewAt(i);
|
||||
if (v.isSelected()) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getChildTabIndex(View v) {
|
||||
final int tabCount = getTabCount();
|
||||
for (int i = 0; i < tabCount; ++i) {
|
||||
if (getChildTabViewAt(i) == v) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setCurrentTabToFocusedTab() {
|
||||
View tab = null;
|
||||
int index = -1;
|
||||
final int count = getTabCount();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
View v = getChildTabViewAt(i);
|
||||
if (v.hasFocus()) {
|
||||
tab = v;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index > -1) {
|
||||
super.setCurrentTab(index);
|
||||
super.onFocusChange(tab, true);
|
||||
}
|
||||
}
|
||||
public void superOnFocusChange(View v, boolean hasFocus) {
|
||||
super.onFocusChange(v, hasFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChange(android.view.View v, boolean hasFocus) {
|
||||
if (v == this && hasFocus && getTabCount() > 0) {
|
||||
getSelectedTab().requestFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,6 @@ import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.FolderInfo.FolderListener;
|
||||
@@ -61,64 +60,65 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
View.OnFocusChangeListener {
|
||||
private static final String TAG = "Launcher.Folder";
|
||||
|
||||
protected DragController mDragController;
|
||||
protected Launcher mLauncher;
|
||||
protected FolderInfo mInfo;
|
||||
/**
|
||||
* We avoid measuring {@link #mContentWrapper} with a 0 width or height, as this
|
||||
* results in CellLayout being measured as UNSPECIFIED, which it does not support.
|
||||
*/
|
||||
private static final int MIN_CONTENT_DIMEN = 5;
|
||||
|
||||
static final int STATE_NONE = -1;
|
||||
static final int STATE_SMALL = 0;
|
||||
static final int STATE_ANIMATING = 1;
|
||||
static final int STATE_OPEN = 2;
|
||||
|
||||
private int mExpandDuration;
|
||||
private int mMaterialExpandDuration;
|
||||
private int mMaterialExpandStagger;
|
||||
protected CellLayout mContent;
|
||||
private ScrollView mScrollView;
|
||||
private final LayoutInflater mInflater;
|
||||
private final IconCache mIconCache;
|
||||
private int mState = STATE_NONE;
|
||||
private static final int REORDER_ANIMATION_DURATION = 230;
|
||||
private static final int REORDER_DELAY = 250;
|
||||
private static final int ON_EXIT_CLOSE_DELAY = 400;
|
||||
private boolean mRearrangeOnClose = false;
|
||||
private static final Rect sTempRect = new Rect();
|
||||
|
||||
private static String sDefaultFolderName;
|
||||
private static String sHintText;
|
||||
|
||||
private final Alarm mReorderAlarm = new Alarm();
|
||||
private final Alarm mOnExitAlarm = new Alarm();
|
||||
|
||||
private final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
|
||||
|
||||
private final int mExpandDuration;
|
||||
private final int mMaterialExpandDuration;
|
||||
private final int mMaterialExpandStagger;
|
||||
|
||||
private final InputMethodManager mInputMethodManager;
|
||||
|
||||
protected final Launcher mLauncher;
|
||||
protected DragController mDragController;
|
||||
protected FolderInfo mInfo;
|
||||
|
||||
private FolderIcon mFolderIcon;
|
||||
private int mMaxCountX;
|
||||
private int mMaxCountY;
|
||||
private int mMaxNumItems;
|
||||
private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
|
||||
|
||||
private FolderCellLayout mContent;
|
||||
private View mContentWrapper;
|
||||
FolderEditText mFolderName;
|
||||
|
||||
private View mBottomContent;
|
||||
private int mBottomContentHeight;
|
||||
|
||||
// Cell ranks used for drag and drop
|
||||
private int mTargetRank, mPrevTargetRank, mEmptyCellRank;
|
||||
|
||||
private int mState = STATE_NONE;
|
||||
private boolean mRearrangeOnClose = false;
|
||||
boolean mItemsInvalidated = false;
|
||||
private ShortcutInfo mCurrentDragInfo;
|
||||
private View mCurrentDragView;
|
||||
private boolean mIsExternalDrag;
|
||||
boolean mSuppressOnAdd = false;
|
||||
private int[] mTargetCell = new int[2];
|
||||
private int[] mPreviousTargetCell = new int[2];
|
||||
private int[] mEmptyCell = new int[2];
|
||||
private Alarm mReorderAlarm = new Alarm();
|
||||
private Alarm mOnExitAlarm = new Alarm();
|
||||
private int mFolderNameHeight;
|
||||
private Rect mTempRect = new Rect();
|
||||
private boolean mDragInProgress = false;
|
||||
private boolean mDeleteFolderOnDropCompleted = false;
|
||||
private boolean mSuppressFolderDeletion = false;
|
||||
private boolean mItemAddedBackToSelfViaIcon = false;
|
||||
FolderEditText mFolderName;
|
||||
private float mFolderIconPivotX;
|
||||
private float mFolderIconPivotY;
|
||||
|
||||
private boolean mIsEditingName = false;
|
||||
private InputMethodManager mInputMethodManager;
|
||||
|
||||
private static String sDefaultFolderName;
|
||||
private static String sHintText;
|
||||
|
||||
private FocusIndicatorView mFocusIndicatorHandler;
|
||||
|
||||
// We avoid measuring the scroll view with a 0 width or height, as this
|
||||
// results in CellLayout being measured as UNSPECIFIED, which it does
|
||||
// not support.
|
||||
private static final int MIN_CONTENT_DIMEN = 5;
|
||||
|
||||
private boolean mDestroyed;
|
||||
|
||||
@@ -130,25 +130,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
* Used to inflate the Workspace from XML.
|
||||
*
|
||||
* @param context The application's context.
|
||||
* @param attrs The attribtues set containing the Workspace's customization values.
|
||||
* @param attrs The attributes set containing the Workspace's customization values.
|
||||
*/
|
||||
public Folder(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
setAlwaysDrawnWithCacheEnabled(false);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mIconCache = app.getIconCache();
|
||||
|
||||
Resources res = getResources();
|
||||
mMaxCountX = (int) grid.numColumns;
|
||||
mMaxCountY = (int) grid.numRows;
|
||||
mMaxNumItems = mMaxCountX * mMaxCountY;
|
||||
|
||||
mInputMethodManager = (InputMethodManager)
|
||||
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
|
||||
Resources res = getResources();
|
||||
mExpandDuration = res.getInteger(R.integer.config_folderExpandDuration);
|
||||
mMaterialExpandDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
|
||||
mMaterialExpandStagger = res.getInteger(R.integer.config_materialFolderExpandStagger);
|
||||
@@ -162,20 +152,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
mLauncher = (Launcher) context;
|
||||
// We need this view to be focusable in touch mode so that when text editing of the folder
|
||||
// name is complete, we have something to focus on, thus hiding the cursor and giving
|
||||
// reliable behvior when clicking the text field (since it will always gain focus on click).
|
||||
// reliable behavior when clicking the text field (since it will always gain focus on click).
|
||||
setFocusableInTouchMode(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mScrollView = (ScrollView) findViewById(R.id.scroll_view);
|
||||
mContent = (CellLayout) findViewById(R.id.folder_content);
|
||||
|
||||
mFocusIndicatorHandler = new FocusIndicatorView(getContext());
|
||||
mContent.addView(mFocusIndicatorHandler, 0);
|
||||
mFocusIndicatorHandler.getLayoutParams().height = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
|
||||
mFocusIndicatorHandler.getLayoutParams().width = FocusIndicatorView.DEFAULT_LAYOUT_SIZE;
|
||||
mContentWrapper = findViewById(R.id.folder_content_wrapper);
|
||||
mContent = (FolderCellLayout) findViewById(R.id.folder_content);
|
||||
mContent.setFolder(this);
|
||||
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
@@ -184,22 +170,25 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
mContent.setGridSize(0, 0);
|
||||
mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false);
|
||||
mContent.setInvertIfRtl(true);
|
||||
|
||||
mFolderName = (FolderEditText) findViewById(R.id.folder_name);
|
||||
mFolderName.setFolder(this);
|
||||
mFolderName.setOnFocusChangeListener(this);
|
||||
|
||||
// We find out how tall the text view wants to be (it is set to wrap_content), so that
|
||||
// we can allocate the appropriate amount of space for it.
|
||||
int measureSpec = MeasureSpec.UNSPECIFIED;
|
||||
mFolderName.measure(measureSpec, measureSpec);
|
||||
mFolderNameHeight = mFolderName.getMeasuredHeight();
|
||||
|
||||
// We disable action mode for now since it messes up the view on phones
|
||||
mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback);
|
||||
mFolderName.setOnEditorActionListener(this);
|
||||
mFolderName.setSelectAllOnFocus(true);
|
||||
mFolderName.setInputType(mFolderName.getInputType() |
|
||||
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
|
||||
|
||||
// We only have the folder name at the bottom for now
|
||||
mBottomContent = mFolderName;
|
||||
// We find out how tall the bottom content wants to be (it is set to wrap_content), so that
|
||||
// we can allocate the appropriate amount of space for it.
|
||||
int measureSpec = MeasureSpec.UNSPECIFIED;
|
||||
mBottomContent.measure(measureSpec, measureSpec);
|
||||
mBottomContentHeight = mBottomContent.getMeasuredHeight();
|
||||
}
|
||||
|
||||
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
|
||||
@@ -240,8 +229,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
mLauncher.getWorkspace().beginDragShared(v, this);
|
||||
|
||||
mCurrentDragInfo = item;
|
||||
mEmptyCell[0] = item.cellX;
|
||||
mEmptyCell[1] = item.cellY;
|
||||
mEmptyCellRank = item.rank;
|
||||
mCurrentDragView = v;
|
||||
|
||||
mContent.removeView(mCurrentDragView);
|
||||
@@ -298,10 +286,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
return mFolderName;
|
||||
}
|
||||
|
||||
public CellLayout getContent() {
|
||||
return mContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to handle touch events to prevent them from falling through to the workspace below.
|
||||
*/
|
||||
@@ -314,7 +298,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
mDragController = dragController;
|
||||
}
|
||||
|
||||
void setFolderIcon(FolderIcon icon) {
|
||||
public void setFolderIcon(FolderIcon icon) {
|
||||
mFolderIcon = icon;
|
||||
}
|
||||
|
||||
@@ -334,30 +318,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
void bind(FolderInfo info) {
|
||||
mInfo = info;
|
||||
ArrayList<ShortcutInfo> children = info.contents;
|
||||
ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>();
|
||||
|
||||
final int totalChildren = children.size();
|
||||
setupContentForNumItems(totalChildren);
|
||||
|
||||
// Arrange children in the grid based on the rank.
|
||||
Collections.sort(children, Utilities.RANK_COMPARATOR);
|
||||
final int countX = mContent.getCountX();
|
||||
|
||||
int visibleChildren = 0;
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
ShortcutInfo child = children.get(i);
|
||||
child.cellX = i % countX;
|
||||
child.cellY = i / countX;
|
||||
|
||||
if (createAndAddShortcut(child) == null) {
|
||||
overflow.add(child);
|
||||
} else {
|
||||
visibleChildren++;
|
||||
}
|
||||
}
|
||||
|
||||
// We rearrange the items in case there are any empty gaps
|
||||
setupContentForNumItems(visibleChildren);
|
||||
ArrayList<ShortcutInfo> overflow = mContent.bindItems(children);
|
||||
|
||||
// If our folder has too many items we prune them from the list. This is an issue
|
||||
// when upgrading from the old Folders implementation which could contain an unlimited
|
||||
@@ -367,6 +330,14 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
LauncherModel.deleteItemFromDatabase(mLauncher, item);
|
||||
}
|
||||
|
||||
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
|
||||
if (lp == null) {
|
||||
lp = new DragLayer.LayoutParams(0, 0);
|
||||
lp.customPosition = true;
|
||||
setLayoutParams(lp);
|
||||
}
|
||||
centerAboutIcon();
|
||||
|
||||
mItemsInvalidated = true;
|
||||
updateTextViewFocus();
|
||||
mInfo.addListener(this);
|
||||
@@ -470,8 +441,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
iconsAlpha.setStartDelay(mMaterialExpandStagger);
|
||||
iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
|
||||
|
||||
mFolderName.setAlpha(0f);
|
||||
Animator textAlpha = LauncherAnimUtils.ofFloat(mFolderName, "alpha", 0f, 1f);
|
||||
mBottomContent.setAlpha(0f);
|
||||
Animator textAlpha = LauncherAnimUtils.ofFloat(mBottomContent, "alpha", 0f, 1f);
|
||||
textAlpha.setDuration(mMaterialExpandDuration);
|
||||
textAlpha.setStartDelay(mMaterialExpandStagger);
|
||||
textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
|
||||
@@ -524,14 +495,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
}
|
||||
|
||||
public void beginExternalDrag(ShortcutInfo item) {
|
||||
setupContentForNumItems(getItemCount() + 1);
|
||||
findAndSetEmptyCells(item);
|
||||
|
||||
mCurrentDragInfo = item;
|
||||
mEmptyCell[0] = item.cellX;
|
||||
mEmptyCell[1] = item.cellY;
|
||||
mEmptyCellRank = mContent.allocateNewLastItemRank();
|
||||
mIsExternalDrag = true;
|
||||
|
||||
mDragInProgress = true;
|
||||
}
|
||||
|
||||
@@ -588,132 +554,34 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
!isFull());
|
||||
}
|
||||
|
||||
protected boolean findAndSetEmptyCells(ShortcutInfo item) {
|
||||
int[] emptyCell = new int[2];
|
||||
if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
|
||||
item.cellX = emptyCell[0];
|
||||
item.cellY = emptyCell[1];
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected View createAndAddShortcut(ShortcutInfo item) {
|
||||
final BubbleTextView textView =
|
||||
(BubbleTextView) mInflater.inflate(R.layout.folder_application, this, false);
|
||||
textView.applyFromShortcutInfo(item, mIconCache, false);
|
||||
|
||||
textView.setOnClickListener(this);
|
||||
textView.setOnLongClickListener(this);
|
||||
textView.setOnFocusChangeListener(mFocusIndicatorHandler);
|
||||
|
||||
// We need to check here to verify that the given item's location isn't already occupied
|
||||
// by another item.
|
||||
if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0
|
||||
|| item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) {
|
||||
// This shouldn't happen, log it.
|
||||
Log.e(TAG, "Folder order not properly persisted during bind");
|
||||
if (!findAndSetEmptyCells(item)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
CellLayout.LayoutParams lp =
|
||||
new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
|
||||
boolean insert = false;
|
||||
textView.setOnKeyListener(new FolderKeyEventListener());
|
||||
mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
|
||||
return textView;
|
||||
}
|
||||
|
||||
public void onDragEnter(DragObject d) {
|
||||
mPreviousTargetCell[0] = -1;
|
||||
mPreviousTargetCell[1] = -1;
|
||||
mPrevTargetRank = -1;
|
||||
mOnExitAlarm.cancelAlarm();
|
||||
}
|
||||
|
||||
OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
|
||||
public void onAlarm(Alarm alarm) {
|
||||
realTimeReorder(mEmptyCell, mTargetCell);
|
||||
mContent.realTimeReorder(mEmptyCellRank, mTargetRank);
|
||||
mEmptyCellRank = mTargetRank;
|
||||
}
|
||||
};
|
||||
|
||||
boolean readingOrderGreaterThan(int[] v1, int[] v2) {
|
||||
if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void realTimeReorder(int[] empty, int[] target) {
|
||||
boolean wrap;
|
||||
int startX;
|
||||
int endX;
|
||||
int startY;
|
||||
int delay = 0;
|
||||
float delayAmount = 30;
|
||||
if (readingOrderGreaterThan(target, empty)) {
|
||||
wrap = empty[0] >= mContent.getCountX() - 1;
|
||||
startY = wrap ? empty[1] + 1 : empty[1];
|
||||
for (int y = startY; y <= target[1]; y++) {
|
||||
startX = y == empty[1] ? empty[0] + 1 : 0;
|
||||
endX = y < target[1] ? mContent.getCountX() - 1 : target[0];
|
||||
for (int x = startX; x <= endX; x++) {
|
||||
View v = mContent.getChildAt(x,y);
|
||||
if (mContent.animateChildToPosition(v, empty[0], empty[1],
|
||||
REORDER_ANIMATION_DURATION, delay, true, true)) {
|
||||
empty[0] = x;
|
||||
empty[1] = y;
|
||||
delay += delayAmount;
|
||||
delayAmount *= 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wrap = empty[0] == 0;
|
||||
startY = wrap ? empty[1] - 1 : empty[1];
|
||||
for (int y = startY; y >= target[1]; y--) {
|
||||
startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1;
|
||||
endX = y > target[1] ? 0 : target[0];
|
||||
for (int x = startX; x >= endX; x--) {
|
||||
View v = mContent.getChildAt(x,y);
|
||||
if (mContent.animateChildToPosition(v, empty[0], empty[1],
|
||||
REORDER_ANIMATION_DURATION, delay, true, true)) {
|
||||
empty[0] = x;
|
||||
empty[1] = y;
|
||||
delay += delayAmount;
|
||||
delayAmount *= 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
public boolean isLayoutRtl() {
|
||||
return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
|
||||
}
|
||||
|
||||
public void onDragOver(DragObject d) {
|
||||
final int scrollOffset = mScrollView.getScrollY();
|
||||
final float[] r = d.getVisualCenter(null);
|
||||
r[0] -= getPaddingLeft();
|
||||
r[1] -= getPaddingTop();
|
||||
|
||||
mTargetCell = mContent.findNearestArea(
|
||||
(int) r[0], (int) r[1] + scrollOffset, 1, 1, mTargetCell);
|
||||
if (isLayoutRtl()) {
|
||||
mTargetCell[0] = mContent.getCountX() - mTargetCell[0] - 1;
|
||||
}
|
||||
if (mTargetCell[0] != mPreviousTargetCell[0]
|
||||
|| mTargetCell[1] != mPreviousTargetCell[1]) {
|
||||
mTargetRank = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1);
|
||||
if (mTargetRank != mPrevTargetRank) {
|
||||
mReorderAlarm.cancelAlarm();
|
||||
mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
|
||||
mReorderAlarm.setAlarm(REORDER_DELAY);
|
||||
mPreviousTargetCell[0] = mTargetCell[0];
|
||||
mPreviousTargetCell[1] = mTargetCell[1];
|
||||
mPrevTargetRank = mTargetRank;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,7 +632,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
replaceFolderWithFinalItem();
|
||||
}
|
||||
} else {
|
||||
setupContentForNumItems(getItemCount());
|
||||
rearrangeChildren();
|
||||
// The drag failed, we need to return the item to the folder
|
||||
mFolderIcon.onDrop(d);
|
||||
}
|
||||
@@ -865,37 +733,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setupContentDimensions(int count) {
|
||||
ArrayList<View> list = getItemsInReadingOrder();
|
||||
|
||||
int countX = mContent.getCountX();
|
||||
int countY = mContent.getCountY();
|
||||
boolean done = false;
|
||||
|
||||
while (!done) {
|
||||
int oldCountX = countX;
|
||||
int oldCountY = countY;
|
||||
if (countX * countY < count) {
|
||||
// Current grid is too small, expand it
|
||||
if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) {
|
||||
countX++;
|
||||
} else if (countY < mMaxCountY) {
|
||||
countY++;
|
||||
}
|
||||
if (countY == 0) countY++;
|
||||
} else if ((countY - 1) * countX >= count && countY >= countX) {
|
||||
countY = Math.max(0, countY - 1);
|
||||
} else if ((countX - 1) * countY >= count) {
|
||||
countX = Math.max(0, countX - 1);
|
||||
}
|
||||
done = countX == oldCountX && countY == oldCountY;
|
||||
}
|
||||
mContent.setGridSize(countX, countY);
|
||||
arrangeChildren(list);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return getItemCount() >= mMaxNumItems;
|
||||
return mContent.isFull();
|
||||
}
|
||||
|
||||
private void centerAboutIcon() {
|
||||
@@ -905,13 +744,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
|
||||
int height = getFolderHeight();
|
||||
|
||||
float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect);
|
||||
float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, sTempRect);
|
||||
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
|
||||
int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2);
|
||||
int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2);
|
||||
int centerX = (int) (sTempRect.left + sTempRect.width() * scale / 2);
|
||||
int centerY = (int) (sTempRect.top + sTempRect.height() * scale / 2);
|
||||
int centeredLeft = centerX - width / 2;
|
||||
int centeredTop = centerY - height / 2;
|
||||
int currentPage = mLauncher.getWorkspace().getNextPage();
|
||||
@@ -964,18 +803,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
return mFolderIconPivotY;
|
||||
}
|
||||
|
||||
private void setupContentForNumItems(int count) {
|
||||
setupContentDimensions(count);
|
||||
|
||||
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
|
||||
if (lp == null) {
|
||||
lp = new DragLayer.LayoutParams(0, 0);
|
||||
lp.customPosition = true;
|
||||
setLayoutParams(lp);
|
||||
}
|
||||
centerAboutIcon();
|
||||
}
|
||||
|
||||
private int getContentAreaHeight() {
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
@@ -983,7 +810,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
|
||||
int maxContentAreaHeight = grid.availableHeightPx -
|
||||
workspacePadding.top - workspacePadding.bottom -
|
||||
mFolderNameHeight;
|
||||
mBottomContentHeight;
|
||||
int height = Math.min(maxContentAreaHeight,
|
||||
mContent.getDesiredHeight());
|
||||
return Math.max(height, MIN_CONTENT_DIMEN);
|
||||
@@ -994,54 +821,52 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
}
|
||||
|
||||
private int getFolderHeight() {
|
||||
int height = getPaddingTop() + getPaddingBottom()
|
||||
+ getContentAreaHeight() + mFolderNameHeight;
|
||||
return height;
|
||||
return getFolderHeight(getContentAreaHeight());
|
||||
}
|
||||
|
||||
private int getFolderHeight(int contentAreaHeight) {
|
||||
return getPaddingTop() + getPaddingBottom() + contentAreaHeight + mBottomContentHeight;
|
||||
}
|
||||
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
|
||||
int height = getFolderHeight();
|
||||
int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(getContentAreaWidth(),
|
||||
MeasureSpec.EXACTLY);
|
||||
int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(),
|
||||
MeasureSpec.EXACTLY);
|
||||
int contentWidth = getContentAreaWidth();
|
||||
int contentHeight = getContentAreaHeight();
|
||||
|
||||
mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight());
|
||||
mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec);
|
||||
mFolderName.measure(contentAreaWidthSpec,
|
||||
MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
|
||||
setMeasuredDimension(width, height);
|
||||
int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY);
|
||||
int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(contentHeight, MeasureSpec.EXACTLY);
|
||||
|
||||
mContent.setFixedSize(contentWidth, contentHeight);
|
||||
mContentWrapper.measure(contentAreaWidthSpec, contentAreaHeightSpec);
|
||||
|
||||
// Move the bottom content below mContent
|
||||
mBottomContent.measure(contentAreaWidthSpec,
|
||||
MeasureSpec.makeMeasureSpec(mBottomContentHeight, MeasureSpec.EXACTLY));
|
||||
|
||||
int folderWidth = getPaddingLeft() + getPaddingRight() + contentWidth;
|
||||
int folderHeight = getFolderHeight(contentHeight);
|
||||
setMeasuredDimension(folderWidth, folderHeight);
|
||||
}
|
||||
|
||||
private void arrangeChildren(ArrayList<View> list) {
|
||||
int[] vacant = new int[2];
|
||||
if (list == null) {
|
||||
list = getItemsInReadingOrder();
|
||||
}
|
||||
mContent.removeAllViews();
|
||||
/**
|
||||
* Rearranges the children based on their rank.
|
||||
*/
|
||||
public void rearrangeChildren() {
|
||||
rearrangeChildren(-1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
View v = list.get(i);
|
||||
mContent.getVacantCell(vacant, 1, 1);
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
|
||||
lp.cellX = vacant[0];
|
||||
lp.cellY = vacant[1];
|
||||
ItemInfo info = (ItemInfo) v.getTag();
|
||||
if (info.cellX != vacant[0] || info.cellY != vacant[1]) {
|
||||
info.cellX = vacant[0];
|
||||
info.cellY = vacant[1];
|
||||
LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
|
||||
info.cellX, info.cellY);
|
||||
}
|
||||
boolean insert = false;
|
||||
mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
|
||||
}
|
||||
/**
|
||||
* Rearranges the children based on their rank.
|
||||
* @param itemCount if greater than the total children count, empty spaces are left at the end,
|
||||
* otherwise it is ignored.
|
||||
*/
|
||||
public void rearrangeChildren(int itemCount) {
|
||||
ArrayList<View> views = getItemsInReadingOrder();
|
||||
mContent.arrangeChildren(views, Math.max(itemCount, views.size()));
|
||||
mItemsInvalidated = true;
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return mContent.getShortcutsAndWidgets().getChildCount();
|
||||
return mContent.getItemCount();
|
||||
}
|
||||
|
||||
public View getItemAt(int index) {
|
||||
@@ -1058,7 +883,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
mFolderIcon.requestFocus();
|
||||
|
||||
if (mRearrangeOnClose) {
|
||||
setupContentForNumItems(getItemCount());
|
||||
rearrangeChildren();
|
||||
mRearrangeOnClose = false;
|
||||
}
|
||||
if (getItemCount() <= 1) {
|
||||
@@ -1153,9 +978,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
View currentDragView;
|
||||
ShortcutInfo si = mCurrentDragInfo;
|
||||
if (mIsExternalDrag) {
|
||||
si.cellX = mEmptyCell[0];
|
||||
si.cellY = mEmptyCell[1];
|
||||
|
||||
currentDragView = mContent.createAndAddViewForRank(si, mEmptyCellRank);
|
||||
// Actually move the item in the database if it was an external drag. Call this
|
||||
// before creating the view, so that ShortcutInfo is updated appropriately.
|
||||
LauncherModel.addOrMoveItemInDatabase(
|
||||
@@ -1166,14 +989,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
updateItemLocationsInDatabaseBatch();
|
||||
}
|
||||
mIsExternalDrag = false;
|
||||
|
||||
currentDragView = createAndAddShortcut(si);
|
||||
} else {
|
||||
currentDragView = mCurrentDragView;
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) currentDragView.getLayoutParams();
|
||||
si.cellX = lp.cellX = mEmptyCell[0];
|
||||
si.cellX = lp.cellY = mEmptyCell[1];
|
||||
mContent.addViewToCellLayout(currentDragView, -1, (int) si.id, lp, true);
|
||||
mContent.addViewForRank(currentDragView, si, mEmptyCellRank);
|
||||
}
|
||||
|
||||
if (d.dragView.hasDrawn()) {
|
||||
@@ -1192,7 +1010,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
currentDragView.setVisibility(VISIBLE);
|
||||
}
|
||||
mItemsInvalidated = true;
|
||||
setupContentDimensions(getItemCount());
|
||||
rearrangeChildren();
|
||||
|
||||
// Temporarily suppress the listener, as we did all the work already here.
|
||||
mSuppressOnAdd = true;
|
||||
@@ -1219,12 +1037,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
// If the item was dropped onto this open folder, we have done the work associated
|
||||
// with adding the item to the folder, as indicated by mSuppressOnAdd being set
|
||||
if (mSuppressOnAdd) return;
|
||||
if (!findAndSetEmptyCells(item)) {
|
||||
// The current layout is full, can we expand it?
|
||||
setupContentForNumItems(getItemCount() + 1);
|
||||
findAndSetEmptyCells(item);
|
||||
}
|
||||
createAndAddShortcut(item);
|
||||
mContent.createAndAddShortcutToEnd(item);
|
||||
LauncherModel.addOrMoveItemInDatabase(
|
||||
mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
|
||||
}
|
||||
@@ -1239,7 +1052,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
||||
if (mState == STATE_ANIMATING) {
|
||||
mRearrangeOnClose = true;
|
||||
} else {
|
||||
setupContentForNumItems(getItemCount());
|
||||
rearrangeChildren();
|
||||
}
|
||||
if (getItemCount() <= 1) {
|
||||
replaceFolderWithFinalItem();
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
package com.android.launcher3;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FolderCellLayout extends CellLayout {
|
||||
|
||||
private static final int REORDER_ANIMATION_DURATION = 230;
|
||||
private static final int START_VIEW_REORDER_DELAY = 30;
|
||||
private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f;
|
||||
|
||||
private static final int[] sTempPosArray = new int[2];
|
||||
|
||||
private final FolderKeyEventListener mKeyListener = new FolderKeyEventListener();
|
||||
private final LayoutInflater mInflater;
|
||||
private final IconCache mIconCache;
|
||||
|
||||
private final int mMaxCountX;
|
||||
private final int mMaxCountY;
|
||||
private final int mMaxNumItems;
|
||||
|
||||
// Indicates the last number of items used to set up the grid size
|
||||
private int mAllocatedContentSize;
|
||||
|
||||
private Folder mFolder;
|
||||
private FocusIndicatorView mFocusIndicatorView;
|
||||
|
||||
public FolderCellLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public FolderCellLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public FolderCellLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
mMaxCountX = (int) grid.numColumns;
|
||||
mMaxCountY = (int) grid.numRows;
|
||||
mMaxNumItems = mMaxCountX * mMaxCountY;
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mIconCache = app.getIconCache();
|
||||
}
|
||||
|
||||
public void setFolder(Folder folder) {
|
||||
mFolder = folder;
|
||||
mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the grid size such that {@param count} items can fit in the grid.
|
||||
* The grid size is calculated such that countY <= countX and countX = ceil(sqrt(count)) while
|
||||
* maintaining the restrictions of {@link #mMaxCountX} & {@link #mMaxCountY}.
|
||||
*/
|
||||
private void setupContentDimensions(int count) {
|
||||
mAllocatedContentSize = count;
|
||||
int countX = getCountX();
|
||||
int countY = getCountY();
|
||||
boolean done = false;
|
||||
|
||||
while (!done) {
|
||||
int oldCountX = countX;
|
||||
int oldCountY = countY;
|
||||
if (countX * countY < count) {
|
||||
// Current grid is too small, expand it
|
||||
if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) {
|
||||
countX++;
|
||||
} else if (countY < mMaxCountY) {
|
||||
countY++;
|
||||
}
|
||||
if (countY == 0) countY++;
|
||||
} else if ((countY - 1) * countX >= count && countY >= countX) {
|
||||
countY = Math.max(0, countY - 1);
|
||||
} else if ((countX - 1) * countY >= count) {
|
||||
countX = Math.max(0, countX - 1);
|
||||
}
|
||||
done = countX == oldCountX && countY == oldCountY;
|
||||
}
|
||||
setGridSize(countX, countY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds items to the layout.
|
||||
* @return list of items that could not be bound, probably because we hit the max size limit.
|
||||
*/
|
||||
public ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> items) {
|
||||
ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>();
|
||||
setupContentDimensions(Math.min(items.size(), mMaxNumItems));
|
||||
|
||||
int countX = getCountX();
|
||||
int rank = 0;
|
||||
for (ShortcutInfo item : items) {
|
||||
if (rank >= mMaxNumItems) {
|
||||
extra.add(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
item.rank = rank;
|
||||
item.cellX = rank % countX;
|
||||
item.cellY = rank / countX;
|
||||
addNewView(item);
|
||||
rank++;
|
||||
}
|
||||
return extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create space for a new item at the end, and returns the rank for that item.
|
||||
* Resizes the content if necessary.
|
||||
*/
|
||||
public int allocateNewLastItemRank() {
|
||||
int rank = getItemCount();
|
||||
mFolder.rearrangeChildren(rank + 1);
|
||||
return rank;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the new item to the end of the grid. Resizes the content if necessary.
|
||||
*/
|
||||
public View createAndAddShortcutToEnd(ShortcutInfo item) {
|
||||
int rank = allocateNewLastItemRank();
|
||||
return createAndAddViewForRank(item, rank);
|
||||
}
|
||||
|
||||
public View createAndAddViewForRank(ShortcutInfo item, int rank) {
|
||||
updateItemXY(item, rank);
|
||||
return addNewView(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param view} to the layout based on {@param rank} and updated the position
|
||||
* related attributes. It assumes that {@param item} is already attached to the view.
|
||||
*/
|
||||
public void addViewForRank(View view, ShortcutInfo item, int rank) {
|
||||
updateItemXY(item, rank);
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
|
||||
lp.cellX = item.cellX;
|
||||
lp.cellY = item.cellY;
|
||||
addViewToCellLayout(view, -1, (int) item.id, lp, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the item cellX and cellY position
|
||||
*/
|
||||
private void updateItemXY(ShortcutInfo item, int rank) {
|
||||
item.rank = rank;
|
||||
int countX = getCountX();
|
||||
item.cellX = rank % countX;
|
||||
item.cellY = rank / countX;
|
||||
}
|
||||
|
||||
private View addNewView(ShortcutInfo item) {
|
||||
final BubbleTextView textView = (BubbleTextView) mInflater.inflate(
|
||||
R.layout.folder_application, getShortcutsAndWidgets(), false);
|
||||
textView.applyFromShortcutInfo(item, mIconCache, false);
|
||||
textView.setOnClickListener(mFolder);
|
||||
textView.setOnLongClickListener(mFolder);
|
||||
textView.setOnFocusChangeListener(mFocusIndicatorView);
|
||||
textView.setOnKeyListener(mKeyListener);
|
||||
|
||||
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(
|
||||
item.cellX, item.cellY, item.spanX, item.spanY);
|
||||
addViewToCellLayout(textView, -1, (int)item.id, lp, true);
|
||||
return textView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refer {@link #findNearestArea(int, int, int, int, View, boolean, int[])}
|
||||
*
|
||||
* @return The rank of a vacant area that can contain this object,
|
||||
* nearest the requested location.
|
||||
*/
|
||||
public int findNearestArea(int pixelX, int pixelY, int spanX, int spanY) {
|
||||
findNearestArea(pixelX, pixelY, spanX, spanY, null, false, sTempPosArray);
|
||||
if (mFolder.isLayoutRtl()) {
|
||||
sTempPosArray[0] = getCountX() - sTempPosArray[0] - 1;
|
||||
}
|
||||
|
||||
// Convert this position to rank.
|
||||
return Math.min(mAllocatedContentSize - 1,
|
||||
sTempPosArray[1] * getCountX() + sTempPosArray[0]);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return getItemCount() >= mMaxNumItems;
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return getShortcutsAndWidgets().getChildCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates position and rank of all the children in the view based.
|
||||
* @param list the ordered list of children.
|
||||
* @param itemCount if greater than the total children count, empty spaces are left at the end.
|
||||
*/
|
||||
public void arrangeChildren(ArrayList<View> list, int itemCount) {
|
||||
setupContentDimensions(itemCount);
|
||||
removeAllViews();
|
||||
|
||||
int newX, newY;
|
||||
int rank = 0;
|
||||
int countX = getCountX();
|
||||
for (View v : list) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
|
||||
newX = rank % countX;
|
||||
newY = rank / countX;
|
||||
ItemInfo info = (ItemInfo) v.getTag();
|
||||
if (info.cellX != newX || info.cellY != newY || info.rank != rank) {
|
||||
info.cellX = newX;
|
||||
info.cellY = newY;
|
||||
info.rank = rank;
|
||||
LauncherModel.addOrMoveItemInDatabase(getContext(), info,
|
||||
mFolder.mInfo.id, 0, info.cellX, info.cellY);
|
||||
}
|
||||
lp.cellX = info.cellX;
|
||||
lp.cellY = info.cellY;
|
||||
rank ++;
|
||||
addViewToCellLayout(v, -1, (int)info.id, lp, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders the items such that the {@param empty} spot moves to {@param target}
|
||||
*/
|
||||
public void realTimeReorder(int empty, int target) {
|
||||
boolean wrap;
|
||||
int startX;
|
||||
int endX;
|
||||
int startY;
|
||||
int delay = 0;
|
||||
float delayAmount = START_VIEW_REORDER_DELAY;
|
||||
|
||||
int countX = getCountX();
|
||||
int emptyX = empty % getCountX();
|
||||
int emptyY = empty / countX;
|
||||
|
||||
int targetX = target % countX;
|
||||
int targetY = target / countX;
|
||||
|
||||
if (target > empty) {
|
||||
wrap = emptyX == countX - 1;
|
||||
startY = wrap ? emptyY + 1 : emptyY;
|
||||
for (int y = startY; y <= targetY; y++) {
|
||||
startX = y == emptyY ? emptyX + 1 : 0;
|
||||
endX = y < targetY ? countX - 1 : targetX;
|
||||
for (int x = startX; x <= endX; x++) {
|
||||
View v = getChildAt(x,y);
|
||||
if (animateChildToPosition(v, emptyX, emptyY,
|
||||
REORDER_ANIMATION_DURATION, delay, true, true)) {
|
||||
emptyX = x;
|
||||
emptyY = y;
|
||||
delay += delayAmount;
|
||||
delayAmount *= VIEW_REORDER_DELAY_FACTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wrap = emptyX == 0;
|
||||
startY = wrap ? emptyY - 1 : emptyY;
|
||||
for (int y = startY; y >= targetY; y--) {
|
||||
startX = y == emptyY ? emptyX - 1 : countX - 1;
|
||||
endX = y > targetY ? 0 : targetX;
|
||||
for (int x = startX; x >= endX; x--) {
|
||||
View v = getChildAt(x,y);
|
||||
if (animateChildToPosition(v, emptyX, emptyY,
|
||||
REORDER_ANIMATION_DURATION, delay, true, true)) {
|
||||
emptyX = x;
|
||||
emptyY = y;
|
||||
delay += delayAmount;
|
||||
delayAmount *= VIEW_REORDER_DELAY_FACTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user