From b532dfe45df5cf254e4ea6ab7c7e01051834ad65 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 13 Dec 2017 17:16:54 -0800 Subject: [PATCH] Updating the hotseat background to a solid color with rounded corners Change-Id: I297920518f925e122f2e9f55a68228b96b42ea27 --- res/layout-land/launcher.xml | 6 +- res/layout-port/launcher.xml | 6 +- res/layout-sw720dp/launcher.xml | 6 +- res/values/dimens.xml | 4 + src/com/android/launcher3/DeviceProfile.java | 13 +- .../WorkspaceStateTransitionAnimation.java | 3 - .../allapps/AllAppsTransitionController.java | 23 ++- .../graphics/NinePatchDrawHelper.java | 71 +++++++++ .../launcher3/graphics/ShadowGenerator.java | 14 ++ .../android/launcher3/views/AllAppsScrim.java | 150 ++++++++++++++++++ 10 files changed, 275 insertions(+), 21 deletions(-) create mode 100644 src/com/android/launcher3/graphics/NinePatchDrawHelper.java create mode 100644 src/com/android/launcher3/views/AllAppsScrim.java diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index d21e45d99e..f6bdd2580c 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -50,7 +50,11 @@ android:layout_gravity="bottom|left" android:background="@drawable/all_apps_handle_landscape" /> - + - + - + 0dp 0dp + + 10dp + 10dp + 5dp 48dp diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index c6226f4477..7b3da67712 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -33,6 +33,7 @@ import android.widget.FrameLayout; import com.android.launcher3.CellLayout.ContainerType; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.badge.BadgeRenderer; +import com.android.launcher3.views.AllAppsScrim; import java.util.ArrayList; @@ -588,14 +589,16 @@ public class DeviceProfile { searchBar.setLayoutParams(lp); // Layout the workspace - PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace); + PagedView workspace = launcher.getWorkspace(); Rect workspacePadding = getWorkspacePadding(null); workspace.setPadding(workspacePadding.left, workspacePadding.top, workspacePadding.right, workspacePadding.bottom); workspace.setPageSpacing(getWorkspacePageSpacing()); + AllAppsScrim allAppsScrim = launcher.findViewById(R.id.all_apps_scrim); + // Layout the hotseat - Hotseat hotseat = (Hotseat) launcher.findViewById(R.id.hotseat); + Hotseat hotseat = launcher.getHotseat(); lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams(); // We want the edges of the hotseat to line up with the edges of the workspace, but the // icons in the hotseat are a different size, and so don't line up perfectly. To account for @@ -604,6 +607,8 @@ public class DeviceProfile { float workspaceCellWidth = (float) getCurrentWidth() / inv.numColumns; float hotseatCellWidth = (float) getCurrentWidth() / inv.numHotseatIcons; int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2); + float scrimMargin = launcher.getResources().getDimension(R.dimen.all_apps_scrim_margin); + if (hasVerticalBarLayout) { // Vertical hotseat -- The hotseat is fixed in the layout to be on the right of the // screen regardless of RTL @@ -629,6 +634,8 @@ public class DeviceProfile { lp.gravity = Gravity.BOTTOM; lp.width = LayoutParams.MATCH_PARENT; lp.height = hotseatBarSizePx + mInsets.bottom; + allAppsScrim.setDrawRegion(lp.height + scrimMargin); + hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx, hotseatBarTopPaddingPx, @@ -640,6 +647,8 @@ public class DeviceProfile { lp.gravity = Gravity.BOTTOM; lp.width = LayoutParams.MATCH_PARENT; lp.height = hotseatBarSizePx + mInsets.bottom; + allAppsScrim.setDrawRegion(lp.height + scrimMargin); + hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx, hotseatBarTopPaddingPx, diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index 8a20bb9adc..80818f2bb8 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -18,7 +18,6 @@ package com.android.launcher3; import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; -import static com.android.launcher3.Partner.TAG; import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled; import android.animation.Animator; @@ -26,7 +25,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; -import android.util.Log; import android.util.Property; import android.view.View; @@ -165,7 +163,6 @@ public class WorkspaceStateTransitionAnimation { public static class PropertySetter { public void setViewAlpha(Animator anim, View view, float alpha) { - Log.d(TAG, "setViewAlpha: " + anim + " " + alpha); if (anim != null) { anim.end(); return; diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 5de58b4723..5830f740d2 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -24,6 +24,7 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.graphics.GradientView; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; +import com.android.launcher3.views.AllAppsScrim; /** * Handles AllApps view transition. @@ -74,7 +75,7 @@ public class AllAppsTransitionController private static final float DEFAULT_SHIFT_RANGE = 10; - private GradientView mGradientView; + private AllAppsScrim mAllAppsScrim; public AllAppsTransitionController(Launcher l) { mLauncher = l; @@ -106,14 +107,6 @@ public class AllAppsTransitionController } } - private void updateAllAppsBg(float progress) { - // gradient - if (mGradientView == null) { - mGradientView = mLauncher.findViewById(R.id.gradient_bg); - } - mGradientView.setProgress(progress); - } - /** * Note this method should not be called outside this class. This is public because it is used * in xml-based animations which also handle updating the appropriate UI. @@ -131,17 +124,21 @@ public class AllAppsTransitionController float alpha = 1 - workspaceHotseatAlpha; float hotseatAlpha = mHotseatAccelInterpolator.getInterpolation(workspaceHotseatAlpha); - updateAllAppsBg(alpha); mAppsView.setAlpha(alpha); mAppsView.setTranslationY(shiftCurrent); + if (mAllAppsScrim == null) { + mAllAppsScrim = mLauncher.findViewById(R.id.all_apps_scrim); + } + float hotseatTranslation = -mShiftRange + shiftCurrent; + mAllAppsScrim.setProgress(hotseatTranslation, alpha); + if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) { - mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y, -mShiftRange + shiftCurrent, + mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y, hotseatTranslation, hotseatAlpha); } else { mWorkspace.setHotseatTranslationAndAlpha(Workspace.Direction.Y, - PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent), - hotseatAlpha); + PARALLAX_COEFFICIENT * hotseatTranslation, hotseatAlpha); } updateLightStatusBar(shiftCurrent); diff --git a/src/com/android/launcher3/graphics/NinePatchDrawHelper.java b/src/com/android/launcher3/graphics/NinePatchDrawHelper.java new file mode 100644 index 0000000000..6df1ecb982 --- /dev/null +++ b/src/com/android/launcher3/graphics/NinePatchDrawHelper.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 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.graphics; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; + +/** + * Utility class which draws a bitmap by dissecting it into 3 segments and stretching + * the middle segment. + */ +public class NinePatchDrawHelper { + + // The extra width used for the bitmap. This portion of the bitmap is stretched to match the + // width of the draw region. Randomly chosen, any value > 4 will be sufficient. + public static final int EXTENSION_PX = 20; + + private final Rect mSrc = new Rect(); + private final RectF mDst = new RectF(); + public final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + public void draw(Bitmap bitmap, Canvas canvas, float left, float top, float right) { + int width = bitmap.getWidth(); + int height = bitmap.getHeight(); + + mSrc.top = 0; + mSrc.bottom = height; + + mDst.top = top; + mDst.bottom = top + height; + + int halfWidth = width / 2; + + // Draw left edge + drawRegion(bitmap, canvas, 0, halfWidth, left, left + halfWidth); + + // Draw right edge + drawRegion(bitmap, canvas, halfWidth, width, right - halfWidth, right); + + // Draw middle stretched region + int halfExt = EXTENSION_PX / 4; + drawRegion(bitmap, canvas, halfWidth - halfExt, halfWidth + halfExt, + left + halfWidth, right - halfWidth); + } + + private void drawRegion(Bitmap bitmap, Canvas c, + int srcLeft, int srcRight, float dstLeft, float dstRight) { + mSrc.left = srcLeft; + mSrc.right = srcRight; + + mDst.left = dstLeft; + mDst.right = dstRight; + c.drawBitmap(bitmap, mSrc, mDst, paint); + } +} diff --git a/src/com/android/launcher3/graphics/ShadowGenerator.java b/src/com/android/launcher3/graphics/ShadowGenerator.java index 08be4c9288..96f26292f7 100644 --- a/src/com/android/launcher3/graphics/ShadowGenerator.java +++ b/src/com/android/launcher3/graphics/ShadowGenerator.java @@ -24,6 +24,8 @@ import android.graphics.BlurMaskFilter.Blur; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.support.v4.graphics.ColorUtils; @@ -167,6 +169,18 @@ public class ShadowGenerator { p.setShadowLayer(shadowBlur, 0, 0, ColorUtils.setAlphaComponent(Color.BLACK, ambientShadowAlpha)); c.drawRoundRect(bounds, radius, radius, p); + + if (Color.alpha(color) < 255) { + // Clear any content inside the pill-rect for translucent fill. + p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + p.clearShadowLayer(); + p.setColor(Color.BLACK); + c.drawRoundRect(bounds, radius, radius, p); + + p.setXfermode(null); + p.setColor(color); + c.drawRoundRect(bounds, radius, radius, p); + } } } } diff --git a/src/com/android/launcher3/views/AllAppsScrim.java b/src/com/android/launcher3/views/AllAppsScrim.java new file mode 100644 index 0000000000..1ada251511 --- /dev/null +++ b/src/com/android/launcher3/views/AllAppsScrim.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2017 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.views; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.support.v4.graphics.ColorUtils; +import android.util.AttributeSet; +import android.view.View; + +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.dynamicui.WallpaperColorInfo; +import com.android.launcher3.graphics.NinePatchDrawHelper; +import com.android.launcher3.graphics.ShadowGenerator; +import com.android.launcher3.util.Themes; + +import static com.android.launcher3.graphics.NinePatchDrawHelper.EXTENSION_PX; + +public class AllAppsScrim extends View implements WallpaperColorInfo.OnChangeListener { + + private static final int MAX_ALPHA = 235; + private static final int MIN_ALPHA_PORTRAIT = 100; + private static final int MIN_ALPHA_LANDSCAPE = MAX_ALPHA; + + private final WallpaperColorInfo mWallpaperColorInfo; + private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private final float mRadius; + private final int mMinAlpha; + private final int mAlphaRange; + private final int mScrimColor; + + private final float mShadowBlur; + private final Bitmap mShadowBitmap; + + private final NinePatchDrawHelper mShadowHelper = new NinePatchDrawHelper(); + + private int mFillAlpha; + + private float mDrawHeight; + private float mTranslateY; + + public AllAppsScrim(Context context) { + this(context, null); + } + + public AllAppsScrim(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public AllAppsScrim(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + mWallpaperColorInfo = WallpaperColorInfo.getInstance(context); + mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor); + mRadius = getResources().getDimension(R.dimen.all_apps_scrim_radius); + mShadowBlur = getResources().getDimension(R.dimen.all_apps_scrim_blur); + + Launcher launcher = Launcher.getLauncher(context); + mFillAlpha = mMinAlpha = launcher.getDeviceProfile().isVerticalBarLayout() + ? MIN_ALPHA_LANDSCAPE : MIN_ALPHA_PORTRAIT; + mAlphaRange = MAX_ALPHA - mMinAlpha; + mShadowBitmap = generateShadowBitmap(); + + updateColors(mWallpaperColorInfo); + } + + private Bitmap generateShadowBitmap() { + float curveBot = mRadius + mShadowBlur; + + ShadowGenerator.Builder builder = new ShadowGenerator.Builder(Color.TRANSPARENT); + builder.radius = mRadius; + builder.shadowBlur = mShadowBlur; + + // Create the bitmap such that only the top half is drawn in the bitmap. + int bitmapHeight = Math.round(curveBot); + int bitmapWidth = bitmapHeight + EXTENSION_PX; + Bitmap result = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888); + + builder.bounds.set(0, mShadowBlur, bitmapWidth, 2 * curveBot + EXTENSION_PX); + builder.drawShadow(new Canvas(result)); + return result; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mWallpaperColorInfo.addOnChangeListener(this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mWallpaperColorInfo.removeOnChangeListener(this); + } + + @Override + public void onExtractedColorsChanged(WallpaperColorInfo info) { + updateColors(info); + invalidate(); + } + + private void updateColors(WallpaperColorInfo info) { + mFillPaint.setColor(ColorUtils.compositeColors(mScrimColor, + ColorUtils.compositeColors(mScrimColor, info.getMainColor()))); + mFillPaint.setAlpha(mFillAlpha); + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + float edgeTop = getHeight() + mTranslateY - mDrawHeight; + + mShadowHelper.draw(mShadowBitmap, canvas, 0, edgeTop - mShadowBlur, getWidth()); + canvas.drawRoundRect(0, edgeTop, getWidth(), + getHeight() + mRadius, mRadius, mRadius, mFillPaint); + } + + public void setProgress(float translateY, float alpha) { + mFillAlpha = Math.round(alpha * mAlphaRange + mMinAlpha); + mFillPaint.setAlpha(mFillAlpha); + + mTranslateY = translateY; + + invalidate(); + } + + public void setDrawRegion(float height) { + mDrawHeight = height; + } +}