Hide animated ghost when underlying view is detached from window.
This mirrors the behavior that we have when the view is made INVISIBLE/GONE. The need for this change is that a view can be detached with its visibility remaining VISIBLE, in which case the updated location of the animated ghost become (0,0), which makes the transition look jumpy and broken. Note that this also disables dismiss animations for the MediaOutputDialog when the "Stop casting" button is tapped, since we know that the notification will go away but can't rely on the timing of it. Disabling the animation makes the dialog fade away in place instead, so it has a reliable transition. Fix: 232542592 Flag: N/A Test: see before/after videos in the bug Change-Id: Ieba6a2f5681ad7143c2f14b59f0309f658d66ce9
This commit is contained in:
@@ -34,7 +34,6 @@ import android.view.ViewGroup
|
||||
import android.view.ViewGroupOverlay
|
||||
import android.widget.FrameLayout
|
||||
import com.android.internal.jank.InteractionJankMonitor
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.util.LinkedList
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
@@ -240,7 +239,7 @@ constructor(
|
||||
val ghostView = this.ghostView ?: return
|
||||
val backgroundView = this.backgroundView!!
|
||||
|
||||
if (!state.visible) {
|
||||
if (!state.visible || !ghostedView.isAttachedToWindow) {
|
||||
if (ghostView.visibility == View.VISIBLE) {
|
||||
// Making the ghost view invisible will make the ghosted view visible, so order is
|
||||
// important here.
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.UiEvent;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||
import com.android.systemui.broadcast.BroadcastSender;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
|
||||
@@ -36,11 +37,14 @@ import com.android.systemui.dagger.SysUISingleton;
|
||||
*/
|
||||
@SysUISingleton
|
||||
public class MediaOutputDialog extends MediaOutputBaseDialog {
|
||||
final UiEventLogger mUiEventLogger;
|
||||
private final DialogLaunchAnimator mDialogLaunchAnimator;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
|
||||
MediaOutputDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender,
|
||||
MediaOutputController mediaOutputController, UiEventLogger uiEventLogger) {
|
||||
MediaOutputController mediaOutputController, DialogLaunchAnimator dialogLaunchAnimator,
|
||||
UiEventLogger uiEventLogger) {
|
||||
super(context, broadcastSender, mediaOutputController);
|
||||
mDialogLaunchAnimator = dialogLaunchAnimator;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mAdapter = new MediaOutputAdapter(mMediaOutputController);
|
||||
if (!aboveStatusbar) {
|
||||
@@ -138,6 +142,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog {
|
||||
}
|
||||
} else {
|
||||
mMediaOutputController.releaseSession();
|
||||
mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,11 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager
|
||||
import com.android.systemui.animation.DialogCuj
|
||||
import com.android.systemui.animation.DialogLaunchAnimator
|
||||
import com.android.systemui.broadcast.BroadcastSender
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.media.nearby.NearbyMediaDevicesManager
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||
import java.util.Optional
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -71,7 +71,8 @@ class MediaOutputDialogFactory @Inject constructor(
|
||||
dialogLaunchAnimator, nearbyMediaDevicesManagerOptional, audioManager,
|
||||
powerExemptionManager, keyGuardManager, featureFlags, userTracker)
|
||||
val dialog =
|
||||
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller, uiEventLogger)
|
||||
MediaOutputDialog(context, aboveStatusBar, broadcastSender, controller,
|
||||
dialogLaunchAnimator, uiEventLogger)
|
||||
mediaOutputDialog = dialog
|
||||
|
||||
// Show the dialog.
|
||||
|
||||
@@ -356,6 +356,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
|
||||
});
|
||||
|
||||
verify(mockMediaOutputController).releaseSession();
|
||||
verify(mDialogLaunchAnimator).disableAllCurrentDialogsExitAnimations();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -371,7 +372,7 @@ public class MediaOutputDialogTest extends SysuiTestCase {
|
||||
@NonNull
|
||||
private MediaOutputDialog makeTestDialog(MediaOutputController controller) {
|
||||
return new MediaOutputDialog(mContext, false, mBroadcastSender,
|
||||
controller, mUiEventLogger);
|
||||
controller, mDialogLaunchAnimator, mUiEventLogger);
|
||||
}
|
||||
|
||||
private void withTestDialog(MediaOutputController controller, Consumer<MediaOutputDialog> c) {
|
||||
|
||||
Reference in New Issue
Block a user