Merge "Add local wallpaper color extraction to folder backgrounds." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
32ee8c6a51
@@ -39,6 +39,7 @@ import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.LocalColorExtractor;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -108,12 +109,21 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
||||
|
||||
protected boolean mIsOpen;
|
||||
|
||||
// Index used to get background color when using local wallpaper color extraction.
|
||||
protected int mColorExtractionIndex;
|
||||
|
||||
public AbstractFloatingView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public AbstractFloatingView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mColorExtractionIndex = LocalColorExtractor.getColorIndex(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.content.Context;
|
||||
@@ -38,6 +39,8 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Build;
|
||||
import android.text.InputType;
|
||||
import android.text.Selection;
|
||||
@@ -45,6 +48,7 @@ import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.TypedValue;
|
||||
import android.view.FocusFinder;
|
||||
import android.view.KeyEvent;
|
||||
@@ -96,13 +100,16 @@ import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pageindicators.PageIndicatorDots;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.views.ClipPathView;
|
||||
import com.android.launcher3.widget.LocalColorExtractor;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -152,6 +159,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
private static final float ICON_OVERSCROLL_WIDTH_FACTOR = 0.45f;
|
||||
|
||||
private static final int FOLDER_NAME_ANIMATION_DURATION = 633;
|
||||
private static final int FOLDER_COLOR_ANIMATION_DURATION = 150;
|
||||
|
||||
private static final int REORDER_DELAY = 250;
|
||||
private static final int ON_EXIT_CLOSE_DELAY = 400;
|
||||
@@ -224,6 +232,19 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
|
||||
@Nullable private FolderWindowInsetsAnimationCallback mFolderWindowInsetsAnimationCallback;
|
||||
|
||||
// Wallpaper local color extraction
|
||||
@Nullable private LocalColorExtractor mColorExtractor;
|
||||
@Nullable private LocalColorExtractor.Listener mColorListener;
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final RectF mTempRectF = new RectF();
|
||||
|
||||
// For simplicity, we start the color change only after the open animation has started.
|
||||
private Runnable mColorChangeRunnable;
|
||||
private Animator mColorChangeAnimator;
|
||||
// The background color animator used in the folder open animation. We keep a reference to this,
|
||||
// so that we can cancel it when starting mColorChangeAnimator.
|
||||
private ObjectAnimator mOpenAnimationColorChangeAnimator;
|
||||
|
||||
/**
|
||||
* Used to inflate the Workspace from XML.
|
||||
*
|
||||
@@ -241,7 +262,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
// 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);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -276,6 +296,45 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
|
||||
setWindowInsetsAnimationCallback(mFolderWindowInsetsAnimationCallback);
|
||||
}
|
||||
|
||||
if (Utilities.ATLEAST_S) {
|
||||
mColorExtractor = LocalColorExtractor.newInstance(mLauncher);
|
||||
mColorListener = (RectF rect, SparseIntArray extractedColors) -> {
|
||||
mColorChangeRunnable = () -> {
|
||||
mColorChangeRunnable = null;
|
||||
int duration = FOLDER_COLOR_ANIMATION_DURATION;
|
||||
|
||||
// Cancel the open animation color change animator.
|
||||
ObjectAnimator existingAnim = mOpenAnimationColorChangeAnimator;
|
||||
if (existingAnim != null && existingAnim.isRunning()) {
|
||||
duration = (int) Math.max(FOLDER_COLOR_ANIMATION_DURATION,
|
||||
existingAnim.getDuration() * (1f - existingAnim.getDuration()));
|
||||
existingAnim.cancel();
|
||||
mOpenAnimationColorChangeAnimator = null;
|
||||
}
|
||||
|
||||
// Start a new animator to the extracted color.
|
||||
int newColor = extractedColors.get(mColorExtractionIndex);
|
||||
GradientDrawable bg = (GradientDrawable) getBackground();
|
||||
mColorChangeAnimator = ObjectAnimator.ofArgb(bg, "color",
|
||||
bg.getColor().getDefaultColor(), newColor).setDuration(duration);
|
||||
mColorChangeAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mColorChangeAnimator = null;
|
||||
}
|
||||
});
|
||||
mColorChangeAnimator.start();
|
||||
};
|
||||
|
||||
// If the folder open animation has started, we can start the color change now.
|
||||
// Otherwise we wait for it to start.
|
||||
if (mOpenAnimationColorChangeAnimator != null
|
||||
&& mOpenAnimationColorChangeAnimator.isStarted()) {
|
||||
post(mColorChangeRunnable);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onLongClick(View v) {
|
||||
@@ -652,15 +711,18 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
// dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice.
|
||||
mDeleteFolderOnDropCompleted = false;
|
||||
|
||||
if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
|
||||
mCurrentAnimator.cancel();
|
||||
}
|
||||
AnimatorSet anim = new FolderAnimationManager(this, true /* isOpening */).getAnimator();
|
||||
cancelRunningAnimations();
|
||||
FolderAnimationManager fam = new FolderAnimationManager(this, true /* isOpening */);
|
||||
AnimatorSet anim = fam.getAnimator();
|
||||
mOpenAnimationColorChangeAnimator = fam.getBgColorAnimator();
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mFolderIcon.setIconVisible(false);
|
||||
mFolderIcon.drawLeaveBehindIfExists();
|
||||
if (mColorChangeRunnable != null) {
|
||||
mColorChangeRunnable.run();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
@@ -752,6 +814,15 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
||||
}
|
||||
|
||||
private void cancelRunningAnimations() {
|
||||
if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
|
||||
mCurrentAnimator.cancel();
|
||||
}
|
||||
if (mColorChangeAnimator != null && mColorChangeAnimator.isRunning()) {
|
||||
mColorChangeAnimator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void animateClosed() {
|
||||
if (mIsAnimatingClosed) {
|
||||
return;
|
||||
@@ -760,9 +831,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
mContent.completePendingPageChanges();
|
||||
mContent.snapToPageImmediately(mContent.getDestinationPage());
|
||||
|
||||
if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
|
||||
mCurrentAnimator.cancel();
|
||||
}
|
||||
cancelRunningAnimations();
|
||||
AnimatorSet a = new FolderAnimationManager(this, false /* isOpening */).getAnimator();
|
||||
a.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
@@ -837,6 +906,19 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
clearDragInfo();
|
||||
mState = STATE_SMALL;
|
||||
mContent.setCurrentPage(0);
|
||||
|
||||
mOpenAnimationColorChangeAnimator = null;
|
||||
mColorChangeRunnable = null;
|
||||
if (mColorChangeAnimator != null) {
|
||||
mColorChangeAnimator.cancel();
|
||||
mColorChangeAnimator = null;
|
||||
}
|
||||
if (mColorExtractor != null) {
|
||||
mColorExtractor.removeLocations();
|
||||
mColorExtractor.setListener(null);
|
||||
}
|
||||
GradientDrawable bg = (GradientDrawable) getBackground();
|
||||
bg.setColor(Themes.getAttrColor(getContext(), R.attr.folderFillColor));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1104,6 +1186,17 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
lp.height = height;
|
||||
lp.x = left;
|
||||
lp.y = top;
|
||||
|
||||
if (mColorExtractor != null) {
|
||||
mColorExtractor.removeLocations();
|
||||
mColorExtractor.setListener(mColorListener);
|
||||
mTempRect.set(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
|
||||
mColorExtractor.getExtractedRectForViewRect(mLauncher,
|
||||
mLauncher.getWorkspace().getCurrentPage(), mTempRect, mTempRectF);
|
||||
if (!mTempRectF.isEmpty()) {
|
||||
mColorExtractor.addLocation(Arrays.asList(mTempRectF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int getContentAreaHeight() {
|
||||
|
||||
@@ -35,8 +35,6 @@ import android.util.Property;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.R;
|
||||
@@ -80,6 +78,8 @@ public class FolderAnimationManager {
|
||||
private final PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
|
||||
private final FolderGridOrganizer mPreviewVerifier;
|
||||
|
||||
private ObjectAnimator mBgColorAnimator;
|
||||
|
||||
public FolderAnimationManager(Folder folder, boolean isOpening) {
|
||||
mFolder = folder;
|
||||
mContent = folder.mContent;
|
||||
@@ -105,6 +105,12 @@ public class FolderAnimationManager {
|
||||
R.interpolator.large_folder_preview_item_close_interpolator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the animator that changes the background color.
|
||||
*/
|
||||
public ObjectAnimator getBgColorAnimator() {
|
||||
return mBgColorAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the Folder for animating between open / closed states.
|
||||
@@ -162,10 +168,15 @@ public class FolderAnimationManager {
|
||||
final float yDistance = initialY - lp.y;
|
||||
|
||||
// Set up the Folder background.
|
||||
final int finalColor = ColorUtils.setAlphaComponent(
|
||||
Themes.getAttrColor(mContext, R.attr.folderFillColor), 255);
|
||||
final int initialColor = setColorAlphaBound(
|
||||
finalColor, mPreviewBackground.getBackgroundAlpha());
|
||||
int previewBackgroundColor = Themes.getAttrColor(mContext, R.attr.folderFillColor);
|
||||
final int finalColor;
|
||||
if (mIsOpening) {
|
||||
finalColor = Themes.getAttrColor(mContext, R.attr.popupColorPrimary);
|
||||
} else {
|
||||
finalColor = mFolderBackground.getColor().getDefaultColor();
|
||||
}
|
||||
final int initialColor = setColorAlphaBound(previewBackgroundColor,
|
||||
mPreviewBackground.getBackgroundAlpha());
|
||||
mFolderBackground.mutate();
|
||||
mFolderBackground.setColor(mIsOpening ? initialColor : finalColor);
|
||||
|
||||
@@ -193,11 +204,12 @@ public class FolderAnimationManager {
|
||||
play(a, anim);
|
||||
}
|
||||
|
||||
mBgColorAnimator = getAnimator(mFolderBackground, "color", initialColor, finalColor);
|
||||
play(a, mBgColorAnimator);
|
||||
play(a, getAnimator(mFolder, View.TRANSLATION_X, xDistance, 0f));
|
||||
play(a, getAnimator(mFolder, View.TRANSLATION_Y, yDistance, 0f));
|
||||
play(a, getAnimator(mFolder.mContent, SCALE_PROPERTY, initialScale, finalScale));
|
||||
play(a, getAnimator(mFolder.mFooter, SCALE_PROPERTY, initialScale, finalScale));
|
||||
play(a, getAnimator(mFolderBackground, "color", initialColor, finalColor));
|
||||
play(a, mFolderIcon.mFolderName.createTextAlphaAnimator(!mIsOpening));
|
||||
play(a, getShape().createRevealAnimator(
|
||||
mFolder, startRect, endRect, finalRadius, !mIsOpening));
|
||||
@@ -409,7 +421,7 @@ public class FolderAnimationManager {
|
||||
: ObjectAnimator.ofFloat(view, property, v2, v1);
|
||||
}
|
||||
|
||||
private Animator getAnimator(GradientDrawable drawable, String property, int v1, int v2) {
|
||||
private ObjectAnimator getAnimator(GradientDrawable drawable, String property, int v1, int v2) {
|
||||
return mIsOpening
|
||||
? ObjectAnimator.ofArgb(drawable, property, v1, v2)
|
||||
: ObjectAnimator.ofArgb(drawable, property, v2, v1);
|
||||
|
||||
@@ -91,9 +91,6 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
|
||||
// +1 for system shortcut view
|
||||
private static final int MAX_NUM_CHILDREN = MAX_SHORTCUTS + 1;
|
||||
// Index used to get background color when using local wallpaper color extraction,
|
||||
private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
|
||||
private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_800;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
@@ -129,7 +126,6 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
private final int[] mColors;
|
||||
private final HashMap<String, View> mViewForRect = new HashMap<>();
|
||||
|
||||
private final int mColorExtractionIndex;
|
||||
@Nullable private LocalColorExtractor mColorExtractor;
|
||||
|
||||
public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
@@ -138,9 +134,6 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
mOutlineRadius = Themes.getDialogCornerRadius(context);
|
||||
mLauncher = BaseDraggingActivity.fromContext(context);
|
||||
mIsRtl = Utilities.isRtl(getResources());
|
||||
mColorExtractionIndex = Utilities.isDarkTheme(context)
|
||||
? DARK_COLOR_EXTRACTION_INDEX
|
||||
: LIGHT_COLOR_EXTRACTION_INDEX;
|
||||
setClipToOutline(true);
|
||||
setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
import java.util.List;
|
||||
@@ -35,6 +36,10 @@ import java.util.List;
|
||||
/** Extracts the colors we need from the wallpaper at given locations. */
|
||||
public class LocalColorExtractor implements ResourceBasedOverride {
|
||||
|
||||
// Index used to get background color when using local wallpaper color extraction,
|
||||
private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
|
||||
private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_800;
|
||||
|
||||
/** Listener for color changes on a screen location. */
|
||||
public interface Listener {
|
||||
/**
|
||||
@@ -103,4 +108,13 @@ public class LocalColorExtractor implements ResourceBasedOverride {
|
||||
RectF colorExtractionRectOut) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an index used to query the color of interest from the list of extracted colors.
|
||||
*/
|
||||
public static int getColorIndex(Context context) {
|
||||
return Utilities.isDarkTheme(context)
|
||||
? DARK_COLOR_EXTRACTION_INDEX
|
||||
: LIGHT_COLOR_EXTRACTION_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user