Merge "Updating gesture tutorial home animation" into ub-launcher3-rvc-qpr-dev

This commit is contained in:
TreeHugger Robot
2020-07-09 21:44:51 +00:00
committed by Android (Google) Code Review
10 changed files with 202 additions and 142 deletions

View File

@@ -140,7 +140,6 @@ public class FallbackSwipeHandler extends
private final long mDuration;
FallbackHomeAnimationFactory(long duration) {
super(null);
mDuration = duration;
if (mRunningOverHome) {

View File

@@ -16,6 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import android.animation.AnimatorSet;
import android.content.Context;
@@ -28,6 +29,7 @@ import androidx.annotation.NonNull;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -72,36 +74,39 @@ public class LauncherSwipeHandlerV2 extends
mActivity.getRootView().setForceHideBackArrow(true);
mActivity.setHintUserWillBeActive();
homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
@Override
public RectF getWindowTargetRect() {
if (canUseWorkspaceView) {
if (canUseWorkspaceView) {
// We want the window alpha to be 0 once this threshold is met, so that the
// FolderIconView can be seen morphing into the icon shape.
float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
homeAnimFactory = new LauncherHomeAnimationFactory() {
@Override
public RectF getWindowTargetRect() {
return iconLocation;
} else {
return super.getWindowTargetRect();
}
}
@NonNull
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
// Return an empty APC here since we have an non-user controlled animation
// to home.
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
return mActivity.getStateManager().createAnimationToNewWorkspace(
NORMAL, accuracy, 0 /* animComponents */);
}
@Override
public void setAnimation(RectFSpringAnim anim) {
anim.addAnimatorListener(floatingIconView);
floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
floatingIconView.setFastFinishRunnable(anim::end);
}
@Override
public void playAtomicAnimation(float velocity) {
new StaggeredWorkspaceAnim(mActivity, velocity,
true /* animateOverviewScrim */).start();
}
};
@Override
public void update(RectF currentRect, float progress, float radius) {
floatingIconView.update(currentRect, 1f, progress, windowAlphaThreshold,
radius, false);
}
@Override
public void onCancel() {
floatingIconView.fastFinish();
}
};
} else {
homeAnimFactory = new LauncherHomeAnimationFactory();
}
} else {
homeAnimFactory = new HomeAnimationFactory(null) {
homeAnimFactory = new HomeAnimationFactory() {
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
@@ -118,4 +123,22 @@ public class LauncherSwipeHandlerV2 extends
mRecentsAnimationController.finish(
true /* toRecents */, callback, true /* sendUserLeaveHint */);
}
private class LauncherHomeAnimationFactory extends HomeAnimationFactory {
@NonNull
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
// Return an empty APC here since we have an non-user controlled animation
// to home.
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
return mActivity.getStateManager().createAnimationToNewWorkspace(
NORMAL, accuracy, 0 /* animComponents */);
}
@Override
public void playAtomicAnimation(float velocity) {
new StaggeredWorkspaceAnim(mActivity, velocity,
true /* animateOverviewScrim */).start();
}
}
}

View File

@@ -17,7 +17,6 @@ package com.android.quickstep;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import android.animation.Animator;
import android.content.Context;
@@ -28,7 +27,6 @@ import android.graphics.RectF;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.DeviceProfile;
@@ -37,7 +35,6 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -148,12 +145,6 @@ public abstract class SwipeUpAnimationLogic {
protected abstract class HomeAnimationFactory {
public FloatingIconView mIconView;
public HomeAnimationFactory(@Nullable FloatingIconView iconView) {
mIconView = iconView;
}
public @NonNull RectF getWindowTargetRect() {
PagedOrientationHandler orientationHandler = getOrientationHandler();
DeviceProfile dp = mDp;
@@ -174,6 +165,12 @@ public abstract class SwipeUpAnimationLogic {
public void playAtomicAnimation(float velocity) {
// No-op
}
public void setAnimation(RectFSpringAnim anim) { }
public void update(RectF currentRect, float progress, float radius) { }
public void onCancel() { }
}
/**
@@ -184,8 +181,6 @@ public abstract class SwipeUpAnimationLogic {
protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
HomeAnimationFactory homeAnimationFactory) {
final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
final FloatingIconView fiv = homeAnimationFactory.mIconView;
final boolean isFloatingIconView = fiv != null;
mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor);
mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
@@ -203,11 +198,7 @@ public abstract class SwipeUpAnimationLogic {
windowToHomePositionMap.mapRect(startRect);
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
if (isFloatingIconView) {
anim.addAnimatorListener(fiv);
fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
fiv.setFastFinishRunnable(anim::end);
}
homeAnimationFactory.setAnimation(anim);
SpringAnimationRunner runner = new SpringAnimationRunner(
homeAnimationFactory, cropRectF, homeToWindowPositionMap);
@@ -242,32 +233,27 @@ public abstract class SwipeUpAnimationLogic {
final RectF mWindowCurrentRect = new RectF();
final Matrix mHomeToWindowPositionMap;
final HomeAnimationFactory mAnimationFactory;
final FloatingIconView mFIV;
final AnimatorPlaybackController mHomeAnim;
final RectF mCropRectF;
final float mStartRadius;
final float mEndRadius;
final float mWindowAlphaThreshold;
SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF,
Matrix homeToWindowPositionMap) {
mAnimationFactory = factory;
mHomeAnim = factory.createActivityAnimationToHome();
mCropRectF = cropRectF;
mHomeToWindowPositionMap = homeToWindowPositionMap;
cropRectF.roundOut(mCropRect);
mFIV = factory.mIconView;
// End on a "round-enough" radius so that the shape reveal doesn't have to do too much
// rounding at the end of the animation.
mStartRadius = mTaskViewSimulator.getCurrentCornerRadius();
mEndRadius = cropRectF.width() / 2f;
// We want the window alpha to be 0 once this threshold is met, so that the
// FolderIconView can be seen morphing into the icon shape.
mWindowAlphaThreshold = mFIV != null ? 1f - SHAPE_PROGRESS_DURATION : 1f;
}
@Override
@@ -282,10 +268,7 @@ public abstract class SwipeUpAnimationLogic {
.setCornerRadius(cornerRadius);
mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this));
if (mFIV != null) {
mFIV.update(currentRect, 1f, progress,
mWindowAlphaThreshold, mMatrix.mapRadius(cornerRadius), false);
}
mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius));
}
@Override
@@ -298,9 +281,7 @@ public abstract class SwipeUpAnimationLogic {
@Override
public void onCancel() {
if (mFIV != null) {
mFIV.fastFinish();
}
mAnimationFactory.onCancel();
}
@Override

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFFFF" />
</shape>

View File

@@ -24,6 +24,14 @@
android:layout_height="match_parent"
android:background="@drawable/gesture_tutorial_ripple"/>
<com.android.launcher3.views.ClipIconView
android:id="@+id/gesture_tutorial_fake_icon_view"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/bg_circle"
android:backgroundTint="@color/gesture_tutorial_fake_task_view_color"
android:visibility="invisible" />
<View
android:id="@+id/gesture_tutorial_fake_task_view"
android:layout_width="match_parent"
@@ -41,81 +49,81 @@
android:id="@+id/gesture_tutorial_fragment_close_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="18dp"
android:layout_marginTop="30dp"
android:layout_marginStart="4dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="@android:color/transparent"
android:layout_marginStart="4dp"
android:layout_marginTop="30dp"
android:accessibilityTraversalAfter="@id/gesture_tutorial_fragment_titles_container"
android:background="@android:color/transparent"
android:contentDescription="@string/gesture_tutorial_close_button_content_description"
android:tint="?android:attr/textColorPrimary"
android:src="@drawable/gesture_tutorial_close_button"/>
android:padding="18dp"
android:src="@drawable/gesture_tutorial_close_button"
android:tint="?android:attr/textColorPrimary"/>
<LinearLayout
android:id="@+id/gesture_tutorial_fragment_titles_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="70dp"
android:layout_alignParentTop="true"
android:layout_marginTop="70dp"
android:focusable="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/gesture_tutorial_fragment_title_view"
style="@style/TextAppearance.GestureTutorial.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/gesture_tutorial_title_margin_start_end"
android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"
style="@style/TextAppearance.GestureTutorial.Title"/>
android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"/>
<TextView
android:id="@+id/gesture_tutorial_fragment_subtitle_view"
style="@style/TextAppearance.GestureTutorial.Subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="@dimen/gesture_tutorial_subtitle_margin_start_end"
android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"
style="@style/TextAppearance.GestureTutorial.Subtitle"/>
android:layout_marginTop="10dp"
android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"/>
</LinearLayout>
<TextView
android:id="@+id/gesture_tutorial_fragment_feedback_view"
style="@style/TextAppearance.GestureTutorial.Feedback"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:layout_above="@id/gesture_tutorial_fragment_action_button"
android:layout_centerHorizontal="true"
android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
style="@style/TextAppearance.GestureTutorial.Feedback"/>
android:layout_marginBottom="10dp"/>
<!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
of elevation and shadow) which is replaced by ripple effect in android:foreground -->
<Button
android:id="@+id/gesture_tutorial_fragment_action_button"
style="@style/TextAppearance.GestureTutorial.ButtonLabel"
android:layout_width="142dp"
android:layout_height="49dp"
android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
android:layout_marginBottom="48dp"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:stateListAnimator="@null"
android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
android:layout_marginBottom="48dp"
android:background="@drawable/gesture_tutorial_action_button_background"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
style="@style/TextAppearance.GestureTutorial.ButtonLabel"/>
android:stateListAnimator="@null"/>
<Button
android:id="@+id/gesture_tutorial_fragment_action_text_button"
style="@style/TextAppearance.GestureTutorial.TextButtonLabel"
android:layout_width="142dp"
android:layout_height="49dp"
android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
android:layout_marginBottom="48dp"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:stateListAnimator="@null"
android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
android:layout_marginBottom="48dp"
android:background="@null"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
style="@style/TextAppearance.GestureTutorial.TextButtonLabel"/>
android:stateListAnimator="@null"/>
</RelativeLayout>

View File

@@ -17,6 +17,7 @@ package com.android.quickstep.interaction;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.quickstep.BaseSwipeUpHandlerV2.MAX_SWIPE_DURATION;
import static com.android.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE;
import static com.android.quickstep.interaction.TutorialController.TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
@@ -110,6 +111,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
AnimatorListenerAdapter resetTaskView = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation, boolean isReverse) {
mFakeIconView.setVisibility(View.INVISIBLE);
mFakeTaskView.setVisibility(View.INVISIBLE);
mFakeTaskView.setAlpha(1);
mRunningWindowAnim = null;
@@ -131,6 +133,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
});
} else {
anim.setViewAlpha(mFakeTaskView, 0, ACCEL);
anim.setViewAlpha(mFakeIconView, 0, ACCEL);
anim.addListener(resetTaskView);
}
if (onEndRunnable != null) {
@@ -202,7 +205,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
// derivative of the scroll interpolator at zero, ie. 2.
long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
long duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
HomeAnimationFactory homeAnimFactory = new HomeAnimationFactory(null) {
HomeAnimationFactory homeAnimFactory = new HomeAnimationFactory() {
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
@@ -218,6 +221,24 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
fakeHomeIconLeft + fakeHomeIconSizePx,
fakeHomeIconTop + fakeHomeIconSizePx);
}
@Override
public void update(RectF rect, float progress, float radius) {
mFakeIconView.setVisibility(View.VISIBLE);
mFakeIconView.update(rect, progress,
1f - SHAPE_PROGRESS_DURATION /* shapeProgressStart */,
radius,
false, /* isOpening */
mFakeIconView, mDp,
false /* isVerticalBarLayout */);
mFakeIconView.setAlpha(1);
mFakeTaskView.setAlpha(getWindowAlpha(progress));
}
@Override
public void onCancel() {
mFakeIconView.setVisibility(View.INVISIBLE);
}
};
RectFSpringAnim windowAnim = createWindowAnimationToHome(startShift, homeAnimFactory);
windowAnim.start(mContext, velocityPxPerMs);

View File

@@ -28,6 +28,7 @@ import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
import com.android.launcher3.views.ClipIconView;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureAttemptCallback;
@@ -46,6 +47,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
final TextView mTitleTextView;
final TextView mSubtitleTextView;
final TextView mFeedbackView;
final ClipIconView mFakeIconView;
final View mFakeTaskView;
final View mRippleView;
final RippleDrawable mRippleDrawable;
@@ -66,6 +68,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view);
mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
mRippleDrawable = (RippleDrawable) mRippleView.getBackground();

View File

@@ -36,6 +36,7 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewOutlineProvider;
import androidx.annotation.Nullable;
@@ -44,8 +45,6 @@ import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
@@ -94,7 +93,6 @@ public class ClipIconView extends View implements ClipPathView {
}
};
private final Launcher mLauncher;
private final int mBlurSizeOutline;
private final boolean mIsRtl;
@@ -128,7 +126,6 @@ public class ClipIconView extends View implements ClipPathView {
public ClipIconView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mLauncher = Launcher.getLauncher(context);
mBlurSizeOutline = getResources().getDimensionPixelSize(
R.dimen.blur_size_medium_outline);
mIsRtl = Utilities.isRtl(getResources());
@@ -143,10 +140,41 @@ public class ClipIconView extends View implements ClipPathView {
.setStiffness(SpringForce.STIFFNESS_LOW));
}
void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
boolean isOpening, float scale, float minSize, LayoutParams parentLp,
boolean isVerticalBarLayout) {
DeviceProfile dp = mLauncher.getDeviceProfile();
/**
* Update the icon UI to match the provided parameters during an animation frame
*/
public void update(RectF rect, float progress, float shapeProgressStart,
float cornerRadius, boolean isOpening, View container,
DeviceProfile dp, boolean isVerticalBarLayout) {
MarginLayoutParams lp = (MarginLayoutParams) container.getLayoutParams();
float dX = mIsRtl
? rect.left - (dp.widthPx - lp.getMarginStart() - lp.width)
: rect.left - lp.getMarginStart();
float dY = rect.top - lp.topMargin;
container.setTranslationX(dX);
container.setTranslationY(dY);
float minSize = Math.min(lp.width, lp.height);
float scaleX = rect.width() / minSize;
float scaleY = rect.height() / minSize;
float scale = Math.max(1f, Math.min(scaleX, scaleY));
update(rect, progress, shapeProgressStart, cornerRadius, isOpening, scale,
minSize, lp, isVerticalBarLayout, dp);
container.setPivotX(0);
container.setPivotY(0);
container.setScaleX(scale);
container.setScaleY(scale);
container.invalidate();
}
private void update(RectF rect, float progress, float shapeProgressStart, float cornerRadius,
boolean isOpening, float scale, float minSize, MarginLayoutParams parentLp,
boolean isVerticalBarLayout, DeviceProfile dp) {
float dX = mIsRtl
? rect.left - (dp.widthPx - parentLp.getMarginStart() - parentLp.width)
: rect.left - parentLp.getMarginStart();
@@ -228,8 +256,11 @@ public class ClipIconView extends View implements ClipPathView {
}
}
void setIcon(@Nullable Drawable drawable, int iconOffset, LayoutParams lp, boolean isOpening,
boolean isVerticalBarLayout) {
/**
* Sets the icon for this view as part of initial setup
*/
public void setIcon(@Nullable Drawable drawable, int iconOffset, MarginLayoutParams lp,
boolean isOpening, boolean isVerticalBarLayout, DeviceProfile dp) {
mIsAdaptiveIcon = drawable instanceof AdaptiveIconDrawable;
if (mIsAdaptiveIcon) {
boolean isFolderIcon = drawable instanceof FolderAdaptiveIcon;
@@ -264,15 +295,14 @@ public class ClipIconView extends View implements ClipPathView {
Utilities.scaleRectAboutCenter(mStartRevealRect, IconShape.getNormalizationScale());
}
float aspectRatio = mLauncher.getDeviceProfile().aspectRatio;
if (isVerticalBarLayout) {
lp.width = (int) Math.max(lp.width, lp.height * aspectRatio);
lp.width = (int) Math.max(lp.width, lp.height * dp.aspectRatio);
} else {
lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
lp.height = (int) Math.max(lp.height, lp.width * dp.aspectRatio);
}
int left = mIsRtl
? mLauncher.getDeviceProfile().widthPx - lp.getMarginStart() - lp.width
? dp.widthPx - lp.getMarginStart() - lp.width
: lp.leftMargin;
layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height);

View File

@@ -20,6 +20,7 @@ import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.Utilities.getFullDrawable;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -47,7 +48,6 @@ import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
@@ -144,32 +144,8 @@ public class FloatingIconView extends FrameLayout implements
public void update(RectF rect, float alpha, float progress, float shapeProgressStart,
float cornerRadius, boolean isOpening) {
setAlpha(alpha);
InsettableFrameLayout.LayoutParams lp =
(InsettableFrameLayout.LayoutParams) getLayoutParams();
DeviceProfile dp = mLauncher.getDeviceProfile();
float dX = mIsRtl
? rect.left - (dp.widthPx - lp.getMarginStart() - lp.width)
: rect.left - lp.getMarginStart();
float dY = rect.top - lp.topMargin;
setTranslationX(dX);
setTranslationY(dY);
float minSize = Math.min(lp.width, lp.height);
float scaleX = rect.width() / minSize;
float scaleY = rect.height() / minSize;
float scale = Math.max(1f, Math.min(scaleX, scaleY));
mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, isOpening, scale,
minSize, lp, mIsVerticalBarLayout);
setPivotX(0);
setPivotY(0);
setScaleX(scale);
setScaleY(scale);
invalidate();
mClipIconView.update(rect, progress, shapeProgressStart, cornerRadius, isOpening,
this, mLauncher.getDeviceProfile(), mIsVerticalBarLayout);
}
@Override
@@ -336,7 +312,8 @@ public class FloatingIconView extends FrameLayout implements
final InsettableFrameLayout.LayoutParams lp =
(InsettableFrameLayout.LayoutParams) getLayoutParams();
mBadge = badge;
mClipIconView.setIcon(drawable, iconOffset, lp, mIsOpening, mIsVerticalBarLayout);
mClipIconView.setIcon(drawable, iconOffset, lp, mIsOpening, mIsVerticalBarLayout,
mLauncher.getDeviceProfile());
if (drawable instanceof AdaptiveIconDrawable) {
final int originalHeight = lp.height;
final int originalWidth = lp.width;
@@ -381,7 +358,7 @@ public class FloatingIconView extends FrameLayout implements
if (mIconLoadResult.isIconLoaded) {
setIcon(mIconLoadResult.drawable, mIconLoadResult.badge,
mIconLoadResult.iconOffset);
hideOriginalView(originalView);
setIconAndDotVisible(originalView, false);
} else {
mIconLoadResult.onIconLoaded = () -> {
if (cancellationSignal.isCanceled()) {
@@ -392,22 +369,13 @@ public class FloatingIconView extends FrameLayout implements
mIconLoadResult.iconOffset);
setVisibility(VISIBLE);
hideOriginalView(originalView);
setIconAndDotVisible(originalView, false);
};
mLoadIconSignal = cancellationSignal;
}
}
}
private void hideOriginalView(View originalView) {
if (originalView instanceof IconLabelDotView) {
((IconLabelDotView) originalView).setIconVisible(false);
((IconLabelDotView) originalView).setForceHideDot(true);
} else {
originalView.setVisibility(INVISIBLE);
}
}
@WorkerThread
@SuppressWarnings("WrongThread")
private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) {
@@ -477,7 +445,7 @@ public class FloatingIconView extends FrameLayout implements
}
if (!mIsOpening) {
// When closing an app, we want the item on the workspace to be invisible immediately
hideOriginalView(mOriginalIcon);
setIconAndDotVisible(mOriginalIcon, false);
}
}
@@ -573,12 +541,7 @@ public class FloatingIconView extends FrameLayout implements
if (hideOriginal) {
if (isOpening) {
if (originalView instanceof BubbleTextView) {
((BubbleTextView) originalView).setIconVisible(true);
((BubbleTextView) originalView).setForceHideDot(false);
} else {
originalView.setVisibility(VISIBLE);
}
setIconAndDotVisible(originalView, true);
view.finish(dragLayer);
} else {
view.mFadeAnimatorSet = view.createFadeAnimation(originalView, dragLayer);
@@ -615,12 +578,10 @@ public class FloatingIconView extends FrameLayout implements
});
if (originalView instanceof IconLabelDotView) {
IconLabelDotView view = (IconLabelDotView) originalView;
fade.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setIconVisible(true);
view.setForceHideDot(false);
setIconAndDotVisible(originalView, true);
}
});
}

View File

@@ -15,10 +15,24 @@
*/
package com.android.launcher3.views;
import android.view.View;
/**
* A view that has an icon, label, and notification dot.
*/
public interface IconLabelDotView {
void setIconVisible(boolean visible);
void setForceHideDot(boolean hide);
/**
* Sets the visibility of icon and dot of the view
*/
static void setIconAndDotVisible(View view, boolean visible) {
if (view instanceof IconLabelDotView) {
((IconLabelDotView) view).setIconVisible(visible);
((IconLabelDotView) view).setForceHideDot(!visible);
} else {
view.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
}
}
}