Fix bug with flickering actions bar

This CL fixes a bug caused by ag/27148514. The bug occurred because:

1) The new way we use FloatProperty to set the alpha did not have a working `get()` function, so it just returned a junk value, set to `-1f` (I didn't think `get()` would ever be called meaningfully for this property).

2) However, during certain UI interactions, `RecentsView#updateActionsViewFocusedScroll()` is called many times in a loop, which repeatedly tries to re-start the fade-in animation for actions bar. Pre ag/27148514, even though the fade-in animation was called repeatedly, it would start and then immediately stop running because it realized that it was already set to the desired alpha. However now that we return a junk value for `get()`, it didn't know to skip and just ran the full fade-in animation again and again.

Fixed by refactoring FLOAT_SETTER (now ALPHA_PROPERTY) and creating a new data class, OverviewActionsAlphaProperty, that handles some of the intricacies of this increasingly complicated alpha system.

Fixes: 339545510
Test: Swipe to Overview, move tiles around, actions bar does not flicker.
Flag: ACONFIG com.android.wm.shell.enable_app_pairs NEXTFOOD
Change-Id: I1093363780db5e0780deda2ff14b4f7361d63940
Merged-In: I1093363780db5e0780deda2ff14b4f7361d63940
This commit is contained in:
Jeremy Sim
2024-05-09 15:49:23 -07:00
parent 740a52a27c
commit ee9e655c5c
5 changed files with 43 additions and 42 deletions

View File

@@ -40,6 +40,7 @@ import androidx.annotation.NonNull;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
@@ -167,8 +168,8 @@ public final class RecentsViewStateController extends
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0;
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlphaSetter(),
OverviewActionsView.FLOAT_SETTER, overviewButtonAlpha, config.getInterpolator(
propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
AnimatedFloat.VALUE, overviewButtonAlpha, config.getInterpolator(
ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
}

View File

@@ -254,7 +254,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, fromState.showTaskThumbnailSplash() ? 1f : 0);
mRecentsView.setContentAlpha(1);
mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress());
mLauncher.getActionsView().getVisibilityAlphaSetter().accept(
mLauncher.getActionsView().getVisibilityAlpha().updateValue(
(fromState.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0 ? 1f : 0f);
mRecentsView.setTaskIconScaledDown(true);

View File

@@ -42,13 +42,13 @@ import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.OverviewActionsView;
/**
* State controller for fallback recents activity
@@ -95,8 +95,8 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
setter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
clearAllButtonAlpha, LINEAR);
float overviewButtonAlpha = state.hasOverviewActions() ? 1 : 0;
setter.setFloat(mActivity.getActionsView().getVisibilityAlphaSetter(),
OverviewActionsView.FLOAT_SETTER, overviewButtonAlpha, LINEAR);
setter.setFloat(mActivity.getActionsView().getVisibilityAlpha(),
AnimatedFloat.VALUE, overviewButtonAlpha, LINEAR);
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mActivity);
setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0],

View File

@@ -34,6 +34,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.NavigationMode;
@@ -42,27 +43,14 @@ import com.android.quickstep.util.LayoutUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.function.Consumer;
/**
* View for showing action buttons in Overview
*/
public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayout
implements OnClickListener, Insettable {
public static final FloatProperty<Consumer<Float>> FLOAT_SETTER =
new FloatProperty<>("floatSetter") {
@Override
public void setValue(Consumer<Float> consumer, float v) {
consumer.accept(v);
}
@Override
public Float get(Consumer<Float> consumer) {
return -1f;
}
};
private final Rect mInsets = new Rect();
@IntDef(flag = true, value = {
@@ -109,7 +97,13 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
public @interface SplitButtonHiddenFlags { }
public static final int FLAG_SMALL_SCREEN_HIDE_SPLIT = 1 << 0;
/** Holds MultiValueAlpha values for all actions buttons */
/**
* Holds an AnimatedFloat for each alpha property, used to set or animate alpha values in
* {@link #mMultiValueAlphas}.
*/
private final AnimatedFloat[] mAlphaProperties = new AnimatedFloat[NUM_ALPHAS];
/** Holds MultiValueAlpha values for all actions bars */
private final MultiValueAlpha[] mMultiValueAlphas = new MultiValueAlpha[2];
/** Index used for single-task actions in the mMultiValueAlphas array */
private static final int ACTIONS_ALPHAS = 0;
@@ -159,11 +153,21 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
// These will take up the same space on the screen and alternate visibility as needed.
mActionButtons = findViewById(R.id.action_buttons);
mGroupActionButtons = findViewById(R.id.group_action_buttons);
// Initialize a list to set alpha on mActionButtons and mGroupActionButtons simultaneously.
// Initialize a list to hold alphas for mActionButtons and mGroupActionButtons.
mMultiValueAlphas[ACTIONS_ALPHAS] = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
mMultiValueAlphas[GROUP_ACTIONS_ALPHAS] =
new MultiValueAlpha(mGroupActionButtons, NUM_ALPHAS);
Arrays.stream(mMultiValueAlphas).forEach(a -> a.setUpdateVisibility(true));
// To control alpha simultaneously on mActionButtons and mGroupActionButtons, we set up an
// AnimatedFloat for each alpha property.
for (int i = 0; i < NUM_ALPHAS; i++) {
final int index = i;
mAlphaProperties[index] = new AnimatedFloat(() -> {
for (MultiValueAlpha multiValueAlpha : mMultiValueAlphas) {
multiValueAlpha.get(index).setValue(mAlphaProperties[index].value);
}
}, 1f /* initialValue */);
}
// The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is
// an ImageButton in go launcher (does not share a common class with Button). Take care when
@@ -220,7 +224,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
mHiddenFlags &= ~visibilityFlags;
}
boolean isHidden = mHiddenFlags != 0;
setActionsAlpha(INDEX_HIDDEN_FLAGS_ALPHA, isHidden ? 0 : 1);
mAlphaProperties[INDEX_HIDDEN_FLAGS_ALPHA].updateValue(isHidden ? 0 : 1);
}
/**
@@ -305,28 +309,24 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
}
}
private void setActionsAlpha(int index, float value) {
Arrays.stream(mMultiValueAlphas).forEach(a -> a.get(index).setValue(value));
public AnimatedFloat getContentAlpha() {
return mAlphaProperties[INDEX_CONTENT_ALPHA];
}
public Consumer<Float> getContentAlphaSetter() {
return v -> setActionsAlpha(INDEX_CONTENT_ALPHA, v);
public AnimatedFloat getVisibilityAlpha() {
return mAlphaProperties[INDEX_VISIBILITY_ALPHA];
}
public Consumer<Float> getVisibilityAlphaSetter() {
return v -> setActionsAlpha(INDEX_VISIBILITY_ALPHA, v);
public AnimatedFloat getFullscreenAlpha() {
return mAlphaProperties[INDEX_FULLSCREEN_ALPHA];
}
public Consumer<Float> getFullscreenAlphaSetter() {
return v -> setActionsAlpha(INDEX_FULLSCREEN_ALPHA, v);
public AnimatedFloat getShareTargetAlpha() {
return mAlphaProperties[INDEX_SHARE_TARGET_ALPHA];
}
public Consumer<Float> getShareTargetAlphaSetter() {
return v -> setActionsAlpha(INDEX_SHARE_TARGET_ALPHA, v);
}
public Consumer<Float> getIndexScrollAlphaSetter() {
return v -> setActionsAlpha(INDEX_SCROLL_ALPHA, v);
public AnimatedFloat getIndexScrollAlpha() {
return mAlphaProperties[INDEX_SCROLL_ALPHA];
}
/**

View File

@@ -2025,7 +2025,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mClearAllButton.setFullscreenProgress(fullscreenProgress);
// Fade out the actions view quickly (0.1 range)
mActionsView.getFullscreenAlphaSetter().accept(
mActionsView.getFullscreenAlpha().updateValue(
mapToRange(fullscreenProgress, 0, 0.1f, 1f, 0f, LINEAR));
}
@@ -2284,8 +2284,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
}
private void animateActionsViewAlpha(float alphaValue, long duration) {
mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(mActionsView.getVisibilityAlphaSetter(),
OverviewActionsView.FLOAT_SETTER, alphaValue);
mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(mActionsView.getVisibilityAlpha(),
AnimatedFloat.VALUE, alphaValue);
mActionsViewAlphaAnimatorFinalValue = alphaValue;
mActionsViewAlphaAnimator.setDuration(duration);
// Set autocancel to prevent race-conditiony setting of alpha from other animations
@@ -2304,7 +2304,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mClearAllButton.onRecentsViewScroll(scroll, mOverviewGridEnabled);
// Clear all button alpha was set by the previous line.
mActionsView.getIndexScrollAlphaSetter().accept(1 - mClearAllButton.getScrollAlpha());
mActionsView.getIndexScrollAlpha().updateValue(1 - mClearAllButton.getScrollAlpha());
}
@Override
@@ -4312,7 +4312,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int alphaInt = Math.round(alpha * 255);
mEmptyMessagePaint.setAlpha(alphaInt);
mEmptyIcon.setAlpha(alphaInt);
mActionsView.getContentAlphaSetter().accept(mContentAlpha);
mActionsView.getContentAlpha().updateValue(mContentAlpha);
if (alpha > 0) {
setVisibility(VISIBLE);