diff options
author | Mario Bertschler <bmario@google.com> | 2017-01-30 17:05:24 -0800 |
---|---|---|
committer | Mario Bertschler <bmario@google.com> | 2017-05-03 10:32:57 -0700 |
commit | 48198d004af64d0d7c8b86bc243087f68dc374c9 (patch) | |
tree | 503173ab33803b465990dff9ed62a8731d5f7e80 /src/com/android/launcher3 | |
parent | 2526ba8215976432806c69c468f7b556e7877513 (diff) | |
download | android_packages_apps_Trebuchet-48198d004af64d0d7c8b86bc243087f68dc374c9.tar.gz android_packages_apps_Trebuchet-48198d004af64d0d7c8b86bc243087f68dc374c9.tar.bz2 android_packages_apps_Trebuchet-48198d004af64d0d7c8b86bc243087f68dc374c9.zip |
All Apps transition with gradient and scrim.
The transition is behind a feature flag and
turned off by default.
Change-Id: I155840ba82b5a573d874376797db5f739a52d706
Diffstat (limited to 'src/com/android/launcher3')
9 files changed, 361 insertions, 10 deletions
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 128d95603..ab82c988e 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -72,7 +72,9 @@ public class Hotseat extends FrameLayout mBackgroundColor = ColorUtils.setAlphaComponent( Themes.getAttrColor(context, android.R.attr.colorPrimary), 0); mBackground = new ColorDrawable(mBackgroundColor); - setBackground(mBackground); + if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + setBackground(mBackground); + } } public CellLayout getLayout() { @@ -179,6 +181,10 @@ public class Hotseat extends FrameLayout } public void updateColor(ExtractedColors extractedColors, boolean animate) { + if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + // not hotseat visible + return; + } if (!mHasVerticalHotseat) { int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX); if (mBackgroundColorAnimator != null) { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 90dc2ef3f..756a85360 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -466,7 +466,9 @@ public class Launcher extends BaseActivity @Override public void onExtractedColorsChanged() { loadExtractedColorsAndColorItems(); - + if (mAllAppsController != null) { + mAllAppsController.onExtractedColorsChanged(); + } if (mLauncherCallbacks != null) { mLauncherCallbacks.onExtractedColorsChanged(); } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 776ec2f62..54e7dd2bc 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -28,6 +28,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; @@ -645,4 +646,28 @@ public final class Utilities { hashSet.add(elem); return hashSet; } + + /** + * @return creates a new alpha mask bitmap out of an existing bitmap + */ + public static Bitmap convertToAlphaMask(Bitmap b, float applyAlpha) { + Bitmap a = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ALPHA_8); + Canvas c = new Canvas(a); + Paint paint = new Paint(); + paint.setAlpha((int) (255f * applyAlpha)); + c.drawBitmap(b, 0f, 0f, paint); + return a; + } + + /** + * @return a new white 1x1 bitmap with ALPHA_8 + */ + public static Bitmap createOnePixBitmap() { + Bitmap a = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); + Canvas c = new Canvas(a); + Paint paint = new Paint(); + paint.setColor(Color.WHITE); + c.drawPaint(paint); + return a; + } } diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index af6763107..7be8e8f0e 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -492,7 +492,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc ViewGroup.LayoutParams navBarBgLp = navBarBg.getLayoutParams(); navBarBgLp.height = insets.bottom; navBarBg.setLayoutParams(navBarBgLp); - navBarBg.setVisibility(View.VISIBLE); + navBarBg.setVisibility(FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS + ? View.INVISIBLE : View.VISIBLE); } } diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 30ed180e7..121ce4ce1 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -22,6 +22,10 @@ import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; +import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dynamicui.ExtractedColors; +import com.android.launcher3.graphics.RadialGradientView; +import com.android.launcher3.graphics.ScrimView; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.Themes; @@ -91,6 +95,8 @@ public class AllAppsTransitionController implements TouchController, VerticalPul // Used in discovery bounce animation to provide the transition without workspace changing. private boolean mIsTranslateWithoutWorkspace = false; private AnimatorSet mDiscoBounceAnimation; + private RadialGradientView mGradientView; + private ScrimView mScrimView; public AllAppsTransitionController(Launcher l) { mLauncher = l; @@ -247,7 +253,9 @@ public class AllAppsTransitionController implements TouchController, VerticalPul if (!mLauncher.isAllAppsVisible()) { mLauncher.tryAndUpdatePredictedApps(); mAppsView.setVisibility(View.VISIBLE); - mAppsView.setRevealDrawableColor(mHotseatBackgroundColor); + if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + mAppsView.setRevealDrawableColor(mHotseatBackgroundColor); + } } } } @@ -263,6 +271,36 @@ public class AllAppsTransitionController implements TouchController, VerticalPul mLauncher.activateLightSystemBars(forceLight, true /* statusBar */, true /* navBar */); } + private void updateAllAppsBg(float progress) { + // gradient + if (mGradientView == null) { + mGradientView = (RadialGradientView) mLauncher.findViewById(R.id.gradient_bg); + mGradientView.setVisibility(View.VISIBLE); + onExtractedColorsChanged(); + } + mGradientView.setProgress(progress); + + // scrim + if (mScrimView == null) { + mScrimView = (ScrimView) mLauncher.findViewById(R.id.scrim_bg); + mScrimView.setVisibility(View.VISIBLE); + } + mScrimView.setProgress(progress); + } + + public void onExtractedColorsChanged() { + if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + if (mGradientView != null) { + int color1 = mLauncher.getExtractedColors() + .getColor(ExtractedColors.ALLAPPS_GRADIENT_MAIN_INDEX); + int color2 = mLauncher.getExtractedColors() + .getColor(ExtractedColors.ALLAPPS_GRADIENT_SECONDARY_INDEX); + mGradientView.onExtractedColorsChanged(color1, color2); + mGradientView.requestLayout(); + } + } + } + /** * @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace */ @@ -280,7 +318,12 @@ public class AllAppsTransitionController implements TouchController, VerticalPul int bgAlpha = Color.alpha((int) mEvaluator.evaluate(alpha, mHotseatBackgroundColor, mAllAppsBackgroundColor)); - mAppsView.setRevealDrawableColor(ColorUtils.setAlphaComponent(color, bgAlpha)); + if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + updateAllAppsBg(alpha); + } else { + mAppsView.setRevealDrawableColor(ColorUtils.setAlphaComponent(color, bgAlpha)); + } + mAppsView.getContentView().setAlpha(alpha); mAppsView.setTranslationY(shiftCurrent); diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionService.java b/src/com/android/launcher3/dynamicui/ColorExtractionService.java index 9379a7285..f6b02aa9c 100644 --- a/src/com/android/launcher3/dynamicui/ColorExtractionService.java +++ b/src/com/android/launcher3/dynamicui/ColorExtractionService.java @@ -63,8 +63,11 @@ public class ColorExtractionService extends IntentService { // We can't extract colors from live wallpapers, so just use the default color always. extractedColors.updateHotseatPalette(null); - if (FeatureFlags.QSB_IN_HOTSEAT) { + if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { extractedColors.updateWallpaperThemePalette(null); + if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + extractedColors.updateAllAppsGradientPalette(null); + } } } else { // We extract colors for the hotseat and status bar separately, @@ -75,8 +78,12 @@ public class ColorExtractionService extends IntentService { extractedColors.updateStatusBarPalette(getStatusBarPalette()); } - if (FeatureFlags.QSB_IN_HOTSEAT) { - extractedColors.updateWallpaperThemePalette(getWallpaperPalette()); + if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + Palette wallpaperPalette = getWallpaperPalette(); + extractedColors.updateWallpaperThemePalette(wallpaperPalette); + if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + extractedColors.updateAllAppsGradientPalette(wallpaperPalette); + } } } diff --git a/src/com/android/launcher3/dynamicui/ExtractedColors.java b/src/com/android/launcher3/dynamicui/ExtractedColors.java index 2e52a0b8c..3c4aba130 100644 --- a/src/com/android/launcher3/dynamicui/ExtractedColors.java +++ b/src/com/android/launcher3/dynamicui/ExtractedColors.java @@ -18,6 +18,7 @@ package com.android.launcher3.dynamicui; import android.content.Context; import android.graphics.Color; +import android.support.annotation.Nullable; import android.support.v4.graphics.ColorUtils; import android.support.v7.graphics.Palette; import android.util.Log; @@ -42,12 +43,24 @@ public class ExtractedColors { public static final int HOTSEAT_INDEX = 1; public static final int STATUS_BAR_INDEX = 2; public static final int WALLPAPER_VIBRANT_INDEX = 3; + public static final int ALLAPPS_GRADIENT_MAIN_INDEX = 4; + public static final int ALLAPPS_GRADIENT_SECONDARY_INDEX = 5; private static final int VERSION; private static final int[] DEFAULT_VALUES; static { - if (FeatureFlags.QSB_IN_HOTSEAT) { + if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) { + VERSION = 3; + DEFAULT_VALUES = new int[] { + VERSION, // VERSION_INDEX + 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha + DEFAULT_DARK, // STATUS_BAR_INDEX + 0xFFCCCCCC, // WALLPAPER_VIBRANT_INDEX + 0xFF000000, // ALLAPPS_GRADIENT_MAIN_INDEX + 0xFF000000 // ALLAPPS_GRADIENT_SECONDARY_INDEX + }; + } else if (FeatureFlags.QSB_IN_HOTSEAT) { VERSION = 2; DEFAULT_VALUES = new int[] { VERSION, // VERSION_INDEX @@ -142,9 +155,20 @@ public class ExtractedColors { DEFAULT_LIGHT : DEFAULT_DARK); } - public void updateWallpaperThemePalette(Palette wallpaperPalette) { + public void updateWallpaperThemePalette(@Nullable Palette wallpaperPalette) { int defaultColor = DEFAULT_VALUES[WALLPAPER_VIBRANT_INDEX]; setColorAtIndex(WALLPAPER_VIBRANT_INDEX, wallpaperPalette == null ? defaultColor : wallpaperPalette.getVibrantColor(defaultColor)); } + + public void updateAllAppsGradientPalette(@Nullable Palette wallpaperPalette) { + // TODO b/37089857 will be modified to take the system extracted colors into account + int idx; + idx = ALLAPPS_GRADIENT_MAIN_INDEX; + setColorAtIndex(idx, wallpaperPalette == null + ? DEFAULT_VALUES[idx] : wallpaperPalette.getDarkVibrantColor(DEFAULT_VALUES[idx])); + idx = ALLAPPS_GRADIENT_SECONDARY_INDEX; + setColorAtIndex(idx, wallpaperPalette == null + ? DEFAULT_VALUES[idx] : wallpaperPalette.getVibrantColor(DEFAULT_VALUES[idx])); + } } diff --git a/src/com/android/launcher3/graphics/RadialGradientView.java b/src/com/android/launcher3/graphics/RadialGradientView.java new file mode 100644 index 000000000..cf6851c00 --- /dev/null +++ b/src/com/android/launcher3/graphics/RadialGradientView.java @@ -0,0 +1,146 @@ +/* + * 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.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RadialGradient; +import android.graphics.RectF; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.DecelerateInterpolator; + +import com.android.launcher3.R; +import com.android.launcher3.Utilities; + +/** + * Draws a translucent radial gradient background from an initial state with progress 0.0 to a + * final state with progress 1.0; + */ +public class RadialGradientView extends View { + + public static final int DEFAULT_COLOR_1 = Color.WHITE; + public static final int DEFAULT_COLOR_2 = Color.BLACK; + + private static Bitmap sFinalGradientMask; + private static Bitmap sAlphaGradientMask; + + // TODO needs to be cleaned up once design finalizes + static class Config { + // dimens + final float gradientCenterX = 0.5f; + final float gradientCenterY = 1.05f; + final float gradientHeadStartFactor = 0.35f; + final float gradientAlphaMaskLengthDp = 700; + // interpolation + final boolean useGradientAlphaDecel = false; + final float decelFactorForGradientAlpha = 2f; + // colors + final float finalGradientAlpha = 0.75f; + int color1 = DEFAULT_COLOR_1; + int color2 = DEFAULT_COLOR_2; + } + + private final RectF mAlphaMaskRect = new RectF(); + private final RectF mFinalMaskRect = new RectF(); + private final Paint mPaint = new Paint(); + private final Config mConfig = new Config(); + private final DecelerateInterpolator mDecelInterpolator; + private float mProgress; + private int mWidth; + private int mHeight; + private final int mMaskHeight; + private final Context mAppContext; + + public RadialGradientView(Context context, AttributeSet attrs) { + super(context, attrs); + this.mAppContext = context.getApplicationContext(); + this.mDecelInterpolator = new DecelerateInterpolator(mConfig.decelFactorForGradientAlpha); + this.mMaskHeight = Utilities.pxFromDp(mConfig.gradientAlphaMaskLengthDp, + mAppContext.getResources().getDisplayMetrics()); + + if (sFinalGradientMask == null) { + sFinalGradientMask = Utilities.convertToAlphaMask( + Utilities.createOnePixBitmap(), mConfig.finalGradientAlpha); + } + if (sAlphaGradientMask == null) { + Bitmap alphaMaskFromResource = BitmapFactory.decodeResource(context.getResources(), + R.drawable.all_apps_alpha_mask); + sAlphaGradientMask = Utilities.convertToAlphaMask( + alphaMaskFromResource, mConfig.finalGradientAlpha); + } + } + + public void onExtractedColorsChanged(int color1, int color2) { + mConfig.color1 = color1; + mConfig.color2 = color2; + if (mWidth + mHeight > 0) { + createRadialShader(); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + this.mWidth = getMeasuredWidth(); + this.mHeight = getMeasuredHeight(); + if (mWidth + mHeight > 0) { + createRadialShader(); + } + } + + // only being called when colors change + private void createRadialShader() { + float radius = Math.max(mHeight, mWidth) * mConfig.gradientCenterY; + + float posScreenBottom = (radius - mHeight) / radius; // center lives below screen + RadialGradient shader = new RadialGradient( + mWidth * mConfig.gradientCenterX, + mHeight * mConfig.gradientCenterY, + radius, + new int[] {mConfig.color1, mConfig.color1, mConfig.color2}, + new float[] {0f, posScreenBottom, 1f}, + Shader.TileMode.CLAMP); + mPaint.setShader(shader); + } + + public void setProgress(float progress) { + this.mProgress = progress; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + float head = mConfig.gradientHeadStartFactor; + float linearProgress = head + (mProgress * (1f - head)); + float adjustProgress = mConfig.useGradientAlphaDecel + ? mDecelInterpolator.getInterpolation(linearProgress) + : linearProgress; + float startMaskY = (1f - adjustProgress) * mHeight - mMaskHeight * adjustProgress; + + mAlphaMaskRect.set(0, startMaskY, mWidth, startMaskY + mMaskHeight); + mFinalMaskRect.set(0, startMaskY + mMaskHeight, mWidth, mHeight); + canvas.drawBitmap(sAlphaGradientMask, null, mAlphaMaskRect, mPaint); + canvas.drawBitmap(sFinalGradientMask, null, mFinalMaskRect, mPaint); + } + +}
\ No newline at end of file diff --git a/src/com/android/launcher3/graphics/ScrimView.java b/src/com/android/launcher3/graphics/ScrimView.java new file mode 100644 index 000000000..521fbedd6 --- /dev/null +++ b/src/com/android/launcher3/graphics/ScrimView.java @@ -0,0 +1,97 @@ +/* + * 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.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.support.v4.graphics.ColorUtils; +import android.util.AttributeSet; +import android.view.View; + +import com.android.launcher3.R; +import com.android.launcher3.Utilities; + +public class ScrimView extends View { + + // Config + private static final int MASK_HEIGHT_DP = 600; + private static final float MASK_START_LENGTH_FACTOR = 0.4f; + private static final float FINAL_ALPHA = 0.87f; + private static final int SCRIM_COLOR = ColorUtils.setAlphaComponent( + Color.WHITE, (int) (FINAL_ALPHA * 255)); + + private static Bitmap sFinalScrimMask; + private static Bitmap sAlphaScrimMask; + + private final int mMaskHeight; + private int mVisibleHeight; + private final int mHeadStart; + + private final RectF mAlphaMaskRect = new RectF(); + private final RectF mFinalMaskRect = new RectF(); + private final Paint mPaint = new Paint(); + private float mProgress; + + public ScrimView(Context context, AttributeSet attrs) { + super(context, attrs); + mMaskHeight = Utilities.pxFromDp(MASK_HEIGHT_DP, getResources().getDisplayMetrics()); + mHeadStart = (int) (mMaskHeight * MASK_START_LENGTH_FACTOR); + mPaint.setColor(SCRIM_COLOR); + + if (sFinalScrimMask == null) { + sFinalScrimMask = Utilities.convertToAlphaMask( + Utilities.createOnePixBitmap(), FINAL_ALPHA); + } + if (sAlphaScrimMask == null) { + Bitmap alphaMaskFromResource = BitmapFactory.decodeResource(getResources(), + R.drawable.all_apps_alpha_mask); + sAlphaScrimMask = Utilities.convertToAlphaMask(alphaMaskFromResource, FINAL_ALPHA); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + mVisibleHeight = MeasureSpec.getSize(heightMeasureSpec); + int fullHeight = mVisibleHeight * 2 + mMaskHeight; + setMeasuredDimension(width, fullHeight); + setProgress(mProgress); + } + + public void setProgress(float progress) { + mProgress = progress; + float initialY = mVisibleHeight - mHeadStart; + float fullTranslationY = mMaskHeight + initialY + mVisibleHeight; + float translationY = initialY - progress * fullTranslationY; + setTranslationY(translationY); + } + + @Override + protected void onDraw(Canvas canvas) { + mAlphaMaskRect.set(0, 0, getWidth(), mMaskHeight); + mFinalMaskRect.set(0, mMaskHeight, getWidth(), getHeight()); + canvas.drawBitmap(sAlphaScrimMask, null, mAlphaMaskRect, mPaint); + canvas.drawBitmap(sFinalScrimMask, null, mFinalMaskRect, mPaint); + } + +} |