Merge "resolve merge conflicts of 1bd96b1e96 to ub-launcher3-qt-future-dev" into ub-launcher3-qt-future-dev

This commit is contained in:
TreeHugger Robot
2019-09-09 20:47:27 +00:00
committed by Android (Google) Code Review
8 changed files with 134 additions and 51 deletions
@@ -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
+2 -2
View File
@@ -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);
}