diff --git a/api/current.txt b/api/current.txt index add82c4d5a4d9..59f7354a68f93 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3553,6 +3553,7 @@ package android.app { method public android.view.WindowManager getWindowManager(); method public boolean hasWindowFocus(); method public void invalidateOptionsMenu(); + method public boolean isActivityTransitionRunning(); method public boolean isChangingConfigurations(); method public final boolean isChild(); method public boolean isDestroyed(); @@ -49235,6 +49236,7 @@ package android.widget { method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode(); method public final synchronized void incrementProgressBy(int); method public final synchronized void incrementSecondaryProgressBy(int); + method public boolean isAnimating(); method public synchronized boolean isIndeterminate(); method public void onRestoreInstanceState(android.os.Parcelable); method public android.os.Parcelable onSaveInstanceState(); diff --git a/api/system-current.txt b/api/system-current.txt index a037eff48fe5a..3b1811eb387d7 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3675,6 +3675,7 @@ package android.app { method public android.view.WindowManager getWindowManager(); method public boolean hasWindowFocus(); method public void invalidateOptionsMenu(); + method public boolean isActivityTransitionRunning(); method public boolean isBackgroundVisibleBehind(); method public boolean isChangingConfigurations(); method public final boolean isChild(); @@ -53001,6 +53002,7 @@ package android.widget { method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode(); method public final synchronized void incrementProgressBy(int); method public final synchronized void incrementSecondaryProgressBy(int); + method public boolean isAnimating(); method public synchronized boolean isIndeterminate(); method public void onRestoreInstanceState(android.os.Parcelable); method public android.os.Parcelable onSaveInstanceState(); diff --git a/api/test-current.txt b/api/test-current.txt index 99ff3a2b703a6..6df2ab165c649 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -3555,6 +3555,7 @@ package android.app { method public android.view.WindowManager getWindowManager(); method public boolean hasWindowFocus(); method public void invalidateOptionsMenu(); + method public boolean isActivityTransitionRunning(); method public boolean isChangingConfigurations(); method public final boolean isChild(); method public boolean isDestroyed(); @@ -49554,6 +49555,7 @@ package android.widget { method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode(); method public final synchronized void incrementProgressBy(int); method public final synchronized void incrementSecondaryProgressBy(int); + method public boolean isAnimating(); method public synchronized boolean isIndeterminate(); method public void onRestoreInstanceState(android.os.Parcelable); method public android.os.Parcelable onSaveInstanceState(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 1d84ff57d3c11..6f9530901d821 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4326,6 +4326,18 @@ public class Activity extends ContextThemeWrapper } } + /** + * Returns whether there are any activity transitions currently running on this + * activity. A return value of {@code true} can mean that either an enter or + * exit transition is running, including whether the background of the activity + * is animating as a part of that transition. + * + * @return true if a transition is currently running on this activity, false otherwise. + */ + public boolean isActivityTransitionRunning() { + return mActivityTransitionState.isTransitionRunning(); + } + private Bundle transferSpringboardActivityOptions(Bundle options) { if (options == null && (mWindow != null && !mWindow.isActive())) { final ActivityOptions activityOptions = getActivityOptions(); diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index af41db01418e8..1eaf029a7c8d8 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -208,6 +208,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { private ArrayList mSharedElementParentMatrices; private boolean mSharedElementTransitionComplete; private boolean mViewsTransitionComplete; + private boolean mBackgroundAnimatorComplete; private ArrayList mStrippedTransitioningViews = new ArrayList<>(); public ActivityTransitionCoordinator(Window window, @@ -884,6 +885,10 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { startInputWhenTransitionsComplete(); } + protected void backgroundAnimatorComplete() { + mBackgroundAnimatorComplete = true; + } + protected void sharedElementTransitionComplete() { mSharedElementTransitionComplete = true; startInputWhenTransitionsComplete(); @@ -966,6 +971,11 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { } } + public boolean isTransitionRunning() { + return !(mViewsTransitionComplete && mSharedElementTransitionComplete && + mBackgroundAnimatorComplete); + } + private static class FixedEpicenterCallback extends Transition.EpicenterCallback { private Rect mEpicenter; diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java index f2616ffa2465b..b8f5a8e942833 100644 --- a/core/java/android/app/ActivityTransitionState.java +++ b/core/java/android/app/ActivityTransitionState.java @@ -336,6 +336,26 @@ class ActivityTransitionState { } } + public boolean isTransitionRunning() { + // Note that *only* enter *or* exit will be running at any given time + if (mEnterTransitionCoordinator != null) { + if (mEnterTransitionCoordinator.isTransitionRunning()) { + return true; + } + } + if (mCalledExitCoordinator != null) { + if (mCalledExitCoordinator.isTransitionRunning()) { + return true; + } + } + if (mReturnExitCoordinator != null) { + if (mReturnExitCoordinator.isTransitionRunning()) { + return true; + } + } + return false; + } + public void startExitOutTransition(Activity activity, Bundle options) { mEnterTransitionCoordinator = null; if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) || diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index b569b798eea21..0454acb31ca52 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -587,6 +587,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { @Override public void onAnimationEnd(Animator animation) { makeOpaque(); + backgroundAnimatorComplete(); } }); mBackgroundAnimator.start(); @@ -598,9 +599,13 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { makeOpaque(); } }); + backgroundAnimatorComplete(); } else { makeOpaque(); + backgroundAnimatorComplete(); } + } else { + backgroundAnimatorComplete(); } } diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 26727988e7853..f04eef24ce5df 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -201,6 +201,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { public void startExit() { if (!mIsExitStarted) { + backgroundAnimatorComplete(); mIsExitStarted = true; pauseInput(); ViewGroup decorView = getDecor(); @@ -303,11 +304,13 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { mIsBackgroundReady = true; notifyComplete(); } + backgroundAnimatorComplete(); } }); mBackgroundAnimator.setDuration(getFadeDuration()); mBackgroundAnimator.start(); } else { + backgroundAnimatorComplete(); mIsBackgroundReady = true; } } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index c4240860db691..0053caa782782 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1924,7 +1924,7 @@ public abstract class Window { public Transition getEnterTransition() { return null; } /** - * Returns he Transition that will be used to move Views out of the scene when the Window is + * Returns the Transition that will be used to move Views out of the scene when the Window is * preparing to close, for example after a call to * {@link android.app.Activity#finishAfterTransition()}. The exiting * Views will be those that are regular Views or ViewGroups that have diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 266ff7520d917..ec2adfbd65527 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -2057,6 +2057,18 @@ public class ProgressBar extends View { stream.addProperty("progress:indeterminate", isIndeterminate()); } + /** + * Returns whether the ProgressBar is animating or not. This is essentially the same + * as whether the ProgressBar is {@link #isIndeterminate() indeterminate} and visible, + * as indeterminate ProgressBars are always animating, and non-indeterminate + * ProgressBars are not animating. + * + * @return true if the ProgressBar is animating, false otherwise. + */ + public boolean isAnimating() { + return isIndeterminate() && getWindowVisibility() == VISIBLE && isShown(); + } + /** * Command for sending an accessibility event. */