From b0340d4c670e9c4d68ebb91123ac4016a1a84ac5 Mon Sep 17 00:00:00 2001 From: Eric Kuck Date: Mon, 30 Mar 2020 11:12:07 -0500 Subject: [PATCH] Removes platform TransitionChangeHandler --- .idea/encodings.xml | 6 + .../SharedElementTransitionChangeHandler.java | 647 ------------------ .../TransitionChangeHandler.java | 153 ----- .../TransitionChangeHandlerCompat.java | 117 ---- .../conductor/demo/util/AnimUtils.java | 12 +- 5 files changed, 12 insertions(+), 923 deletions(-) create mode 100644 .idea/encodings.xml delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandlerCompat.java diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java deleted file mode 100644 index 7ff26d1..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java +++ /dev/null @@ -1,647 +0,0 @@ -package com.bluelinelabs.conductor.changehandler; - -import android.annotation.TargetApi; -import android.app.SharedElementCallback; -import android.graphics.Rect; -import android.os.Build; -import android.transition.Transition; -import android.transition.Transition.TransitionListener; -import android.transition.TransitionSet; -import android.util.ArrayMap; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnPreDrawListener; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.bluelinelabs.conductor.Controller; -import com.bluelinelabs.conductor.ControllerChangeHandler; -import com.bluelinelabs.conductor.internal.LegacyTransitionUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - * A TransitionChangeHandler that facilitates using different Transitions for the entering view, the exiting view, - * and shared elements between the two. - * - * @deprecated See {@link TransitionChangeHandler} - */ -// Much of this class is based on FragmentTransition.java and FragmentTransitionCompat21.java from the Android support library -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -@Deprecated -public abstract class SharedElementTransitionChangeHandler extends TransitionChangeHandler { - - // A map of from -> to names. Generally these will be the same. - @NonNull final ArrayMap sharedElementNames = new ArrayMap<>(); - - @NonNull final List waitForTransitionNames = new ArrayList<>(); - @NonNull final List removedViews = new ArrayList<>(); - - @Nullable Transition exitTransition; - @Nullable Transition enterTransition; - @Nullable Transition sharedElementTransition; - @Nullable private SharedElementCallback exitTransitionCallback; - @Nullable private SharedElementCallback enterTransitionCallback; - - @NonNull - @Override - protected final Transition getTransition(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush) { - exitTransition = getExitTransition(container, from, to, isPush); - enterTransition = getEnterTransition(container, from, to, isPush); - sharedElementTransition = getSharedElementTransition(container, from, to, isPush); - exitTransitionCallback = getExitTransitionCallback(container, from, to, isPush); - enterTransitionCallback = getEnterTransitionCallback(container, from, to, isPush); - - if (enterTransition == null && sharedElementTransition == null && exitTransition == null) { - throw new IllegalStateException("SharedElementTransitionChangeHandler must have at least one transaction."); - } - - return mergeTransitions(isPush); - } - - @Override - public void prepareForTransition(@NonNull final ViewGroup container, @Nullable final View from, @Nullable final View to, @NonNull final Transition transition, final boolean isPush, @NonNull final OnTransitionPreparedListener onTransitionPreparedListener) { - OnTransitionPreparedListener listener = () -> { - configureTransition(container, from, to, transition, isPush); - onTransitionPreparedListener.onPrepared(); - }; - - configureSharedElements(container, from, to, isPush); - - if (to != null && to.getParent() == null && waitForTransitionNames.size() > 0) { - waitOnAllTransitionNames(to, listener); - container.addView(to); - } else { - listener.onPrepared(); - } - } - - @Override - public final void executePropertyChanges(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, @Nullable Transition transition, boolean isPush) { - if (to != null && removedViews.size() > 0) { - to.setVisibility(View.VISIBLE); - - for (ViewParentPair removedView : removedViews) { - removedView.parent.addView(removedView.view); - } - - removedViews.clear(); - } - - super.executePropertyChanges(container, from, to, transition, isPush); - } - - @Override - public void onAbortPush(@NonNull ControllerChangeHandler newHandler, @Nullable Controller newTop) { - super.onAbortPush(newHandler, newTop); - - removedViews.clear(); - } - - @Override - protected void onEnd() { - exitTransition = null; - enterTransition = null; - sharedElementTransition = null; - } - - void configureTransition(@NonNull final ViewGroup container, @Nullable View from, @Nullable View to, @NonNull final Transition transition, boolean isPush) { - final View nonExistentView = new View(container.getContext()); - - List fromSharedElements = new ArrayList<>(); - List toSharedElements = new ArrayList<>(); - - configureSharedElements(container, nonExistentView, to, from, isPush, fromSharedElements, toSharedElements); - - List exitingViews = exitTransition != null ? configureEnteringExitingViews(exitTransition, from, fromSharedElements, nonExistentView) : null; - if (exitingViews == null || exitingViews.isEmpty()) { - exitTransition = null; - } - - if (enterTransition != null) { - enterTransition.addTarget(nonExistentView); - } - - final List enteringViews = new ArrayList<>(); - scheduleRemoveTargets(transition, enterTransition, enteringViews, exitTransition, exitingViews, sharedElementTransition, toSharedElements); - scheduleTargetChange(container, to, nonExistentView, toSharedElements, enteringViews, exitingViews); - - setNameOverrides(container, toSharedElements); - scheduleNameReset(container, toSharedElements); - } - - private void waitOnAllTransitionNames(@NonNull final View to, @NonNull final OnTransitionPreparedListener onTransitionPreparedListener) { - OnPreDrawListener onPreDrawListener = new OnPreDrawListener() { - boolean addedSubviewListeners; - - @Override - public boolean onPreDraw() { - List foundViews = new ArrayList<>(); - boolean allViewsFound = true; - for (String transitionName : waitForTransitionNames) { - View namedView = LegacyTransitionUtils.findNamedView(to, transitionName); - if (namedView != null) { - foundViews.add(LegacyTransitionUtils.findNamedView(to, transitionName)); - } else { - allViewsFound = false; - break; - } - } - - if (allViewsFound && !addedSubviewListeners) { - addedSubviewListeners = true; - waitOnChildTransitionNames(to, foundViews, this, onTransitionPreparedListener); - } - - return false; - } - }; - - to.getViewTreeObserver().addOnPreDrawListener(onPreDrawListener); - } - - void waitOnChildTransitionNames(@NonNull final View to, @NonNull List foundViews, @NonNull final OnPreDrawListener parentPreDrawListener, @NonNull final OnTransitionPreparedListener onTransitionPreparedListener) { - for (final View view : foundViews) { - OneShotPreDrawListener.add(true, view, () -> { - waitForTransitionNames.remove(view.getTransitionName()); - - removedViews.add(new ViewParentPair(view, (ViewGroup) view.getParent())); - ((ViewGroup) view.getParent()).removeView(view); - - if (waitForTransitionNames.size() == 0) { - to.getViewTreeObserver().removeOnPreDrawListener(parentPreDrawListener); - to.setVisibility(View.INVISIBLE); - onTransitionPreparedListener.onPrepared(); - } - }); - } - } - - private void scheduleTargetChange(@NonNull final ViewGroup container, @Nullable final View to, @NonNull final View nonExistentView, - @NonNull final List toSharedElements, @NonNull final List enteringViews, @Nullable final List exitingViews) { - OneShotPreDrawListener.add(true, container, () -> { - if (enterTransition != null) { - enterTransition.removeTarget(nonExistentView); - List views = configureEnteringExitingViews(enterTransition, to, toSharedElements, nonExistentView); - enteringViews.addAll(views); - } - - if (exitingViews != null) { - if (exitTransition != null) { - List tempExiting = new ArrayList<>(); - tempExiting.add(nonExistentView); - LegacyTransitionUtils.replaceTargets(exitTransition, exitingViews, tempExiting); - } - exitingViews.clear(); - exitingViews.add(nonExistentView); - } - }); - } - - private Transition mergeTransitions(boolean isPush) { - boolean overlap = enterTransition == null || exitTransition == null || allowTransitionOverlap(isPush); - - if (overlap) { - return LegacyTransitionUtils.mergeTransitions(TransitionSet.ORDERING_TOGETHER, exitTransition, enterTransition, sharedElementTransition); - } else { - Transition staggered = LegacyTransitionUtils.mergeTransitions(TransitionSet.ORDERING_SEQUENTIAL, exitTransition, enterTransition); - return LegacyTransitionUtils.mergeTransitions(TransitionSet.ORDERING_TOGETHER, staggered, sharedElementTransition); - } - } - - @NonNull List configureEnteringExitingViews(@NonNull Transition transition, @Nullable View view, @NonNull List sharedElements, @NonNull View nonExistentView) { - List viewList = new ArrayList<>(); - if (view != null) { - captureTransitioningViews(viewList, view); - } - viewList.removeAll(sharedElements); - if (!viewList.isEmpty()) { - viewList.add(nonExistentView); - LegacyTransitionUtils.addTargets(transition, viewList); - } - return viewList; - } - - private void configureSharedElements(@NonNull ViewGroup container, @NonNull final View nonExistentView, @Nullable final View to, @Nullable View from, - final boolean isPush, @NonNull final List fromSharedElements, @NonNull final List toSharedElements) { - - if (to == null || from == null) { - return; - } - - ArrayMap capturedFromSharedElements = captureFromSharedElements(from); - - if (sharedElementNames.isEmpty()) { - sharedElementTransition = null; - } else if (capturedFromSharedElements != null) { - fromSharedElements.addAll(capturedFromSharedElements.values()); - } - - if (enterTransition == null && exitTransition == null && sharedElementTransition == null) { - return; - } - - callSharedElementStartEnd(capturedFromSharedElements, true); - - final Rect toEpicenter; - if (sharedElementTransition != null) { - toEpicenter = new Rect(); - LegacyTransitionUtils.setTargets(sharedElementTransition, nonExistentView, fromSharedElements); - setFromEpicenter(capturedFromSharedElements); - if (enterTransition != null) { - enterTransition.setEpicenterCallback(new Transition.EpicenterCallback() { - @Override - public Rect onGetEpicenter(Transition transition) { - if (toEpicenter.isEmpty()) { - return null; - } - return toEpicenter; - } - }); - } - } else { - toEpicenter = null; - } - - OneShotPreDrawListener.add(true, container, () -> { - ArrayMap capturedToSharedElements = captureToSharedElements(to, isPush); - - if (capturedToSharedElements != null) { - toSharedElements.addAll(capturedToSharedElements.values()); - toSharedElements.add(nonExistentView); - } - - callSharedElementStartEnd(capturedToSharedElements, false); - if (sharedElementTransition != null) { - sharedElementTransition.getTargets().clear(); - sharedElementTransition.getTargets().addAll(toSharedElements); - LegacyTransitionUtils.replaceTargets(sharedElementTransition, fromSharedElements, toSharedElements); - - final View toEpicenterView = getToEpicenterView(capturedToSharedElements); - if (toEpicenterView != null && toEpicenter != null) { - LegacyTransitionUtils.getBoundsOnScreen(toEpicenterView, toEpicenter); - } - } - }); - } - - @Nullable View getToEpicenterView(@Nullable ArrayMap toSharedElements) { - if (enterTransition != null && sharedElementNames.size() > 0 && toSharedElements != null) { - return toSharedElements.get(sharedElementNames.valueAt(0)); - } - return null; - } - - private void setFromEpicenter(@Nullable ArrayMap fromSharedElements) { - if (sharedElementNames.size() > 0 && fromSharedElements != null) { - final View fromEpicenterView = fromSharedElements.get(sharedElementNames.keyAt(0)); - - if (sharedElementTransition != null) { - LegacyTransitionUtils.setEpicenter(sharedElementTransition, fromEpicenterView); - } - - if (exitTransition != null) { - LegacyTransitionUtils.setEpicenter(exitTransition, fromEpicenterView); - } - } - } - - @Nullable ArrayMap captureToSharedElements(@Nullable final View to, boolean isPush) { - if (sharedElementNames.isEmpty() || sharedElementTransition == null || to == null) { - sharedElementNames.clear(); - return null; - } - - final ArrayMap toSharedElements = new ArrayMap<>(); - LegacyTransitionUtils.findNamedViews(toSharedElements, to); - for (ViewParentPair removedView : removedViews) { - toSharedElements.put(removedView.view.getTransitionName(), removedView.view); - } - - final List names = new ArrayList<>(sharedElementNames.values()); - - toSharedElements.retainAll(names); - if (enterTransitionCallback != null) { - enterTransitionCallback.onMapSharedElements(names, toSharedElements); - for (int i = names.size() - 1; i >= 0; i--) { - String name = names.get(i); - View view = toSharedElements.get(name); - if (view == null) { - String key = findKeyForValue(sharedElementNames, name); - if (key != null) { - sharedElementNames.remove(key); - } - } else if (!name.equals(view.getTransitionName())) { - String key = findKeyForValue(sharedElementNames, name); - if (key != null) { - sharedElementNames.put(key, view.getTransitionName()); - } - } - } - } else { - for (int i = sharedElementNames.size() - 1; i >= 0; i--) { - final String targetName = sharedElementNames.valueAt(i); - if (!toSharedElements.containsKey(targetName)) { - sharedElementNames.removeAt(i); - } - } - } - return toSharedElements; - } - - @Nullable String findKeyForValue(@NonNull ArrayMap map, @NonNull String value) { - final int numElements = map.size(); - for (int i = 0; i < numElements; i++) { - if (value.equals(map.valueAt(i))) { - return map.keyAt(i); - } - } - return null; - } - - @Nullable - private ArrayMap captureFromSharedElements(@NonNull View from) { - if (sharedElementNames.isEmpty() || sharedElementTransition == null) { - sharedElementNames.clear(); - return null; - } - - final ArrayMap fromSharedElements = new ArrayMap<>(); - LegacyTransitionUtils.findNamedViews(fromSharedElements, from); - - final List names = new ArrayList<>(sharedElementNames.keySet()); - - fromSharedElements.retainAll(names); - if (exitTransitionCallback != null) { - exitTransitionCallback.onMapSharedElements(names, fromSharedElements); - for (int i = names.size() - 1; i >= 0; i--) { - String name = names.get(i); - View view = fromSharedElements.get(name); - if (view == null) { - sharedElementNames.remove(name); - } else if (!name.equals(view.getTransitionName())) { - String targetValue = sharedElementNames.remove(name); - sharedElementNames.put(view.getTransitionName(), targetValue); - } - } - } else { - sharedElementNames.retainAll(fromSharedElements.keySet()); - } - return fromSharedElements; - } - - void callSharedElementStartEnd(@Nullable ArrayMap sharedElements, boolean isStart) { - if (enterTransitionCallback != null) { - final int count = sharedElements == null ? 0 : sharedElements.size(); - List views = new ArrayList<>(count); - List names = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - names.add(sharedElements.keyAt(i)); - views.add(sharedElements.valueAt(i)); - } - if (isStart) { - enterTransitionCallback.onSharedElementStart(names, views, null); - } else { - enterTransitionCallback.onSharedElementEnd(names, views, null); - } - } - } - - private void captureTransitioningViews(@NonNull List transitioningViews, @NonNull View view) { - if (view.getVisibility() == View.VISIBLE) { - if (view instanceof ViewGroup) { - ViewGroup viewGroup = (ViewGroup) view; - if (viewGroup.isTransitionGroup()) { - transitioningViews.add(viewGroup); - } else { - int count = viewGroup.getChildCount(); - for (int i = 0; i < count; i++) { - View child = viewGroup.getChildAt(i); - captureTransitioningViews(transitioningViews, child); - } - } - } else { - transitioningViews.add(view); - } - } - } - - private void scheduleRemoveTargets(@NonNull final Transition overallTransition, - @Nullable final Transition enterTransition, @Nullable final List enteringViews, - @Nullable final Transition exitTransition, @Nullable final List exitingViews, - @Nullable final Transition sharedElementTransition, @Nullable final List toSharedElements) { - overallTransition.addListener(new TransitionListener() { - @Override - public void onTransitionStart(Transition transition) { - if (enterTransition != null && enteringViews != null) { - LegacyTransitionUtils.replaceTargets(enterTransition, enteringViews, null); - } - if (exitTransition != null && exitingViews != null) { - LegacyTransitionUtils.replaceTargets(exitTransition, exitingViews, null); - } - if (sharedElementTransition != null && toSharedElements != null) { - LegacyTransitionUtils.replaceTargets(sharedElementTransition, toSharedElements, null); - } - } - - @Override - public void onTransitionEnd(Transition transition) { } - - @Override - public void onTransitionCancel(Transition transition) { } - - @Override - public void onTransitionPause(Transition transition) { } - - @Override - public void onTransitionResume(Transition transition) { } - }); - } - - private void setNameOverrides(@NonNull final View container, @NonNull final List toSharedElements) { - OneShotPreDrawListener.add(true, container, () -> { - final int numSharedElements = toSharedElements.size(); - for (int i = 0; i < numSharedElements; i++) { - View view = toSharedElements.get(i); - String name = view.getTransitionName(); - if (name != null) { - String inName = findKeyForValue(sharedElementNames, name); - view.setTransitionName(inName); - } - } - }); - } - - private void scheduleNameReset(@NonNull final ViewGroup container, @NonNull final List toSharedElements) { - OneShotPreDrawListener.add(true, container, () -> { - final int numSharedElements = toSharedElements.size(); - for (int i = 0; i < numSharedElements; i++) { - final View view = toSharedElements.get(i); - final String name = view.getTransitionName(); - final String inName = sharedElementNames.get(name); - view.setTransitionName(inName); - } - }); - } - - /** - * Will be called when views are ready to have their shared elements configured. Within this method one of the addSharedElement methods - * should be called for each shared element that will be used. If one or more of these shared elements will not instantly be available in - * the incoming view (for ex, in a RecyclerView), waitOnSharedElementNamed can be called to delay the transition until everything is available. - */ - public abstract void configureSharedElements(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush); - - /** - * Should return the transition that will be used on the exiting ("from") view, if one is desired. - */ - @Nullable - public abstract Transition getExitTransition(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush); - - /** - * Should return the transition that will be used on shared elements between the from and to views. - */ - @Nullable - public abstract Transition getSharedElementTransition(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush); - - /** - * Should return the transition that will be used on the entering ("to") view, if one is desired. - */ - @Nullable - public abstract Transition getEnterTransition(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush); - - /** - * Should return a callback that can be used to customize transition behavior of the shared element transition for the "from" view. - */ - @Nullable - public SharedElementCallback getExitTransitionCallback(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush) { - return null; - } - - /** - * Should return a callback that can be used to customize transition behavior of the shared element transition for the "to" view. - */ - @Nullable - public SharedElementCallback getEnterTransitionCallback(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush) { - return null; - } - - /** - * Should return whether or not the the exit transition and enter transition should overlap. If true, - * the enter transition will start as soon as possible. Otherwise, the enter transition will wait until the - * completion of the exit transition. Defaults to true. - */ - public boolean allowTransitionOverlap(boolean isPush) { - return true; - } - - /** - * Used to register an element that will take part in the shared element transition. - * - * @param name The transition name that is used for both the entering and exiting views. - */ - protected final void addSharedElement(@NonNull String name) { - sharedElementNames.put(name, name); - } - - /** - * Used to register an element that will take part in the shared element transition. Maps the name used in the - * "from" view to the name used in the "to" view if they are not the same. - * - * @param fromName The transition name used in the "from" view - * @param toName The transition name used in the "to" view - */ - protected final void addSharedElement(@NonNull String fromName, @NonNull String toName) { - sharedElementNames.put(fromName, toName); - } - - /** - * Used to register an element that will take part in the shared element transition. Maps the name used in the - * "from" view to the name used in the "to" view if they are not the same. - * - * @param sharedElement The view from the "from" view that will take part in the shared element transition - * @param toName The transition name used in the "to" view - */ - protected final void addSharedElement(@NonNull View sharedElement, @NonNull String toName) { - String transitionName = sharedElement.getTransitionName(); - if (transitionName == null) { - throw new IllegalArgumentException("Unique transitionNames are required for all sharedElements"); - } - sharedElementNames.put(transitionName, toName); - } - - /** - * The transition will be delayed until the view with the name passed in is available in the "to" hierarchy. This is - * particularly useful for views that don't load instantly, like RecyclerViews. Note that using this method can - * potentially lock up your app indefinitely if the view never loads! - */ - protected final void waitOnSharedElementNamed(@NonNull String name) { - if (!sharedElementNames.values().contains(name)) { - throw new IllegalStateException("Can't wait on a shared element that hasn't been registered using addSharedElement"); - } - waitForTransitionNames.add(name); - } - - private static class OneShotPreDrawListener implements OnPreDrawListener, View.OnAttachStateChangeListener { - - private final View view; - private ViewTreeObserver viewTreeObserver; - private final Runnable runnable; - private final boolean preDrawReturnValue; - - private OneShotPreDrawListener(boolean preDrawReturnValue, @NonNull View view, @NonNull Runnable runnable) { - this.preDrawReturnValue = preDrawReturnValue; - this.view = view; - viewTreeObserver = view.getViewTreeObserver(); - this.runnable = runnable; - } - - @NonNull - public static OneShotPreDrawListener add(boolean preDrawReturnValue, @NonNull View view, @NonNull Runnable runnable) { - OneShotPreDrawListener listener = new OneShotPreDrawListener(preDrawReturnValue, view, runnable); - view.getViewTreeObserver().addOnPreDrawListener(listener); - view.addOnAttachStateChangeListener(listener); - return listener; - } - - @Override - public boolean onPreDraw() { - removeListener(); - runnable.run(); - return preDrawReturnValue; - } - - private void removeListener() { - if (viewTreeObserver.isAlive()) { - viewTreeObserver.removeOnPreDrawListener(this); - } else { - view.getViewTreeObserver().removeOnPreDrawListener(this); - } - view.removeOnAttachStateChangeListener(this); - } - - @Override - public void onViewAttachedToWindow(View v) { - viewTreeObserver = v.getViewTreeObserver(); - } - - @Override - public void onViewDetachedFromWindow(View v) { - removeListener(); - } - - } - - private static class ViewParentPair { - @NonNull final View view; - @NonNull final ViewGroup parent; - - ViewParentPair(@NonNull View view, ViewGroup parent) { - this.view = view; - this.parent = parent; - } - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java deleted file mode 100644 index db10825..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.bluelinelabs.conductor.changehandler; - -import android.annotation.TargetApi; -import android.os.Build; -import android.transition.Transition; -import android.transition.Transition.TransitionListener; -import android.transition.TransitionManager; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.bluelinelabs.conductor.Controller; -import com.bluelinelabs.conductor.ControllerChangeHandler; - -/** - * A base {@link ControllerChangeHandler} that facilitates using {@link android.transition.Transition}s to replace Controller Views. - * - * @deprecated Transitions are backported via - * AndroidX. - * They have the same API, but are preferred to the built-in framework transitions as they fix - * platform-specific bugs, and even work on versions older than 5.0. - * The {@code androidx-transition} module provides an equivalent {@link ControllerChangeHandler}. - */ -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -@Deprecated -public abstract class TransitionChangeHandler extends ControllerChangeHandler { - - public interface OnTransitionPreparedListener { - void onPrepared(); - } - - boolean canceled; - private boolean needsImmediateCompletion; - - /** - * Should be overridden to return the Transition to use while replacing Views. - * - * @param container The container these Views are hosted in - * @param from The previous View in the container or {@code null} if there was no Controller before this transition - * @param to The next View that should be put in the container or {@code null} if no Controller is being transitioned to - * @param isPush True if this is a push transaction, false if it's a pop - */ - @NonNull - protected abstract Transition getTransition(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush); - - @Override - public void onAbortPush(@NonNull ControllerChangeHandler newHandler, @Nullable Controller newTop) { - super.onAbortPush(newHandler, newTop); - - canceled = true; - } - - @Override - public void completeImmediately() { - super.completeImmediately(); - - needsImmediateCompletion = true; - } - - @Nullable - private ControllerChangeCompletedListener listener; - - @Override - public void performChange(@NonNull final ViewGroup container, @Nullable final View from, @Nullable final View to, final boolean isPush, @NonNull final ControllerChangeCompletedListener changeListener) { - listener = changeListener; - if (canceled) { - changeListener.onChangeCompleted(); - return; - } - if (needsImmediateCompletion) { - executePropertyChanges(container, from, to, null, isPush); - changeListener.onChangeCompleted(); - return; - } - - final Runnable onTransitionNotStarted = changeListener::onChangeCompleted; - - final Transition transition = getTransition(container, from, to, isPush); - transition.addListener(new TransitionListener() { - @Override - public void onTransitionStart(Transition transition) { - container.removeCallbacks(onTransitionNotStarted); - } - - @Override - public void onTransitionEnd(Transition transition) { - listener.onChangeCompleted(); - listener = null; - } - - @Override - public void onTransitionCancel(Transition transition) { - listener.onChangeCompleted(); - listener = null; - } - - @Override - public void onTransitionPause(Transition transition) { } - - @Override - public void onTransitionResume(Transition transition) { } - }); - - prepareForTransition(container, from, to, transition, isPush, () -> { - if (!canceled) { - TransitionManager.beginDelayedTransition(container, transition); - executePropertyChanges(container, from, to, transition, isPush); - container.post(onTransitionNotStarted); - } - }); - } - - @Override - public boolean removesFromViewOnPush() { - return true; - } - - /** - * Called before a transition occurs. This can be used to reorder views, set their transition names, etc. The transition will begin - * when {@code onTransitionPreparedListener} is called. - * - * @param container The container these Views are hosted in - * @param from The previous View in the container or {@code null} if there was no Controller before this transition - * @param to The next View that should be put in the container or {@code null} if no Controller is being transitioned to - * @param transition The transition that is being prepared for - * @param isPush True if this is a push transaction, false if it's a pop - */ - public void prepareForTransition(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, @NonNull Transition transition, boolean isPush, @NonNull OnTransitionPreparedListener onTransitionPreparedListener) { - onTransitionPreparedListener.onPrepared(); - } - - /** - * This should set all view properties needed for the transition to work properly. By default it removes the "from" view - * and adds the "to" view. - * - * @param container The container these Views are hosted in - * @param from The previous View in the container or {@code null} if there was no Controller before this transition - * @param to The next View that should be put in the container or {@code null} if no Controller is being transitioned to - * @param transition The transition with which {@code TransitionManager.beginDelayedTransition} has been called. This will be null only if another ControllerChangeHandler immediately overrides this one. - * @param isPush True if this is a push transaction, false if it's a pop - */ - public void executePropertyChanges(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, @Nullable Transition transition, boolean isPush) { - if (from != null && (removesFromViewOnPush() || !isPush) && from.getParent() == container) { - container.removeView(from); - } - if (to != null && to.getParent() == null) { - container.addView(to); - } - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandlerCompat.java b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandlerCompat.java deleted file mode 100644 index 977bd94..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandlerCompat.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.bluelinelabs.conductor.changehandler; - -import android.os.Build; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.bluelinelabs.conductor.Controller; -import com.bluelinelabs.conductor.ControllerChangeHandler; -import com.bluelinelabs.conductor.internal.ClassUtils; - -/** - * A base {@link ControllerChangeHandler} that facilitates using {@link android.transition.Transition}s to replace Controller Views. - * If the target device is running on a version of Android that doesn't support transitions, a fallback {@link ControllerChangeHandler} will be used. - */ -public class TransitionChangeHandlerCompat extends ControllerChangeHandler { - - private static final String KEY_CHANGE_HANDLER_CLASS = "TransitionChangeHandlerCompat.changeHandler.class"; - private static final String KEY_HANDLER_STATE = "TransitionChangeHandlerCompat.changeHandler.state"; - - @Nullable - private ControllerChangeHandler changeHandler; - - public TransitionChangeHandlerCompat() { } - - /** - * Constructor that takes a {@link TransitionChangeHandler} for use with compatible devices, as well as a fallback - * {@link ControllerChangeHandler} for use with older devices. - * - * @param transitionChangeHandler The change handler that will be used on API 21 and above - * @param fallbackChangeHandler The change handler that will be used on APIs below 21 - */ - public TransitionChangeHandlerCompat(@NonNull TransitionChangeHandler transitionChangeHandler, @NonNull ControllerChangeHandler fallbackChangeHandler) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - changeHandler = transitionChangeHandler; - } else { - changeHandler = fallbackChangeHandler; - } - } - - @Override - public void performChange(@NonNull final ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush, @NonNull final ControllerChangeCompletedListener changeListener) { - if (changeHandler != null) { - changeHandler.performChange(container, from, to, isPush, changeListener); - } - } - - @Override - public void saveToBundle(@NonNull Bundle bundle) { - super.saveToBundle(bundle); - - if (changeHandler != null) { - bundle.putString(KEY_CHANGE_HANDLER_CLASS, changeHandler.getClass().getName()); - } - - Bundle stateBundle = new Bundle(); - if (changeHandler != null) { - changeHandler.saveToBundle(stateBundle); - } - bundle.putBundle(KEY_HANDLER_STATE, stateBundle); - } - - @Override - public void restoreFromBundle(@NonNull Bundle bundle) { - super.restoreFromBundle(bundle); - - String className = bundle.getString(KEY_CHANGE_HANDLER_CLASS); - changeHandler = ClassUtils.newInstance(className); - //noinspection ConstantConditions - changeHandler.restoreFromBundle(bundle.getBundle(KEY_HANDLER_STATE)); - } - - @Override - public boolean removesFromViewOnPush() { - if (changeHandler != null) { - return changeHandler.removesFromViewOnPush(); - } - return true; - } - - @Override @NonNull - public ControllerChangeHandler copy() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - return new TransitionChangeHandlerCompat((TransitionChangeHandler)changeHandler.copy(), null); - } else { - return new TransitionChangeHandlerCompat(null, changeHandler.copy()); - } - } - - @Override - public void onAbortPush(@NonNull ControllerChangeHandler newHandler, @Nullable Controller newTop) { - if (changeHandler != null) { - changeHandler.onAbortPush(newHandler, newTop); - } - } - - @Override - public void completeImmediately() { - if (changeHandler != null) { - changeHandler.completeImmediately(); - } - } - - @Override - public void setForceRemoveViewOnPush(boolean force) { - if (changeHandler != null) { - changeHandler.setForceRemoveViewOnPush(force); - } - } - - @Override - protected void onEnd() { - changeHandler = null; - } -} diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/util/AnimUtils.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/util/AnimUtils.java index 8e1319e..0c64242 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/util/AnimUtils.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/util/AnimUtils.java @@ -20,12 +20,6 @@ import android.animation.Animator; import android.animation.TimeInterpolator; import android.annotation.TargetApi; import android.os.Build; -import androidx.annotation.NonNull; -import androidx.interpolator.view.animation.FastOutLinearInInterpolator; -import androidx.interpolator.view.animation.FastOutSlowInInterpolator; -import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; -import androidx.transition.Transition; - import android.util.ArrayMap; import android.util.FloatProperty; import android.util.IntProperty; @@ -35,6 +29,12 @@ import android.view.animation.LinearInterpolator; import java.util.ArrayList; +import androidx.annotation.NonNull; +import androidx.interpolator.view.animation.FastOutLinearInInterpolator; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; +import androidx.transition.Transition; + /** * Utility methods for working with animations. */