diff options
-rw-r--r-- | res/layout/page_indicator_marker.xml | 4 | ||||
-rw-r--r-- | res/layout/user_folder.xml | 52 | ||||
-rw-r--r-- | res/layout/user_folder_scroll.xml | 106 | ||||
-rw-r--r-- | src/com/android/launcher3/Folder.java | 180 | ||||
-rw-r--r-- | src/com/android/launcher3/FolderCellLayout.java | 330 | ||||
-rw-r--r-- | src/com/android/launcher3/FolderPagedView.java | 129 |
6 files changed, 161 insertions, 640 deletions
diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml index 686d27569..564a95811 100644 --- a/res/layout/page_indicator_marker.xml +++ b/res/layout/page_indicator_marker.xml @@ -16,8 +16,8 @@ <com.android.launcher3.PageIndicatorMarker xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res-auto" - android:layout_width="16dp" - android:layout_height="16dp" + android:layout_width="12dp" + android:layout_height="12dp" android:layout_gravity="center_vertical"> <ImageView android:id="@+id/inactive" diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml index 7a4d5e881..cd3a051ad 100644 --- a/res/layout/user_folder.xml +++ b/res/layout/user_folder.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2008 The Android Open Source Project + Copyright (C) 2015 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. @@ -34,30 +34,44 @@ android:layout_width="20dp" android:layout_height="20dp" /> - <com.android.launcher3.FolderCellLayout + <com.android.launcher3.FolderPagedView android:id="@+id/folder_content" android:layout_width="match_parent" android:layout_height="match_parent" - android:cacheColorHint="#ff333333" - android:hapticFeedbackEnabled="false" /> + launcher:pageIndicator="@+id/folder_page_indicator" /> </FrameLayout> - <com.android.launcher3.FolderEditText - android:id="@+id/folder_name" + <LinearLayout + android:id="@+id/folder_footer" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="#00000000" - android:fontFamily="sans-serif-condensed" - android:gravity="center_horizontal" - android:hint="@string/folder_hint_text" - android:imeOptions="flagNoExtractUi" - 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" /> + android:orientation="vertical" > + + <include + android:id="@+id/folder_page_indicator" + android:layout_width="wrap_content" + android:layout_height="12dp" + android:layout_gravity="center_horizontal" + layout="@layout/page_indicator" /> + + <com.android.launcher3.FolderEditText + android:id="@+id/folder_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:background="#00000000" + android:fontFamily="sans-serif-condensed" + android:gravity="center_horizontal" + android:hint="@string/folder_hint_text" + android:imeOptions="flagNoExtractUi" + 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" /> + </LinearLayout> </com.android.launcher3.Folder>
\ No newline at end of file diff --git a/res/layout/user_folder_scroll.xml b/res/layout/user_folder_scroll.xml deleted file mode 100644 index 12e5097f3..000000000 --- a/res/layout/user_folder_scroll.xml +++ /dev/null @@ -1,106 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2015 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.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:background="@drawable/quantum_panel" - android:orientation="vertical" > - - <FrameLayout - android:id="@+id/folder_content_wrapper" - android:layout_width="match_parent" - 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.FolderPagedView - android:id="@+id/folder_content" - android:layout_width="match_parent" - android:layout_height="match_parent" - launcher:pageIndicator="@+id/folder_page_indicator" /> - </FrameLayout> - - <LinearLayout - android:id="@+id/folder_footer" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:paddingStart="12dp" - android:paddingEnd="8dp" > - - <com.android.launcher3.FolderEditText - android:id="@+id/folder_name" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_weight="1" - android:background="#00000000" - android:fontFamily="sans-serif-condensed" - android:gravity="start" - android:hint="@string/folder_hint_text" - android:imeOptions="flagNoExtractUi" - 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" /> - - <include - android:id="@+id/folder_page_indicator" - android:layout_width="wrap_content" - android:layout_height="12dp" - android:layout_gravity="top" - android:layout_marginTop="5dp" - layout="@layout/page_indicator" /> - - <LinearLayout - android:id="@+id/folder_sort" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_gravity="center_vertical" - android:gravity="end|center_vertical" > - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:text="@string/sort_alphabetical" - android:textColor="#ff777777" - android:textSize="14sp" /> - - <Switch - android:id="@+id/folder_sort_switch" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:clickable="false" - android:duplicateParentState="true" - android:focusable="false" /> - </LinearLayout> - </LinearLayout> - -</com.android.launcher3.Folder>
\ No newline at end of file diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 1e1d1eeb4..0eb1fd8bb 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -69,7 +69,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList * results in CellLayout being measured as UNSPECIFIED, which it does not support. */ private static final int MIN_CONTENT_DIMEN = 5; - private static final boolean ALLOW_FOLDER_SCROLL = true; static final int STATE_NONE = -1; static final int STATE_SMALL = 0; @@ -101,6 +100,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private final Alarm mReorderAlarm = new Alarm(); private final Alarm mOnExitAlarm = new Alarm(); + private final Alarm mOnScrollHintAlarm = new Alarm(); + @Thunk final Alarm mScrollPauseAlarm = new Alarm(); @Thunk final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); @@ -116,7 +117,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Thunk FolderIcon mFolderIcon; - @Thunk FolderContent mContent; + @Thunk FolderPagedView mContent; @Thunk View mContentWrapper; FolderEditText mFolderName; @@ -149,11 +150,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // Folder scrolling private int mScrollAreaOffset; - private Alarm mOnScrollHintAlarm; - @Thunk Alarm mScrollPauseAlarm; - - // TODO: Use {@link #mContent} once {@link #ALLOW_FOLDER_SCROLL} is removed. - @Thunk FolderPagedView mPagedView; @Thunk int mScrollHintDir = DragController.SCROLL_NONE; @Thunk int mCurrentScrollDir = DragController.SCROLL_NONE; @@ -186,18 +182,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // name is complete, we have something to focus on, thus hiding the cursor and giving // reliable behavior when clicking the text field (since it will always gain focus on click). setFocusableInTouchMode(true); - - if (ALLOW_FOLDER_SCROLL) { - mOnScrollHintAlarm = new Alarm(); - mScrollPauseAlarm = new Alarm(); - } } @Override protected void onFinishInflate() { super.onFinishInflate(); mContentWrapper = findViewById(R.id.folder_content_wrapper); - mContent = (FolderContent) findViewById(R.id.folder_content); + mContent = (FolderPagedView) findViewById(R.id.folder_content); mContent.setFolder(this); mFolderName = (FolderEditText) findViewById(R.id.folder_name); @@ -211,16 +202,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mFolderName.setInputType(mFolderName.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); - mFooter = ALLOW_FOLDER_SCROLL ? findViewById(R.id.folder_footer) : mFolderName; + mFooter = findViewById(R.id.folder_footer); + updateFooterHeight(); + } + + public void updateFooterHeight() { // We find out how tall footer 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; mFooter.measure(measureSpec, measureSpec); mFooterHeight = mFooter.getMeasuredHeight(); - - if (ALLOW_FOLDER_SCROLL) { - mPagedView = (FolderPagedView) mContent; - } } private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { @@ -398,8 +389,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList * @return A new UserFolder. */ static Folder fromXml(Context context) { - return (Folder) LayoutInflater.from(context).inflate( - ALLOW_FOLDER_SCROLL ? R.layout.user_folder_scroll : R.layout.user_folder, null); + return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null); } /** @@ -424,12 +414,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void animateOpen() { if (!(getParent() instanceof DragLayer)) return; - if (ALLOW_FOLDER_SCROLL) { - mPagedView.completePendingPageChanges(); - if (!(mDragInProgress && mPagedView.mIsSorted)) { - // Open on the first page. - mPagedView.snapToPageImmediately(0); - } + mContent.completePendingPageChanges(); + if (!(mDragInProgress && mContent.mIsSorted)) { + // Open on the first page. + mContent.snapToPageImmediately(0); } Animator openFolderAnim = null; @@ -533,10 +521,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mDragController.forceTouchMove(); } - if (ALLOW_FOLDER_SCROLL) { - FolderPagedView pages = (FolderPagedView) mContent; - pages.verifyVisibleHighResIcons(pages.getNextPage()); - } + FolderPagedView pages = (FolderPagedView) mContent; + pages.verifyVisibleHighResIcons(pages.getNextPage()); } public void beginExternalDrag(ShortcutInfo item) { @@ -544,7 +530,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mEmptyCellRank = mContent.allocateRankForNewItem(item); mIsExternalDrag = true; mDragInProgress = true; - if (ALLOW_FOLDER_SCROLL && mPagedView.mIsSorted) { + + if (mContent.mIsSorted) { mScrollPauseAlarm.setOnAlarmListener(null); mScrollPauseAlarm.cancelAlarm(); mScrollPauseAlarm.setAlarm(SORTED_STICKY_REORDER_DELAY); @@ -601,11 +588,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void onDragEnter(DragObject d) { mPrevTargetRank = -1; mOnExitAlarm.cancelAlarm(); - if (ALLOW_FOLDER_SCROLL) { - // Get the area offset such that the folder only closes if half the drag icon width - // is outside the folder area - mScrollAreaOffset = d.dragView.getDragRegionWidth() / 2 - d.xOffset; - } + // Get the area offset such that the folder only closes if half the drag icon width + // is outside the folder area + mScrollAreaOffset = d.dragView.getDragRegionWidth() / 2 - d.xOffset; } OnAlarmListener mReorderAlarmListener = new OnAlarmListener() { @@ -632,7 +617,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } @Thunk void onDragOver(DragObject d, int reorderDelay) { - if (ALLOW_FOLDER_SCROLL && mScrollPauseAlarm.alarmPending()) { + if (mScrollPauseAlarm.alarmPending()) { return; } final float[] r = new float[2]; @@ -645,27 +630,23 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mPrevTargetRank = mTargetRank; } - if (!ALLOW_FOLDER_SCROLL) { - return; - } - float x = r[0]; - int currentPage = mPagedView.getNextPage(); + int currentPage = mContent.getNextPage(); - float cellOverlap = mPagedView.getCurrentCellLayout().getCellWidth() + float cellOverlap = mContent.getCurrentCellLayout().getCellWidth() * ICON_OVERSCROLL_WIDTH_FACTOR; boolean isOutsideLeftEdge = x < cellOverlap; boolean isOutsideRightEdge = x > (getWidth() - cellOverlap); - if (currentPage > 0 && (mPagedView.rtlLayout ? isOutsideRightEdge : isOutsideLeftEdge)) { + if (currentPage > 0 && (mContent.rtlLayout ? isOutsideRightEdge : isOutsideLeftEdge)) { showScrollHint(DragController.SCROLL_LEFT, d); - } else if (currentPage < (mPagedView.getPageCount() - 1) - && (mPagedView.rtlLayout ? isOutsideLeftEdge : isOutsideRightEdge)) { + } else if (currentPage < (mContent.getPageCount() - 1) + && (mContent.rtlLayout ? isOutsideLeftEdge : isOutsideRightEdge)) { showScrollHint(DragController.SCROLL_RIGHT, d); } else { mOnScrollHintAlarm.cancelAlarm(); if (mScrollHintDir != DragController.SCROLL_NONE) { - mPagedView.clearScrollHint(); + mContent.clearScrollHint(); mScrollHintDir = DragController.SCROLL_NONE; } } @@ -674,7 +655,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private void showScrollHint(int direction, DragObject d) { // Show scroll hint on the right if (mScrollHintDir != direction) { - mPagedView.showScrollHint(direction); + mContent.showScrollHint(direction); mScrollHintDir = direction; } @@ -714,13 +695,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } mReorderAlarm.cancelAlarm(); - if (ALLOW_FOLDER_SCROLL) { - mOnScrollHintAlarm.cancelAlarm(); - mScrollPauseAlarm.cancelAlarm(); - if (mScrollHintDir != DragController.SCROLL_NONE) { - mPagedView.clearScrollHint(); - mScrollHintDir = DragController.SCROLL_NONE; - } + mOnScrollHintAlarm.cancelAlarm(); + mScrollPauseAlarm.cancelAlarm(); + if (mScrollHintDir != DragController.SCROLL_NONE) { + mContent.clearScrollHint(); + mScrollHintDir = DragController.SCROLL_NONE; } } @@ -1088,21 +1067,19 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList }; } - if (ALLOW_FOLDER_SCROLL) { - // If the icon was dropped while the page was being scrolled, we need to compute - // the target location again such that the icon is placed of the final page. - if (!mPagedView.rankOnCurrentPage(mEmptyCellRank)) { - // Reorder again. - mTargetRank = getTargetRank(d, null); + // If the icon was dropped while the page was being scrolled, we need to compute + // the target location again such that the icon is placed of the final page. + if (!mContent.rankOnCurrentPage(mEmptyCellRank)) { + // Reorder again. + mTargetRank = getTargetRank(d, null); - // Rearrange items immediately. - mReorderAlarmListener.onAlarm(mReorderAlarm); + // Rearrange items immediately. + mReorderAlarmListener.onAlarm(mReorderAlarm); - mOnScrollHintAlarm.cancelAlarm(); - mScrollPauseAlarm.cancelAlarm(); - } - mPagedView.completePendingPageChanges(); + mOnScrollHintAlarm.cancelAlarm(); + mScrollPauseAlarm.cancelAlarm(); } + mContent.completePendingPageChanges(); View currentDragView; ShortcutInfo si = mCurrentDragInfo; @@ -1252,10 +1229,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Override public void onAlarm(Alarm alarm) { if (mCurrentScrollDir == DragController.SCROLL_LEFT) { - mPagedView.scrollLeft(); + mContent.scrollLeft(); mScrollHintDir = DragController.SCROLL_NONE; } else if (mCurrentScrollDir == DragController.SCROLL_RIGHT) { - mPagedView.scrollRight(); + mContent.scrollRight(); mScrollHintDir = DragController.SCROLL_NONE; } else { // This should not happen @@ -1286,69 +1263,4 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList onDragOver(mDragObject, 1); } } - - public static interface FolderContent { - void setFolder(Folder f); - - void removeItem(View v); - - boolean isFull(); - int getItemCount(); - - int getDesiredWidth(); - int getDesiredHeight(); - void setFixedSize(int width, int height); - - /** - * Iterates over all its items in a reading order. - * @return the view for which the operator returned true. - */ - View iterateOverItems(ItemOperator op); - View getLastItem(); - - String getAccessibilityDescription(); - - /** - * Binds items to the layout. - * @return list of items that could not be bound, probably because we hit the max size limit. - */ - ArrayList<ShortcutInfo> bindItems(ArrayList<ShortcutInfo> children); - - /** - * Create space for a new item, and returns the rank for that item. - * Resizes the content if necessary. - */ - int allocateRankForNewItem(ShortcutInfo info); - - View createAndAddViewForRank(ShortcutInfo item, int rank); - - /** - * 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. - */ - void addViewForRank(View view, ShortcutInfo item, int rank); - - /** - * Reorders the items such that the {@param empty} spot moves to {@param target} - */ - void realTimeReorder(int empty, int target); - - /** - * @return the rank of the cell nearest to the provided pixel position. - */ - int findNearestArea(int pixelX, int pixelY); - - /** - * 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. - */ - void arrangeChildren(ArrayList<View> list, int itemCount); - - /** - * Sets the focus on the first visible child. - */ - void setFocusOnFirstChild(); - } } diff --git a/src/com/android/launcher3/FolderCellLayout.java b/src/com/android/launcher3/FolderCellLayout.java deleted file mode 100644 index 8585addd5..000000000 --- a/src/com/android/launcher3/FolderCellLayout.java +++ /dev/null @@ -1,330 +0,0 @@ -/** - * Copyright (C) 2015 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.LayoutInflater; -import android.view.View; - -import com.android.launcher3.Workspace.ItemOperator; - -import java.util.ArrayList; - -public class FolderCellLayout extends CellLayout implements Folder.FolderContent { - - 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(); - - setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx); - getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); - setInvertIfRtl(true); - } - - @Override - 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); - } - - @Override - 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; - } - - @Override - public int allocateRankForNewItem(ShortcutInfo info) { - int rank = getItemCount(); - mFolder.rearrangeChildren(rank + 1); - return rank; - } - - @Override - public View createAndAddViewForRank(ShortcutInfo item, int rank) { - updateItemXY(item, rank); - return addNewView(item); - } - - @Override - 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, mFolder.mLauncher.getViewIdForItem(item), lp, true); - } - - @Override - public void removeItem(View v) { - removeView(v); - } - - /** - * 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, mFolder.mLauncher.getViewIdForItem(item), lp, true); - return textView; - } - - /** - * Refer {@link #findNearestArea(int, int, int, int, View, boolean, int[])} - */ - @Override - public int findNearestArea(int pixelX, int pixelY) { - findNearestArea(pixelX, pixelY, 1, 1, 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]); - } - - @Override - public boolean isFull() { - return getItemCount() >= mMaxNumItems; - } - - @Override - public int getItemCount() { - return getShortcutsAndWidgets().getChildCount(); - } - - @Override - 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, mFolder.mLauncher.getViewIdForItem(info), lp, true); - } - } - - @Override - public View iterateOverItems(ItemOperator op) { - for (int j = 0; j < getCountY(); j++) { - for (int i = 0; i < getCountX(); i++) { - View v = getChildAt(i, j); - if ((v != null) && op.evaluate((ItemInfo) v.getTag(), v, this)) { - return v; - } - } - } - return null; - } - - @Override - public String getAccessibilityDescription() { - return String.format(getContext().getString(R.string.folder_opened), - getCountX(), getCountY()); - } - - @Override - public void setFocusOnFirstChild() { - View firstChild = getChildAt(0, 0); - if (firstChild != null) { - firstChild.requestFocus(); - } - } - - @Override - public View getLastItem() { - int lastRank = getShortcutsAndWidgets().getChildCount() - 1; - // count can be zero if the folder is not yet laid out. - int count = getCountX(); - if (count > 0) { - return getShortcutsAndWidgets().getChildAt(lastRank % count, lastRank / count); - } else { - return getShortcutsAndWidgets().getChildAt(lastRank); - } - } - - @Override - 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; - } - } - } - } - } -} diff --git a/src/com/android/launcher3/FolderPagedView.java b/src/com/android/launcher3/FolderPagedView.java index 1c42d2592..247c55246 100644 --- a/src/com/android/launcher3/FolderPagedView.java +++ b/src/com/android/launcher3/FolderPagedView.java @@ -19,7 +19,6 @@ package com.android.launcher3; import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; -import android.util.LayoutDirection; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; @@ -42,10 +41,15 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -public class FolderPagedView extends PagedView implements Folder.FolderContent { +public class FolderPagedView extends PagedView { private static final String TAG = "FolderPagedView"; + private static final boolean ALLOW_FOLDER_SCROLL = true; + + // To enable this flag, user_folder.xml needs to be modified to add sort button. + private static final boolean ALLOW_ITEM_SORTING = false; + 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; @@ -96,32 +100,38 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { setDataIsReady(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - mMaxCountX = Math.min((int) grid.numColumns, MAX_ITEMS_PER_PAGE); - mMaxCountY = Math.min((int) grid.numRows, MAX_ITEMS_PER_PAGE); + if (ALLOW_FOLDER_SCROLL) { + mMaxCountX = Math.min((int) grid.numColumns, MAX_ITEMS_PER_PAGE); + mMaxCountY = Math.min((int) grid.numRows, MAX_ITEMS_PER_PAGE); + } else { + mMaxCountX = (int) grid.numColumns; + mMaxCountY = (int) grid.numRows; + } + mMaxItemsPerPage = mMaxCountX * mMaxCountY; mInflater = LayoutInflater.from(context); mIconCache = app.getIconCache(); - rtlLayout = getResources().getConfiguration().getLayoutDirection() == LayoutDirection.RTL; + rtlLayout = getResources().getConfiguration().getLayoutDirection() == LAYOUT_DIRECTION_RTL; } - @Override public void setFolder(Folder folder) { mFolder = folder; mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator); mKeyListener = new PagedFolderKeyEventListener(folder); + mPageIndicator = folder.findViewById(R.id.folder_page_indicator); - mSortButton = folder.findViewById(R.id.folder_sort); - mSortButton.setOnClickListener(new OnClickListener() { + if (ALLOW_ITEM_SORTING) { + // Initialize {@link #mSortSwitch} and {@link #mSortButton}. + mSortButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - onSortClicked(); - } - }); - mPageIndicator = folder.findViewById(R.id.folder_page_indicator); - mSortSwitch = (Switch) folder.findViewById(R.id.folder_sort_switch); + @Override + public void onClick(View v) { + onSortClicked(); + } + }); + } } private void onSortClicked() { @@ -138,9 +148,11 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { private void setIsSorted(boolean isSorted, boolean saveChanges) { mIsSorted = isSorted; - mSortSwitch.setChecked(isSorted); - mFolder.mInfo.setOption(FolderInfo.FLAG_ITEMS_SORTED, isSorted, - saveChanges ? mFolder.mLauncher : null); + if (ALLOW_ITEM_SORTING) { + mSortSwitch.setChecked(isSorted); + mFolder.mInfo.setOption(FolderInfo.FLAG_ITEMS_SORTED, isSorted, + saveChanges ? mFolder.mLauncher : null); + } } /** @@ -282,26 +294,34 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { } } - @Override + /** + * 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) { - mIsSorted = mFolder.mInfo.hasOption(FolderInfo.FLAG_ITEMS_SORTED); + mIsSorted = ALLOW_ITEM_SORTING && mFolder.mInfo.hasOption(FolderInfo.FLAG_ITEMS_SORTED); ArrayList<View> icons = new ArrayList<View>(); + ArrayList<ShortcutInfo> extra = new ArrayList<ShortcutInfo>(); + for (ShortcutInfo item : items) { - icons.add(createNewView(item)); + if (!ALLOW_FOLDER_SCROLL && icons.size() >= mMaxItemsPerPage) { + extra.add(item); + } else { + icons.add(createNewView(item)); + } } arrangeChildren(icons, icons.size(), false); - return new ArrayList<ShortcutInfo>(); + return extra; } /** * Create space for a new item at the end, and returns the rank for that item. * Also sets the current page to the last page. */ - @Override public int allocateRankForNewItem(ShortcutInfo info) { int rank = getItemCount(); ArrayList<View> views = new ArrayList<View>(mFolder.getItemsInReadingOrder()); - if (mIsSorted) { + if (ALLOW_ITEM_SORTING && mIsSorted) { View tmp = new View(getContext()); tmp.setTag(info); int index = Collections.binarySearch(views, tmp, new ViewComparator()); @@ -321,14 +341,16 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { return rank; } - @Override public View createAndAddViewForRank(ShortcutInfo item, int rank) { View icon = createNewView(item); addViewForRank(icon, item, rank); return icon; } - @Override + /** + * 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) { int pagePos = rank % mMaxItemsPerPage; int pageNo = rank / mMaxItemsPerPage; @@ -388,14 +410,12 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { return page; } - @Override public void setFixedSize(int width, int height) { for (int i = getChildCount() - 1; i >= 0; i --) { ((CellLayout) getChildAt(i)).setFixedSize(width, height); } } - @Override public void removeItem(View v) { for (int i = getChildCount() - 1; i >= 0; i --) { getPageAt(i).removeView(v); @@ -412,7 +432,6 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { * at the end, otherwise it is ignored. * */ - @Override public void arrangeChildren(ArrayList<View> list, int itemCount) { arrangeChildren(list, itemCount, true); } @@ -488,19 +507,26 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { setCurrentPage(0); } - setIsSorted(isSorted, saveChanges); + setEnableOverscroll(getPageCount() > 1); // Update footer - if (getPageCount() > 1) { - mPageIndicator.setVisibility(View.VISIBLE); - mSortButton.setVisibility(View.VISIBLE); - mFolder.mFolderName.setGravity(rtlLayout ? Gravity.RIGHT : Gravity.LEFT); - setEnableOverscroll(true); + if (ALLOW_ITEM_SORTING) { + setIsSorted(isSorted, saveChanges); + if (getPageCount() > 1) { + mPageIndicator.setVisibility(View.VISIBLE); + mSortButton.setVisibility(View.VISIBLE); + mFolder.mFolderName.setGravity(rtlLayout ? Gravity.RIGHT : Gravity.LEFT); + } else { + mPageIndicator.setVisibility(View.GONE); + mSortButton.setVisibility(View.GONE); + mFolder.mFolderName.setGravity(Gravity.CENTER_HORIZONTAL); + } } else { - mPageIndicator.setVisibility(View.GONE); - mSortButton.setVisibility(View.GONE); - mFolder.mFolderName.setGravity(Gravity.CENTER_HORIZONTAL); - setEnableOverscroll(false); + int indicatorVisibility = mPageIndicator.getVisibility(); + mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE); + if (indicatorVisibility != mPageIndicator.getVisibility()) { + mFolder.updateFooterHeight(); + } } } @@ -521,7 +547,6 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { return getPageCount() > 0 ? getPageAt(0).getDesiredHeight() : 0; } - @Override public int getItemCount() { int lastPageIndex = getChildCount() - 1; if (lastPageIndex < 0) { @@ -532,7 +557,9 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { + lastPageIndex * mMaxItemsPerPage; } - @Override + /** + * @return the rank of the cell nearest to the provided pixel position. + */ public int findNearestArea(int pixelX, int pixelY) { int pageIndex = getNextPage(); CellLayout page = getPageAt(pageIndex); @@ -550,12 +577,10 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { R.drawable.ic_pageindicator_default_folder); } - @Override public boolean isFull() { - return false; + return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage; } - @Override public View getLastItem() { if (getChildCount() < 1) { return null; @@ -569,7 +594,10 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { } } - @Override + /** + * Iterates over all its items in a reading order. + * @return the view for which the operator returned true. + */ public View iterateOverItems(ItemOperator op) { for (int k = 0 ; k < getChildCount(); k++) { CellLayout page = getPageAt(k); @@ -585,13 +613,14 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { return null; } - @Override public String getAccessibilityDescription() { return String.format(getContext().getString(R.string.folder_opened), mGridCountX, mGridCountY); } - @Override + /** + * Sets the focus on the first visible child. + */ public void setFocusOnFirstChild() { View firstChild = getCurrentCellLayout().getChildAt(0, 0); if (firstChild != null) { @@ -605,7 +634,7 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { if (mFolder != null) { mFolder.updateTextViewFocus(); } - if (mSortOperationPending && getNextPage() == 0) { + if (ALLOW_ITEM_SORTING && mSortOperationPending && getNextPage() == 0) { post(new Runnable() { @Override @@ -680,7 +709,9 @@ public class FolderPagedView extends PagedView implements Folder.FolderContent { } } - @Override + /** + * Reorders the items such that the {@param empty} spot moves to {@param target} + */ public void realTimeReorder(int empty, int target) { completePendingPageChanges(); int delay = 0; |