Merge "resolve merge conflicts of 1bd96b1e96 to ub-launcher3-qt-future-dev" into ub-launcher3-qt-future-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0a07dfa25d
+43
-12
@@ -29,6 +29,7 @@ import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
@@ -40,7 +41,9 @@ import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.PropertySetter;
|
||||
import com.android.launcher3.anim.SpringObjectAnimator;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -62,7 +65,9 @@ public class StaggeredWorkspaceAnim {
|
||||
|
||||
private final float mVelocity;
|
||||
private final float mSpringTransY;
|
||||
private final View mViewToIgnore;
|
||||
|
||||
// The original view of the {@link FloatingIconView}.
|
||||
private final View mOriginalView;
|
||||
|
||||
private final List<Animator> mAnimators = new ArrayList<>();
|
||||
|
||||
@@ -72,9 +77,7 @@ public class StaggeredWorkspaceAnim {
|
||||
public StaggeredWorkspaceAnim(Launcher launcher, @Nullable View floatingViewOriginalView,
|
||||
float velocity) {
|
||||
mVelocity = velocity;
|
||||
// We ignore this view since it's visibility and position is controlled by
|
||||
// the FloatingIconView.
|
||||
mViewToIgnore = floatingViewOriginalView;
|
||||
mOriginalView = floatingViewOriginalView;
|
||||
|
||||
// Scale the translationY based on the initial velocity to better sync the workspace items
|
||||
// with the floating view.
|
||||
@@ -86,16 +89,21 @@ public class StaggeredWorkspaceAnim {
|
||||
Workspace workspace = launcher.getWorkspace();
|
||||
CellLayout cellLayout = (CellLayout) workspace.getChildAt(workspace.getCurrentPage());
|
||||
ShortcutAndWidgetContainer currentPage = cellLayout.getShortcutsAndWidgets();
|
||||
ViewGroup hotseat = launcher.getHotseat();
|
||||
|
||||
boolean workspaceClipChildren = workspace.getClipChildren();
|
||||
boolean workspaceClipToPadding = workspace.getClipToPadding();
|
||||
boolean cellLayoutClipChildren = cellLayout.getClipChildren();
|
||||
boolean cellLayoutClipToPadding = cellLayout.getClipToPadding();
|
||||
boolean hotseatClipChildren = hotseat.getClipChildren();
|
||||
boolean hotseatClipToPadding = hotseat.getClipToPadding();
|
||||
|
||||
workspace.setClipChildren(false);
|
||||
workspace.setClipToPadding(false);
|
||||
cellLayout.setClipChildren(false);
|
||||
cellLayout.setClipToPadding(false);
|
||||
hotseat.setClipChildren(false);
|
||||
hotseat.setClipToPadding(false);
|
||||
|
||||
// Hotseat and QSB takes up two additional rows.
|
||||
int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
|
||||
@@ -108,16 +116,18 @@ public class StaggeredWorkspaceAnim {
|
||||
}
|
||||
|
||||
// Set up springs for the hotseat and qsb.
|
||||
ViewGroup hotseatChild = (ViewGroup) hotseat.getChildAt(0);
|
||||
if (grid.isVerticalBarLayout()) {
|
||||
ViewGroup hotseat = (ViewGroup) launcher.getHotseat().getChildAt(0);
|
||||
for (int i = hotseat.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = hotseat.getChildAt(i);
|
||||
for (int i = hotseatChild.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = hotseatChild.getChildAt(i);
|
||||
CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
|
||||
addStaggeredAnimationForView(child, lp.cellY + 1, totalRows);
|
||||
}
|
||||
} else {
|
||||
View hotseat = launcher.getHotseat().getChildAt(0);
|
||||
addStaggeredAnimationForView(hotseat, grid.inv.numRows + 1, totalRows);
|
||||
for (int i = hotseatChild.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = hotseatChild.getChildAt(i);
|
||||
addStaggeredAnimationForView(child, grid.inv.numRows + 1, totalRows);
|
||||
}
|
||||
|
||||
View qsb = launcher.findViewById(R.id.search_container_all_apps);
|
||||
addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
|
||||
@@ -140,6 +150,8 @@ public class StaggeredWorkspaceAnim {
|
||||
workspace.setClipToPadding(workspaceClipToPadding);
|
||||
cellLayout.setClipChildren(cellLayoutClipChildren);
|
||||
cellLayout.setClipToPadding(cellLayoutClipToPadding);
|
||||
hotseat.setClipChildren(hotseatClipChildren);
|
||||
hotseat.setClipToPadding(hotseatClipToPadding);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -180,16 +192,35 @@ public class StaggeredWorkspaceAnim {
|
||||
springTransY.setStartDelay(startDelay);
|
||||
mAnimators.add(springTransY);
|
||||
|
||||
if (v == mViewToIgnore) {
|
||||
return;
|
||||
ObjectAnimator alpha = getAlphaAnimator(v, startDelay);
|
||||
if (v == mOriginalView) {
|
||||
// For IconLabelDotViews, we just want the label to fade in.
|
||||
// Icon, badge, and dots will animate in separately (controlled via FloatingIconView)
|
||||
if (v instanceof IconLabelDotView) {
|
||||
alpha.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
IconLabelDotView view = (IconLabelDotView) v;
|
||||
view.setIconVisible(false);
|
||||
view.setForceHideDot(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
v.setAlpha(0);
|
||||
mAnimators.add(alpha);
|
||||
}
|
||||
|
||||
private ObjectAnimator getAlphaAnimator(View v, long startDelay) {
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
|
||||
alpha.setInterpolator(LINEAR);
|
||||
alpha.setDuration(ALPHA_DURATION_MS);
|
||||
alpha.setStartDelay(startDelay);
|
||||
mAnimators.add(alpha);
|
||||
return alpha;
|
||||
|
||||
}
|
||||
|
||||
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils.TruncateAt;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
@@ -54,8 +53,8 @@ import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.IconCache.IconLoadRequest;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
@@ -64,7 +63,8 @@ import java.text.NumberFormat;
|
||||
* because we want to make the bubble taller than the text and TextView's clip is
|
||||
* too aggressive.
|
||||
*/
|
||||
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback {
|
||||
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback,
|
||||
IconLabelDotView {
|
||||
|
||||
private static final int DISPLAY_WORKSPACE = 0;
|
||||
private static final int DISPLAY_ALL_APPS = 1;
|
||||
@@ -413,7 +413,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
public void forceHideDot(boolean forceHideDot) {
|
||||
@Override
|
||||
public void setForceHideDot(boolean forceHideDot) {
|
||||
if (mForceHideDot == forceHideDot) {
|
||||
return;
|
||||
}
|
||||
@@ -602,6 +603,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIconVisible(boolean visible) {
|
||||
mIsIconVisible = visible;
|
||||
Drawable icon = visible ? mIcon : new ColorDrawable(Color.TRANSPARENT);
|
||||
|
||||
@@ -142,8 +142,11 @@ public class FastBitmapDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mAlpha = alpha;
|
||||
mPaint.setAlpha(alpha);
|
||||
if (mAlpha != alpha) {
|
||||
mAlpha = alpha;
|
||||
mPaint.setAlpha(alpha);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -538,7 +538,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mFolderIcon.setBackgroundVisible(false);
|
||||
mFolderIcon.setIconVisible(false);
|
||||
mFolderIcon.drawLeaveBehindIfExists();
|
||||
}
|
||||
@Override
|
||||
@@ -658,7 +658,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
clearFocus();
|
||||
if (mFolderIcon != null) {
|
||||
mFolderIcon.setVisibility(View.VISIBLE);
|
||||
mFolderIcon.setBackgroundVisible(true);
|
||||
mFolderIcon.setIconVisible(true);
|
||||
mFolderIcon.mFolderName.setTextVisibility(true);
|
||||
if (wasAnimated) {
|
||||
mFolderIcon.animateBgShadowAndStroke();
|
||||
|
||||
@@ -65,6 +65,7 @@ import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -74,7 +75,7 @@ import java.util.function.Predicate;
|
||||
/**
|
||||
* An icon that can appear on in the workspace representing an {@link Folder}.
|
||||
*/
|
||||
public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
public class FolderIcon extends FrameLayout implements FolderListener, IconLabelDotView {
|
||||
|
||||
@Thunk Launcher mLauncher;
|
||||
@Thunk Folder mFolder;
|
||||
@@ -108,6 +109,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
|
||||
private Alarm mOpenAlarm = new Alarm();
|
||||
|
||||
private boolean mForceHideDot;
|
||||
@ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
|
||||
private FolderDotInfo mDotInfo = new FolderDotInfo();
|
||||
private DotRenderer mDotRenderer;
|
||||
@@ -404,6 +406,20 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
return mPreviewLayoutRule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceHideDot(boolean forceHideDot) {
|
||||
if (mForceHideDot == forceHideDot) {
|
||||
return;
|
||||
}
|
||||
mForceHideDot = forceHideDot;
|
||||
|
||||
if (forceHideDot) {
|
||||
invalidate();
|
||||
} else if (hasDot()) {
|
||||
animateDotScale(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets mDotScale to 1 or 0, animating if wasDotted or isDotted is false
|
||||
* (the dot is being added or removed).
|
||||
@@ -463,7 +479,8 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
mBackground.setInvalidateDelegate(this);
|
||||
}
|
||||
|
||||
public void setBackgroundVisible(boolean visible) {
|
||||
@Override
|
||||
public void setIconVisible(boolean visible) {
|
||||
mBackgroundIsVisible = visible;
|
||||
invalidate();
|
||||
}
|
||||
@@ -503,7 +520,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
|
||||
}
|
||||
|
||||
public void drawDot(Canvas canvas) {
|
||||
if ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0) {
|
||||
if (!mForceHideDot && ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0)) {
|
||||
Rect iconBounds = mDotParams.iconBounds;
|
||||
BubbleTextView.getIconBounds(this, iconBounds,
|
||||
mLauncher.getWallpaperDeviceProfile().iconSizePx);
|
||||
|
||||
@@ -300,7 +300,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
|
||||
}
|
||||
|
||||
mLauncher.getDragController().addDragListener(this);
|
||||
mOriginalIcon.forceHideDot(true);
|
||||
mOriginalIcon.setForceHideDot(true);
|
||||
|
||||
// All views are added. Animate layout from now on.
|
||||
setLayoutTransition(new LayoutTransition());
|
||||
@@ -562,13 +562,13 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
|
||||
protected void onCreateCloseAnimation(AnimatorSet anim) {
|
||||
// Animate original icon's text back in.
|
||||
anim.play(mOriginalIcon.createTextAlphaAnimator(true /* fadeIn */));
|
||||
mOriginalIcon.forceHideDot(false);
|
||||
mOriginalIcon.setForceHideDot(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeComplete() {
|
||||
mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible());
|
||||
mOriginalIcon.forceHideDot(false);
|
||||
mOriginalIcon.setForceHideDot(false);
|
||||
super.closeComplete();
|
||||
}
|
||||
|
||||
|
||||
@@ -562,11 +562,6 @@ public class FloatingIconView extends View implements
|
||||
*/
|
||||
private void checkIconResult(View originalView, boolean isOpening) {
|
||||
CancellationSignal cancellationSignal = new CancellationSignal();
|
||||
if (!isOpening) {
|
||||
// Hide immediately since the floating view starts at a different location.
|
||||
originalView.setVisibility(INVISIBLE);
|
||||
cancellationSignal.setOnCancelListener(() -> originalView.setVisibility(VISIBLE));
|
||||
}
|
||||
|
||||
if (mIconLoadResult == null) {
|
||||
Log.w(TAG, "No icon load result found in checkIconResult");
|
||||
@@ -578,7 +573,7 @@ public class FloatingIconView extends View implements
|
||||
setIcon(originalView, mIconLoadResult.drawable, mIconLoadResult.badge,
|
||||
mIconLoadResult.iconOffset);
|
||||
if (isOpening) {
|
||||
originalView.setVisibility(INVISIBLE);
|
||||
hideOriginalView(originalView);
|
||||
}
|
||||
} else {
|
||||
mIconLoadResult.onIconLoaded = () -> {
|
||||
@@ -589,15 +584,26 @@ public class FloatingIconView extends View implements
|
||||
setIcon(originalView, mIconLoadResult.drawable, mIconLoadResult.badge,
|
||||
mIconLoadResult.iconOffset);
|
||||
|
||||
// Delay swapping views until the icon is loaded to prevent a flash.
|
||||
setVisibility(VISIBLE);
|
||||
originalView.setVisibility(INVISIBLE);
|
||||
if (isOpening) {
|
||||
// Delay swapping views until the icon is loaded to prevent a flash.
|
||||
hideOriginalView(originalView);
|
||||
}
|
||||
};
|
||||
mLoadIconSignal = cancellationSignal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideOriginalView(View originalView) {
|
||||
if (originalView instanceof BubbleTextView) {
|
||||
((BubbleTextView) originalView).setIconVisible(false);
|
||||
((BubbleTextView) originalView).setForceHideDot(true);
|
||||
} else {
|
||||
originalView.setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setBackgroundDrawableBounds(float scale) {
|
||||
sTmpRect.set(mFinalDrawableBounds);
|
||||
Utilities.scaleRectAboutCenter(sTmpRect, scale);
|
||||
@@ -774,7 +780,12 @@ public class FloatingIconView extends View implements
|
||||
|
||||
if (hideOriginal) {
|
||||
if (isOpening) {
|
||||
originalView.setVisibility(VISIBLE);
|
||||
if (originalView instanceof BubbleTextView) {
|
||||
((BubbleTextView) originalView).setIconVisible(true);
|
||||
((BubbleTextView) originalView).setForceHideDot(false);
|
||||
} else {
|
||||
originalView.setVisibility(VISIBLE);
|
||||
}
|
||||
view.finish(dragLayer);
|
||||
} else {
|
||||
view.mFadeAnimatorSet = view.createFadeAnimation(originalView, dragLayer);
|
||||
@@ -802,38 +813,33 @@ public class FloatingIconView extends View implements
|
||||
}
|
||||
});
|
||||
|
||||
if (mBadge != null && !(mOriginalIcon instanceof FolderIcon)) {
|
||||
if (mBadge != null) {
|
||||
ObjectAnimator badgeFade = ObjectAnimator.ofInt(mBadge, DRAWABLE_ALPHA, 255);
|
||||
badgeFade.addUpdateListener(valueAnimator -> invalidate());
|
||||
fade.play(badgeFade);
|
||||
}
|
||||
|
||||
if (originalView instanceof BubbleTextView) {
|
||||
BubbleTextView btv = (BubbleTextView) originalView;
|
||||
btv.forceHideDot(true);
|
||||
if (originalView instanceof IconLabelDotView) {
|
||||
IconLabelDotView view = (IconLabelDotView) originalView;
|
||||
fade.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
btv.forceHideDot(false);
|
||||
view.setIconVisible(true);
|
||||
view.setForceHideDot(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (originalView instanceof FolderIcon) {
|
||||
FolderIcon folderIcon = (FolderIcon) originalView;
|
||||
folderIcon.setBackgroundVisible(false);
|
||||
folderIcon.getFolderName().setTextVisibility(false);
|
||||
fade.play(folderIcon.getFolderName().createTextAlphaAnimator(true));
|
||||
if (originalView instanceof BubbleTextView) {
|
||||
BubbleTextView btv = (BubbleTextView) originalView;
|
||||
fade.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
folderIcon.setBackgroundVisible(true);
|
||||
if (folderIcon.hasDot()) {
|
||||
folderIcon.animateDotScale(0, 1f);
|
||||
}
|
||||
public void onAnimationStart(Animator animation) {
|
||||
btv.setIconVisible(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fade.play(ObjectAnimator.ofInt(btv.getIcon(), DRAWABLE_ALPHA, 0, 255));
|
||||
} else if (!(originalView instanceof FolderIcon)) {
|
||||
fade.play(ObjectAnimator.ofFloat(originalView, ALPHA, 0f, 1f));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
/**
|
||||
* A view that has an icon, label, and notification dot.
|
||||
*/
|
||||
public interface IconLabelDotView {
|
||||
void setIconVisible(boolean visible);
|
||||
void setForceHideDot(boolean hide);
|
||||
}
|
||||
Reference in New Issue
Block a user