public class

FragmentTransitionSupport

extends FragmentTransitionImpl

 java.lang.Object

androidx.fragment.app.FragmentTransitionImpl

↳androidx.transition.FragmentTransitionSupport

Gradle dependencies

compile group: 'androidx.transition', name: 'transition', version: '1.5.1'

  • groupId: androidx.transition
  • artifactId: transition
  • version: 1.5.1

Artifact androidx.transition:transition:1.5.1 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.transition:transition com.android.support:transition

Androidx class mapping:

androidx.transition.FragmentTransitionSupport android.support.transition.FragmentTransitionSupport

Summary

Constructors
publicFragmentTransitionSupport()

Methods
public abstract voidaddTarget(java.lang.Object transitionObj, View view)

Adds a View target to a transition.

public abstract voidaddTargets(java.lang.Object transitionObj, java.util.ArrayList<View> views)

This method adds views as targets to the transition, but only if the transition doesn't already have a target.

public voidanimateToEnd(java.lang.Object transitionController)

Animate the transition to end.

public voidanimateToStart(java.lang.Object transitionController, java.lang.Runnable completeRunnable)

Animate the transition to start.

public abstract voidbeginDelayedTransition(ViewGroup sceneRoot, java.lang.Object transition)

Calls TransitionManager#beginDelayedTransition(ViewGroup, Transition).

public abstract booleancanHandle(java.lang.Object transition)

Returns true if this implementation can handle the specified .

public abstract java.lang.ObjectcloneTransition(java.lang.Object transition)

Returns a clone of a transition or null if it is null

public java.lang.ObjectcontrolDelayedTransition(ViewGroup sceneRoot, java.lang.Object transition)

Allows for controlling a seekable transition

public booleanisSeekingSupported()

Returns true if the Transition is seekable.

public booleanisSeekingSupported(java.lang.Object transition)

Returns true if the Transition is seekable.

public abstract java.lang.ObjectmergeTransitionsInSequence(java.lang.Object exitTransitionObj, java.lang.Object enterTransitionObj, java.lang.Object sharedElementTransitionObj)

Combines enter, exit, and shared element transition so that they play in the proper sequence.

public abstract java.lang.ObjectmergeTransitionsTogether(java.lang.Object transition1, java.lang.Object transition2, java.lang.Object transition3)

Creates a TransitionSet that plays all passed transitions together.

public abstract voidremoveTarget(java.lang.Object transitionObj, View view)

Remove a View target to a transition.

public abstract voidreplaceTargets(java.lang.Object transitionObj, java.util.ArrayList<View> oldTargets, java.util.ArrayList<View> newTargets)

This method removes the views from transitions that target ONLY those views and replaces them with the new targets list.

public abstract voidscheduleHideFragmentView(java.lang.Object exitTransitionObj, View fragmentView, java.util.ArrayList<View> exitingViews)

After the transition completes, the fragment's view is set to GONE and the exiting views are set to VISIBLE.

public abstract voidscheduleRemoveTargets(java.lang.Object overallTransitionObj, java.lang.Object enterTransition, java.util.ArrayList<View> enteringViews, java.lang.Object exitTransition, java.util.ArrayList<View> exitingViews, java.lang.Object sharedElementTransition, java.util.ArrayList<View> sharedElementsIn)

After the transition has started, remove all targets that we added to the transitions so that the transitions are left in a clean state.

public voidsetCurrentPlayTime(java.lang.Object transitionController, float progress)

Uses given progress to set the current play time of the transition.

public abstract voidsetEpicenter(java.lang.Object transitionObj, Rect epicenter)

Sets the epicenter of a transition to a rect object.

public abstract voidsetEpicenter(java.lang.Object transitionObj, Rect epicenter)

Sets the epicenter of a transition to a rect object.

public voidsetListenerForTransitionEnd(Fragment outFragment, java.lang.Object transition, CancellationSignal signal, java.lang.Runnable transitionCompleteRunnable)

If either exitingViews or SharedElementsOut contain a view, an Transition.TransitionListener.onTransitionEnd(Transition) listener is added that calls run once the Transition ends.

public voidsetListenerForTransitionEnd(Fragment outFragment, java.lang.Object transition, CancellationSignal signal, java.lang.Runnable cancelRunnable, java.lang.Runnable transitionCompleteRunnable)

Set a listener for Transition end events.

public abstract voidsetSharedElementTargets(java.lang.Object transitionObj, View nonExistentView, java.util.ArrayList<View> sharedViews)

Finds all children of the shared elements and sets the wrapping TransitionSet targets to point to those.

public abstract voidswapSharedElementTargets(java.lang.Object sharedElementTransitionObj, java.util.ArrayList<View> sharedElementsOut, java.util.ArrayList<View> sharedElementsIn)

Swap the targets for the shared element transition from those Views in sharedElementsOut to those in sharedElementsIn

public abstract java.lang.ObjectwrapTransitionInSet(java.lang.Object transition)

Wraps a transition in a TransitionSet and returns the set.

from FragmentTransitionImplbfsAddViewChildren, getBoundsOnScreen, isNullOrEmpty, setEpicenter
from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public FragmentTransitionSupport()

Methods

public abstract boolean canHandle(java.lang.Object transition)

Returns true if this implementation can handle the specified .

public abstract java.lang.Object cloneTransition(java.lang.Object transition)

Returns a clone of a transition or null if it is null

public abstract java.lang.Object wrapTransitionInSet(java.lang.Object transition)

Wraps a transition in a TransitionSet and returns the set. If transition is null, null is returned.

public abstract void setSharedElementTargets(java.lang.Object transitionObj, View nonExistentView, java.util.ArrayList<View> sharedViews)

Finds all children of the shared elements and sets the wrapping TransitionSet targets to point to those. It also limits transitions that have no targets to the specific shared elements. This allows developers to target child views of the shared elements specifically, but this doesn't happen by default.

public abstract void setEpicenter(java.lang.Object transitionObj, Rect epicenter)

Sets the epicenter of a transition to a rect object. The object can be modified until the transition runs.

public abstract void addTargets(java.lang.Object transitionObj, java.util.ArrayList<View> views)

This method adds views as targets to the transition, but only if the transition doesn't already have a target. It is best for views to contain one View object that does not exist in the view hierarchy (state.nonExistentView) so that when they are removed later, a list match will suffice to remove the targets. Otherwise, if you happened to have targeted the exact views for the transition, the replaceTargets call will remove them unexpectedly.

public abstract java.lang.Object mergeTransitionsTogether(java.lang.Object transition1, java.lang.Object transition2, java.lang.Object transition3)

Creates a TransitionSet that plays all passed transitions together. Any null transitions passed will not be added to the set. If all are null, then an empty TransitionSet will be returned.

public abstract void scheduleHideFragmentView(java.lang.Object exitTransitionObj, View fragmentView, java.util.ArrayList<View> exitingViews)

After the transition completes, the fragment's view is set to GONE and the exiting views are set to VISIBLE.

public abstract java.lang.Object mergeTransitionsInSequence(java.lang.Object exitTransitionObj, java.lang.Object enterTransitionObj, java.lang.Object sharedElementTransitionObj)

Combines enter, exit, and shared element transition so that they play in the proper sequence. First the exit transition plays along with the shared element transition. When the exit transition completes, the enter transition starts. The shared element transition can continue running while the enter transition plays.

Returns:

A TransitionSet with all of enter, exit, and shared element transitions in it (modulo null values), ordered such that they play in the proper sequence.

public abstract void beginDelayedTransition(ViewGroup sceneRoot, java.lang.Object transition)

Calls TransitionManager#beginDelayedTransition(ViewGroup, Transition).

public boolean isSeekingSupported()

Returns true if the Transition is seekable.

public boolean isSeekingSupported(java.lang.Object transition)

Returns true if the Transition is seekable.

public java.lang.Object controlDelayedTransition(ViewGroup sceneRoot, java.lang.Object transition)

Allows for controlling a seekable transition

public void setCurrentPlayTime(java.lang.Object transitionController, float progress)

Uses given progress to set the current play time of the transition.

public void animateToEnd(java.lang.Object transitionController)

Animate the transition to end.

public void animateToStart(java.lang.Object transitionController, java.lang.Runnable completeRunnable)

Animate the transition to start.

public abstract void scheduleRemoveTargets(java.lang.Object overallTransitionObj, java.lang.Object enterTransition, java.util.ArrayList<View> enteringViews, java.lang.Object exitTransition, java.util.ArrayList<View> exitingViews, java.lang.Object sharedElementTransition, java.util.ArrayList<View> sharedElementsIn)

After the transition has started, remove all targets that we added to the transitions so that the transitions are left in a clean state.

public void setListenerForTransitionEnd(Fragment outFragment, java.lang.Object transition, CancellationSignal signal, java.lang.Runnable transitionCompleteRunnable)

If either exitingViews or SharedElementsOut contain a view, an Transition.TransitionListener.onTransitionEnd(Transition) listener is added that calls run once the Transition ends. If CancellationSignal.cancel() is called on the given signal, the transition calls Transition.cancel().

public void setListenerForTransitionEnd(Fragment outFragment, java.lang.Object transition, CancellationSignal signal, java.lang.Runnable cancelRunnable, java.lang.Runnable transitionCompleteRunnable)

Set a listener for Transition end events. The default behavior immediately completes the transition. Use this when the given transition is seeking. The cancelRunnable should handle cleaning up the transition when seeking is cancelled. If the transition is not seeking, you should use FragmentTransitionImpl.setListenerForTransitionEnd(Fragment, Object, CancellationSignal, Runnable).

Parameters:

outFragment: The first fragment that is exiting
transition: all transitions to be executed on a single container
signal: used indicate the desired behavior on transition cancellation
cancelRunnable: runnable to handle the logic when the signal is cancelled
transitionCompleteRunnable: used to notify the FragmentManager when a transition is complete

public abstract void swapSharedElementTargets(java.lang.Object sharedElementTransitionObj, java.util.ArrayList<View> sharedElementsOut, java.util.ArrayList<View> sharedElementsIn)

Swap the targets for the shared element transition from those Views in sharedElementsOut to those in sharedElementsIn

public abstract void replaceTargets(java.lang.Object transitionObj, java.util.ArrayList<View> oldTargets, java.util.ArrayList<View> newTargets)

This method removes the views from transitions that target ONLY those views and replaces them with the new targets list. The views list should match those added in addTargets and should contain one view that is not in the view hierarchy (state.nonExistentView).

public abstract void addTarget(java.lang.Object transitionObj, View view)

Adds a View target to a transition. If transitionObj is null, nothing is done.

public abstract void removeTarget(java.lang.Object transitionObj, View view)

Remove a View target to a transition. If transitionObj is null, nothing is done.

public abstract void setEpicenter(java.lang.Object transitionObj, Rect epicenter)

Sets the epicenter of a transition to a rect object. The object can be modified until the transition runs.

Source

/*
 * Copyright (C) 2017 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.
 */

package androidx.transition;

import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;

import android.annotation.SuppressLint;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransitionImpl;

import java.util.ArrayList;
import java.util.List;


/**
 */
// This is instantiated in androidx.fragment.app.FragmentTransition
@SuppressWarnings("unused")
@RestrictTo(LIBRARY_GROUP_PREFIX)
public class FragmentTransitionSupport extends FragmentTransitionImpl {

    @Override
    public boolean canHandle(@NonNull Object transition) {
        return transition instanceof Transition;
    }

    @Nullable
    @Override
    public Object cloneTransition(@Nullable Object transition) {
        Transition copy = null;
        if (transition != null) {
            copy = ((Transition) transition).clone();
        }
        return copy;
    }

    @Nullable
    @Override
    public Object wrapTransitionInSet(@Nullable Object transition) {
        if (transition == null) {
            return null;
        }
        TransitionSet transitionSet = new TransitionSet();
        transitionSet.addTransition((Transition) transition);
        return transitionSet;
    }

    @Override
    public void setSharedElementTargets(@NonNull Object transitionObj,
            @NonNull View nonExistentView, @NonNull ArrayList<View> sharedViews) {
        TransitionSet transition = (TransitionSet) transitionObj;
        final List<View> views = transition.getTargets();
        views.clear();
        final int count = sharedViews.size();
        for (int i = 0; i < count; i++) {
            final View view = sharedViews.get(i);
            bfsAddViewChildren(views, view);
        }
        views.add(nonExistentView);
        sharedViews.add(nonExistentView);
        addTargets(transition, sharedViews);
    }

    @Override
    public void setEpicenter(@NonNull Object transitionObj, @Nullable View view) {
        if (view != null) {
            Transition transition = (Transition) transitionObj;
            final Rect epicenter = new Rect();
            getBoundsOnScreen(view, epicenter);

            transition.setEpicenterCallback(new Transition.EpicenterCallback() {
                @Override
                public Rect onGetEpicenter(@NonNull Transition transition) {
                    return epicenter;
                }
            });
        }
    }

    @Override
    public void addTargets(@NonNull Object transitionObj, @NonNull ArrayList<View> views) {
        Transition transition = (Transition) transitionObj;
        if (transition == null) {
            return;
        }
        if (transition instanceof TransitionSet) {
            TransitionSet set = (TransitionSet) transition;
            int numTransitions = set.getTransitionCount();
            for (int i = 0; i < numTransitions; i++) {
                Transition child = set.getTransitionAt(i);
                addTargets(child, views);
            }
        } else if (!hasSimpleTarget(transition)) {
            List<View> targets = transition.getTargets();
            if (isNullOrEmpty(targets)) {
                // We can just add the target views
                int numViews = views.size();
                for (int i = 0; i < numViews; i++) {
                    transition.addTarget(views.get(i));
                }
            }
        }
    }

    private static boolean hasSimpleTarget(Transition transition) {
        return !isNullOrEmpty(transition.getTargetIds())
                || !isNullOrEmpty(transition.getTargetNames())
                || !isNullOrEmpty(transition.getTargetTypes());
    }

    @NonNull
    @Override
    public Object mergeTransitionsTogether(@Nullable Object transition1,
            @Nullable Object transition2, @Nullable Object transition3) {
        TransitionSet transitionSet = new TransitionSet();
        if (transition1 != null) {
            transitionSet.addTransition((Transition) transition1);
        }
        if (transition2 != null) {
            transitionSet.addTransition((Transition) transition2);
        }
        if (transition3 != null) {
            transitionSet.addTransition((Transition) transition3);
        }
        return transitionSet;
    }

    @Override
    public void scheduleHideFragmentView(@NonNull Object exitTransitionObj,
            final @NonNull View fragmentView, final @NonNull ArrayList<View> exitingViews) {
        Transition exitTransition = (Transition) exitTransitionObj;
        exitTransition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(@NonNull Transition transition) {
                // If any of the exiting views are not shared elements, the TransitionManager
                // adds additional listeners to the this transition. If those listeners are
                // DisappearListeners for a view that is going away, they can change the state of
                // views after our onTransitionEnd callback.
                // We need to make sure this listener gets the onTransitionEnd callback last to
                // ensure that exiting views are made visible once the Transition is complete.
                transition.removeListener(this);
                transition.addListener(this);
            }

            @Override
            public void onTransitionEnd(@NonNull Transition transition) {
                transition.removeListener(this);
                fragmentView.setVisibility(View.GONE);
                final int numViews = exitingViews.size();
                for (int i = 0; i < numViews; i++) {
                    exitingViews.get(i).setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onTransitionCancel(@NonNull Transition transition) {
            }

            @Override
            public void onTransitionPause(@NonNull Transition transition) {
            }

            @Override
            public void onTransitionResume(@NonNull Transition transition) {
            }
        });
    }

    @Nullable
    @Override
    public Object mergeTransitionsInSequence(@Nullable Object exitTransitionObj,
            @Nullable Object enterTransitionObj, @Nullable Object sharedElementTransitionObj) {
        // First do exit, then enter, but allow shared element transition to happen
        // during both.
        Transition staggered = null;
        final Transition exitTransition = (Transition) exitTransitionObj;
        final Transition enterTransition = (Transition) enterTransitionObj;
        final Transition sharedElementTransition = (Transition) sharedElementTransitionObj;
        if (exitTransition != null && enterTransition != null) {
            staggered = new TransitionSet()
                    .addTransition(exitTransition)
                    .addTransition(enterTransition)
                    .setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
        } else if (exitTransition != null) {
            staggered = exitTransition;
        } else if (enterTransition != null) {
            staggered = enterTransition;
        }
        if (sharedElementTransition != null) {
            TransitionSet together = new TransitionSet();
            if (staggered != null) {
                together.addTransition(staggered);
            }
            together.addTransition(sharedElementTransition);
            return together;
        } else {
            return staggered;
        }
    }

    @Override
    public void beginDelayedTransition(@NonNull ViewGroup sceneRoot, @Nullable Object transition) {
        TransitionManager.beginDelayedTransition(sceneRoot, (Transition) transition);
    }

    @Override
    public boolean isSeekingSupported() {
        return true;
    }

    @Override
    public boolean isSeekingSupported(@NonNull Object transition) {
        boolean supported = ((Transition) transition).isSeekingSupported();
        if (!supported) {
            Log.v("FragmentManager",
                    "Predictive back not available for AndroidX Transition "
                            + transition + ". Please enable seeking support for the designated "
                            + "transition by overriding isSeekingSupported().");
        }
        return supported;
    }

    @Override
    @Nullable
    public Object controlDelayedTransition(@NonNull ViewGroup sceneRoot,
            @NonNull Object transition) {
        return TransitionManager.controlDelayedTransition(sceneRoot, (Transition) transition);
    }

    @Override
    public void setCurrentPlayTime(@NonNull Object transitionController, float progress) {
        TransitionSeekController controller = (TransitionSeekController) transitionController;
        if (controller.isReady()) {
            long time = (long) (progress * controller.getDurationMillis());
            // We cannot let the time get to 0 or the totalDuration to avoid
            // completing the operation accidentally.
            if (time == 0L) {
                time = 1L;
            }
            if (time == controller.getDurationMillis()) {
                time = controller.getDurationMillis() - 1;
            }
            controller.setCurrentPlayTimeMillis(time);
        }
    }

    @Override
    public void animateToEnd(@NonNull Object transitionController) {
        TransitionSeekController controller = (TransitionSeekController) transitionController;
        controller.animateToEnd();
    }

    @Override
    public void animateToStart(@NonNull Object transitionController,
            @NonNull Runnable completeRunnable) {
        TransitionSeekController controller = (TransitionSeekController) transitionController;
        controller.animateToStart(completeRunnable);
    }

    @Override
    public void scheduleRemoveTargets(final @NonNull Object overallTransitionObj,
            final @Nullable Object enterTransition, final @Nullable ArrayList<View> enteringViews,
            final @Nullable Object exitTransition, final @Nullable ArrayList<View> exitingViews,
            final @Nullable Object sharedElementTransition,
            final @Nullable ArrayList<View> sharedElementsIn) {
        final Transition overallTransition = (Transition) overallTransitionObj;
        overallTransition.addListener(new TransitionListenerAdapter() {
            @Override
            public void onTransitionStart(@NonNull Transition transition) {
                if (enterTransition != null) {
                    replaceTargets(enterTransition, enteringViews, null);
                }
                if (exitTransition != null) {
                    replaceTargets(exitTransition, exitingViews, null);
                }
                if (sharedElementTransition != null) {
                    replaceTargets(sharedElementTransition, sharedElementsIn, null);
                }
            }

            @Override
            public void onTransitionEnd(@NonNull Transition transition) {
                transition.removeListener(this);
            }
        });
    }

    /**
     * {@inheritDoc}
     *
     * If either exitingViews or SharedElementsOut contain a view, an
     * {@link Transition.TransitionListener#onTransitionEnd} listener is added that calls
     * {@link Runnable#run()} once the Transition ends.
     *
     * If {@link androidx.core.os.CancellationSignal#cancel()} is called on the given signal, the
     * transition calls
     * {@link Transition#cancel()}.
     */
    @SuppressWarnings("deprecation")
    @Override
    public void setListenerForTransitionEnd(@NonNull final Fragment outFragment,
            @NonNull final Object transition,
            @NonNull final androidx.core.os.CancellationSignal signal,
            @NonNull final Runnable transitionCompleteRunnable) {
        setListenerForTransitionEnd(outFragment, transition, signal,
                null, transitionCompleteRunnable);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void setListenerForTransitionEnd(@NonNull Fragment outFragment,
            @NonNull Object transition, @NonNull androidx.core.os.CancellationSignal signal,
            @Nullable Runnable cancelRunnable, @NonNull Runnable transitionCompleteRunnable) {
        final Transition realTransition = ((Transition) transition);
        signal.setOnCancelListener(() -> {
            if (cancelRunnable == null) {
                realTransition.cancel();
                transitionCompleteRunnable.run();
            } else {
                cancelRunnable.run();
            }
        });
        realTransition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(@NonNull Transition transition) { }

            @Override
            public void onTransitionEnd(@NonNull Transition transition) {
                transitionCompleteRunnable.run();
            }

            @Override
            public void onTransitionCancel(@NonNull Transition transition) { }

            @Override
            public void onTransitionPause(@NonNull Transition transition) { }

            @Override
            public void onTransitionResume(@NonNull Transition transition) { }
        });
    }

    @Override
    public void swapSharedElementTargets(@Nullable Object sharedElementTransitionObj,
            @Nullable ArrayList<View> sharedElementsOut,
            @Nullable ArrayList<View> sharedElementsIn) {
        TransitionSet sharedElementTransition = (TransitionSet) sharedElementTransitionObj;
        if (sharedElementTransition != null) {
            sharedElementTransition.getTargets().clear();
            sharedElementTransition.getTargets().addAll(sharedElementsIn);
            replaceTargets(sharedElementTransition, sharedElementsOut, sharedElementsIn);
        }
    }

    @Override
    public void replaceTargets(@NonNull Object transitionObj,
            @SuppressLint("UnknownNullness") ArrayList<View> oldTargets,
            @SuppressLint("UnknownNullness") ArrayList<View> newTargets) {
        Transition transition = (Transition) transitionObj;
        if (transition instanceof TransitionSet) {
            TransitionSet set = (TransitionSet) transition;
            int numTransitions = set.getTransitionCount();
            for (int i = 0; i < numTransitions; i++) {
                Transition child = set.getTransitionAt(i);
                replaceTargets(child, oldTargets, newTargets);
            }
        } else if (!hasSimpleTarget(transition)) {
            List<View> targets = transition.getTargets();
            if (targets.size() == oldTargets.size()
                    && targets.containsAll(oldTargets)) {
                // We have an exact match. We must have added these earlier in addTargets
                final int targetCount = newTargets == null ? 0 : newTargets.size();
                for (int i = 0; i < targetCount; i++) {
                    transition.addTarget(newTargets.get(i));
                }
                for (int i = oldTargets.size() - 1; i >= 0; i--) {
                    transition.removeTarget(oldTargets.get(i));
                }
            }
        }
    }

    @Override
    public void addTarget(@NonNull Object transitionObj, @NonNull View view) {
        if (transitionObj != null) {
            Transition transition = (Transition) transitionObj;
            transition.addTarget(view);
        }
    }

    @Override
    public void removeTarget(@NonNull Object transitionObj, @NonNull View view) {
        if (transitionObj != null) {
            Transition transition = (Transition) transitionObj;
            transition.removeTarget(view);
        }
    }

    @Override
    public void setEpicenter(@NonNull Object transitionObj, final @NonNull Rect epicenter) {
        if (transitionObj != null) {
            Transition transition = (Transition) transitionObj;
            transition.setEpicenterCallback(new Transition.EpicenterCallback() {
                @Override
                public Rect onGetEpicenter(@NonNull Transition transition) {
                    if (epicenter == null || epicenter.isEmpty()) {
                        return null;
                    }
                    return epicenter;
                }
            });
        }
    }

}