diff options
author | Adam Cohen <adamcohen@google.com> | 2016-02-17 19:07:47 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-02-17 19:07:47 +0000 |
commit | 29aac6e27202703b721df7ab029ab81202dfd286 (patch) | |
tree | 407e18059dd7635504912f3ca84e8ff7b1243a70 | |
parent | 775d4c9ac0544c8ba95e9a7817bccc0c63508bcd (diff) | |
parent | 119e8982ab6a0cf00e31e8744f27b72ba8bf7b20 (diff) | |
download | android_packages_apps_Trebuchet-29aac6e27202703b721df7ab029ab81202dfd286.tar.gz android_packages_apps_Trebuchet-29aac6e27202703b721df7ab029ab81202dfd286.tar.bz2 android_packages_apps_Trebuchet-29aac6e27202703b721df7ab029ab81202dfd286.zip |
Merge "First pass at new FolderIcon visual treatment" into ub-launcher3-calgary
8 files changed, 184 insertions, 31 deletions
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml index 75b5c4839..d445a7ae3 100644 --- a/res/layout/user_folder_icon_normalized.xml +++ b/res/layout/user_folder_icon_normalized.xml @@ -14,7 +14,7 @@ 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" +<com.android.launcher3.folder.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" @@ -34,7 +34,7 @@ android:layout_width="20dp" android:layout_height="20dp" /> - <com.android.launcher3.FolderPagedView + <com.android.launcher3.folder.FolderPagedView android:id="@+id/folder_content" android:layout_width="match_parent" android:layout_height="match_parent" @@ -82,4 +82,4 @@ </LinearLayout> -</com.android.launcher3.Folder> +</com.android.launcher3.folder.Folder> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 468beaa37..fee62dcb8 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -138,8 +138,8 @@ <dimen name="quantum_panel_outer_padding">4dp</dimen> <!-- Folders --> - <!-- The amount that the preview contents are inset from the preview background --> - <dimen name="folder_preview_padding">4dp</dimen> + <!-- The size of the padding on the preview background drawable --> + <dimen name="folder_preview_padding">6dp</dimen> <!-- Sizes for managed profile badges --> <dimen name="profile_badge_size">24dp</dimen> diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index d7f1d8677..38700805f 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -93,7 +93,7 @@ public class FastBitmapDrawable extends Drawable { private static final ColorMatrix sTempBrightnessMatrix = new ColorMatrix(); private static final ColorMatrix sTempFilterMatrix = new ColorMatrix(); - private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); + private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); private final Bitmap mBitmap; private State mState = State.NORMAL; diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 1cb08b931..36acedee7 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -40,13 +40,13 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.ExtendedEditText; +import com.android.launcher3.folder.Folder; import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherTransitionable; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; -import com.android.launcher3.folder.Folder; import com.android.launcher3.util.ComponentKey; import java.nio.charset.Charset; diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b0b602c8c..e8e15c207 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -31,7 +31,8 @@ public final class FeatureFlags { public static boolean IS_RELEASE_BUILD = true; // Custom flags go below this - public static boolean LAUNCHER3_ICON_NORMALIZATION = false; // As opposed to the new spring-loaded workspace. public static boolean LAUNCHER3_LEGACY_WORKSPACE_DND = false; + public static boolean LAUNCHER3_ICON_NORMALIZATION = true; + public static boolean LAUNCHER3_CLIPPED_FOLDER_ICON = false; } diff --git a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java new file mode 100644 index 000000000..44d7ac6e9 --- /dev/null +++ b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java @@ -0,0 +1,128 @@ +package com.android.launcher3.folder; + +import android.graphics.Path; +import android.graphics.Point; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.Utilities; + +public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule { + + static final int MAX_NUM_ITEMS_IN_PREVIEW = 4; + private static final int MIN_NUM_ITEMS_IN_PREVIEW = 2; + + final float MIN_SCALE = 0.48f; + final float MAX_SCALE = 0.58f; + final float MAX_RADIUS_DILATION = 0.15f; + + private float[] mTmpPoint = new float[2]; + + private float mAvailableSpace; + private float mRadius; + private float mIconSize; + private boolean mIsRtl; + private Path mClipPath = new Path(); + + @Override + public void init(int availableSpace, int intrinsicIconSize, boolean rtl) { + mAvailableSpace = availableSpace; + mRadius = 0.66f * availableSpace; + mIconSize = intrinsicIconSize; + mIsRtl = rtl; + + // We make the clip radius just slightly smaller than the background drawable + // TODO(adamcohen): this is hacky, needs cleanup (likely through programmatic drawing). + int clipRadius = (int) mAvailableSpace / 2 - 1; + + mClipPath.addCircle(mAvailableSpace / 2, mAvailableSpace / 2, clipRadius, Path.Direction.CW); + } + + @Override + public FolderIcon.PreviewItemDrawingParams computePreviewItemDrawingParams(int index, + int curNumItems, FolderIcon.PreviewItemDrawingParams params) { + + getPosition(index, curNumItems, mTmpPoint); + + float transX = mTmpPoint[0]; + float transY = mTmpPoint[1]; + float totalScale = scaleForNumItems(curNumItems); + float overlayAlpha = 0; + + if (params == null) { + params = new FolderIcon.PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha); + } else { + params.transX = transX; + params.transY = transY; + params.scale = totalScale; + params.overlayAlpha = overlayAlpha; + } + + return params; + } + + private void getPosition(int index, int curNumItems, float[] result) { + // The case of two items is homomorphic to the case of one. + curNumItems = Math.max(curNumItems, 2); + + + // We model the preview as a circle of items starting in the appropriate piece of the + // upper left quadrant (to achieve horizontal and vertical symmetry). + double theta0 = mIsRtl ? 0 : Math.PI; + + // In RTL we go counterclockwise + int direction = mIsRtl ? 1 : -1; + + double thetaShift = 0; + if (curNumItems == 3) { + thetaShift = Math.PI / 6; + } else if (curNumItems == 4) { + thetaShift = Math.PI / 4; + } + theta0 += direction * thetaShift; + + // We want the items to appear in reading order. For the case of 1, 2 and 3 items, this + // is natural for the circular model. With 4 items, however, we need to swap the 3rd and + // 4th indices to achieve reading order. + if (curNumItems == 4 && index == 3) { + index = 2; + } else if (curNumItems == 4 && index == 2) { + index = 3; + } + + // We bump the radius up between 0 and MAX_RADIUS_DILATION % as the number of items increase + float radius = mRadius * (1 + MAX_RADIUS_DILATION * (curNumItems - + MIN_NUM_ITEMS_IN_PREVIEW) / (MAX_NUM_ITEMS_IN_PREVIEW - MIN_NUM_ITEMS_IN_PREVIEW)); + double theta = theta0 + index * (2 * Math.PI / curNumItems) * direction; + + float halfIconSize = (mIconSize * scaleForNumItems(curNumItems)) / 2; + + // Map the location along the circle, and offset the coordinates to represent the center + // of the icon, and to be based from the top / left of the preview area. The y component + // is inverted to match the coordinate system. + result[0] = mAvailableSpace / 2 + (float) (radius * Math.cos(theta) / 2) - halfIconSize; + result[1] = mAvailableSpace / 2 + (float) (- radius * Math.sin(theta) / 2) - halfIconSize; + + } + + private float scaleForNumItems(int numItems) { + if (numItems <= 2) { + return MAX_SCALE; + } else if (numItems == 3) { + return (MAX_SCALE + MIN_SCALE) / 2; + } else { + return MIN_SCALE; + } + } + + @Override + public int numItems() { + return MAX_NUM_ITEMS_IN_PREVIEW; + } + + @Override + public Path getClipPath() { + return mClipPath; + } + +} diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 8b95e76cf..5c084d949 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -65,6 +66,7 @@ import com.android.launcher3.SimpleOnStylusPressListener; import com.android.launcher3.StylusEventHelper; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.util.Thunk; @@ -81,8 +83,9 @@ public class FolderIcon extends FrameLayout implements FolderListener { private FolderInfo mInfo; @Thunk static boolean sStaticValuesDirty = true; - // TODO(adamcohen): remove this - public static final int NUM_ITEMS_IN_PREVIEW = 3; + public static final int NUM_ITEMS_IN_PREVIEW = FeatureFlags.LAUNCHER3_CLIPPED_FOLDER_ICON ? + ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW : + StackFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW; private CheckLongPressHelper mLongPressHelper; private StylusEventHelper mStylusEventHelper; @@ -152,7 +155,10 @@ public class FolderIcon extends FrameLayout implements FolderListener { private void init() { mLongPressHelper = new CheckLongPressHelper(this); mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this); - mPreviewLayoutRule = new StackFolderIconLayoutRule(); + mPreviewLayoutRule = FeatureFlags.LAUNCHER3_CLIPPED_FOLDER_ICON ? + new ClippedFolderIconLayoutRule() : + new StackFolderIconLayoutRule(); + setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate()); } @@ -468,7 +474,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { } int[] center = new int[2]; - float scale = getLocalCenterForIndex(index, center); + float scale = getLocalCenterForIndex(index, index + 1, center); center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]); center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]); @@ -516,7 +522,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { mIntrinsicIconSize = drawableSize; mTotalWidth = totalSize; - final int previewSize = mPreviewBackground.getLayoutParams().height; + final int previewSize = FolderRingAnimator.sPreviewSize; final int previewPadding = FolderRingAnimator.sPreviewPadding; mAvailableSpaceInPreview = (previewSize - 2 * previewPadding); @@ -524,8 +530,8 @@ public class FolderIcon extends FrameLayout implements FolderListener { mPreviewOffsetX = (mTotalWidth - mAvailableSpaceInPreview) / 2; mPreviewOffsetY = previewPadding + grid.folderBackgroundOffset + getPaddingTop(); - // Initialize the preview layout rule - mPreviewLayoutRule.init(mAvailableSpaceInPreview, mIntrinsicIconSize); + mPreviewLayoutRule.init(mAvailableSpaceInPreview, mIntrinsicIconSize, + Utilities.isRtl(getResources())); } } @@ -547,9 +553,9 @@ public class FolderIcon extends FrameLayout implements FolderListener { Drawable drawable; } - private float getLocalCenterForIndex(int index, int[] center) { + private float getLocalCenterForIndex(int index, int curNumItems, int[] center) { mParams = computePreviewItemDrawingParams(Math.min(mPreviewLayoutRule.numItems(), index), - mParams); + curNumItems, mParams); mParams.transX += mPreviewOffsetX; mParams.transY += mPreviewOffsetY; @@ -561,14 +567,14 @@ public class FolderIcon extends FrameLayout implements FolderListener { return mParams.scale; } - private PreviewItemDrawingParams computePreviewItemDrawingParams(int index, + private PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems, PreviewItemDrawingParams params) { - return mPreviewLayoutRule.computePreviewItemDrawingParams(index, params); + return mPreviewLayoutRule.computePreviewItemDrawingParams(index, curNumItems, params); } private void drawPreviewItem(Canvas canvas, PreviewItemDrawingParams params) { canvas.save(); - canvas.translate(params.transX + mPreviewOffsetX, params.transY + mPreviewOffsetY); + canvas.translate(params.transX, params.transY); canvas.scale(params.scale, params.scale); Drawable d = params.drawable; @@ -612,13 +618,20 @@ public class FolderIcon extends FrameLayout implements FolderListener { computePreviewDrawingParams(d); } + canvas.save(); + canvas.translate(mPreviewOffsetX, mPreviewOffsetY); + Path clipPath = mPreviewLayoutRule.getClipPath(); + if (clipPath != null) { + canvas.clipPath(clipPath); + } + int nItemsInPreview = Math.min(items.size(), mPreviewLayoutRule.numItems()); if (!mAnimating) { for (int i = nItemsInPreview - 1; i >= 0; i--) { v = (TextView) items.get(i); if (!mHiddenItems.contains(v.getTag())) { d = getTopDrawable(v); - mParams = computePreviewItemDrawingParams(i, mParams); + mParams = computePreviewItemDrawingParams(i, nItemsInPreview, mParams); mParams.drawable = d; drawPreviewItem(canvas, mParams); } @@ -626,6 +639,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { } else { drawPreviewItem(canvas, mAnimParams); } + canvas.restore(); } private Drawable getTopDrawable(TextView v) { @@ -635,7 +649,9 @@ public class FolderIcon extends FrameLayout implements FolderListener { private void animateFirstItem(final Drawable d, int duration, final boolean reverse, final Runnable onCompleteRunnable) { - final PreviewItemDrawingParams finalParams = computePreviewItemDrawingParams(0, null); + + final PreviewItemDrawingParams finalParams = + computePreviewItemDrawingParams(0, reverse ? 1 : 2, null); float iconSize = mLauncher.getDeviceProfile().iconSizePx; final float scale0 = iconSize / d.getIntrinsicWidth() ; @@ -749,11 +765,12 @@ public class FolderIcon extends FrameLayout implements FolderListener { } public interface PreviewLayoutRule { - public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, + public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems, PreviewItemDrawingParams params); - public void init(int availableSpace, int intrinsicIconSize); + public void init(int availableSpace, int intrinsicIconSize, boolean rtl); public int numItems(); + public Path getClipPath(); } } diff --git a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java index 1405b40c5..87f5f897b 100644 --- a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java +++ b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java @@ -16,11 +16,13 @@ package com.android.launcher3.folder; +import android.graphics.Path; + import com.android.launcher3.folder.FolderIcon.PreviewItemDrawingParams; public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule { - public static final int NUM_ITEMS_IN_PREVIEW = 3; + static final int MAX_NUM_ITEMS_IN_PREVIEW = 3; // The degree to which the item in the back of the stack is scaled [0...1] // (0 means it's not scaled at all, 1 means it's scaled to nothing) @@ -29,13 +31,13 @@ public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule { // The amount of vertical spread between items in the stack [0...1] private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f; - //private int mIntrinsicIconSize; private float mBaselineIconScale; private int mBaselineIconSize; private int mAvailableSpaceInPreview; private float mMaxPerspectiveShift; - public void init(int availableSpace, int intrinsicIconSize) { + @Override + public void init(int availableSpace, int intrinsicIconSize, boolean rtl) { mAvailableSpaceInPreview = availableSpace; // cos(45) = 0.707 + ~= 0.1) = 0.8f @@ -50,11 +52,11 @@ public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule { } @Override - public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, + public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems, PreviewItemDrawingParams params) { - index = NUM_ITEMS_IN_PREVIEW - index - 1; - float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1); + index = MAX_NUM_ITEMS_IN_PREVIEW - index - 1; + float r = (index * 1.0f) / (MAX_NUM_ITEMS_IN_PREVIEW - 1); float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r)); float offset = (1 - r) * mMaxPerspectiveShift; @@ -81,6 +83,11 @@ public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule { @Override public int numItems() { - return NUM_ITEMS_IN_PREVIEW; + return MAX_NUM_ITEMS_IN_PREVIEW; + } + + @Override + public Path getClipPath() { + return null; } } |