13f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
33f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki *
43f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * Licensed under the Apache License, Version 2.0 (the "License");
53f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * you may not use this file except in compliance with the License.
63f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * You may obtain a copy of the License at
73f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki *
83f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki *      http://www.apache.org/licenses/LICENSE-2.0
93f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki *
103f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * Unless required by applicable law or agreed to in writing, software
113f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * distributed under the License is distributed on an "AS IS" BASIS,
123f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * See the License for the specific language governing permissions and
143f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * limitations under the License.
153f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki */
163f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.fragment.app;
183f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
203f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
213f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Arakiimport android.graphics.Rect;
22320113721c2e14bbc2403809046fa2959a665c11Aurimas Liutikasimport android.view.View;
23320113721c2e14bbc2403809046fa2959a665c11Aurimas Liutikasimport android.view.ViewGroup;
24320113721c2e14bbc2403809046fa2959a665c11Aurimas Liutikas
25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo;
26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.view.ViewCompat;
27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.view.ViewGroupCompat;
283f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
293f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Arakiimport java.util.ArrayList;
303f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Arakiimport java.util.List;
313f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Arakiimport java.util.Map;
323f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
333f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
343f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki/**
353f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki * @hide
363f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki */
373f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki@RestrictTo(LIBRARY_GROUP)
383f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Arakipublic abstract class FragmentTransitionImpl {
393f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
403f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
413f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Returns {@code true} if this implementation can handle the specified {@link transition}.
423f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
433f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract boolean canHandle(Object transition);
443f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
453f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
463f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Returns a clone of a transition or null if it is null
473f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
483f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract Object cloneTransition(Object transition);
493f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
503f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
513f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Wraps a transition in a TransitionSet and returns the set. If transition is null, null is
523f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * returned.
533f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
543f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract Object wrapTransitionInSet(Object transition);
553f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
563f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
573f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Finds all children of the shared elements and sets the wrapping TransitionSet
583f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * targets to point to those. It also limits transitions that have no targets to the
593f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * specific shared elements. This allows developers to target child views of the
603f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * shared elements specifically, but this doesn't happen by default.
613f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
623f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void setSharedElementTargets(Object transitionObj,
633f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            View nonExistentView, ArrayList<View> sharedViews);
643f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
653f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
663f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Sets a transition epicenter to the rectangle of a given View.
673f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
683f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void setEpicenter(Object transitionObj, View view);
693f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
703f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
713f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Replacement for view.getBoundsOnScreen because that is not public. This returns a rect
723f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * containing the bounds relative to the screen that the view is in.
733f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
743f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    protected void getBoundsOnScreen(View view, Rect epicenter) {
753f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        int[] loc = new int[2];
763f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        view.getLocationOnScreen(loc);
773f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        epicenter.set(loc[0], loc[1], loc[0] + view.getWidth(), loc[1] + view.getHeight());
783f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
793f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
803f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
813f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * This method adds views as targets to the transition, but only if the transition
823f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * doesn't already have a target. It is best for views to contain one View object
833f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * that does not exist in the view hierarchy (state.nonExistentView) so that
843f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * when they are removed later, a list match will suffice to remove the targets.
853f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Otherwise, if you happened to have targeted the exact views for the transition,
863f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * the replaceTargets call will remove them unexpectedly.
873f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
883f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void addTargets(Object transitionObj, ArrayList<View> views);
893f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
903f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
913f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Creates a TransitionSet that plays all passed transitions together. Any null
923f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * transitions passed will not be added to the set. If all are null, then an empty
933f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * TransitionSet will be returned.
943f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
953f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract Object mergeTransitionsTogether(Object transition1, Object transition2,
963f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            Object transition3);
973f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
983f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
993f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * After the transition completes, the fragment's view is set to GONE and the exiting
1003f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * views are set to VISIBLE.
1013f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
1023f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void scheduleHideFragmentView(Object exitTransitionObj, View fragmentView,
1033f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            ArrayList<View> exitingViews);
1043f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1053f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
1063f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Combines enter, exit, and shared element transition so that they play in the proper
1073f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * sequence. First the exit transition plays along with the shared element transition.
1083f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * When the exit transition completes, the enter transition starts. The shared element
1093f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * transition can continue running while the enter transition plays.
1103f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     *
1113f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * @return A TransitionSet with all of enter, exit, and shared element transitions in
1123f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * it (modulo null values), ordered such that they play in the proper sequence.
1133f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
1143f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract Object mergeTransitionsInSequence(Object exitTransitionObj,
1153f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            Object enterTransitionObj, Object sharedElementTransitionObj);
1163f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1173f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
1183f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Calls {@code TransitionManager#beginDelayedTransition(ViewGroup, Transition)}.
1193f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
1203f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void beginDelayedTransition(ViewGroup sceneRoot, Object transition);
1213f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1223f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
1233f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Prepares for setting the shared element names by gathering the names of the incoming
1243f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * shared elements and clearing them. {@link #setNameOverridesReordered(View, ArrayList,
1253f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * ArrayList, ArrayList, Map)} must be called after this to complete setting the shared element
1263f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * name overrides. This must be called before
1273f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * {@link #beginDelayedTransition(ViewGroup, Object)}.
1283f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
1293f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    ArrayList<String> prepareSetNameOverridesReordered(ArrayList<View> sharedElementsIn) {
1303f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        final ArrayList<String> names = new ArrayList<>();
1313f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        final int numSharedElements = sharedElementsIn.size();
1323f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        for (int i = 0; i < numSharedElements; i++) {
1333f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final View view = sharedElementsIn.get(i);
1343f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            names.add(ViewCompat.getTransitionName(view));
1353f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            ViewCompat.setTransitionName(view, null);
1363f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
1373f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        return names;
1383f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
1393f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1403f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
1413f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Changes the shared element names for the incoming shared elements to match those of the
1423f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * outgoing shared elements. This also temporarily clears the shared element names of the
1433f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * outgoing shared elements. Must be called after
1443f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * {@link #beginDelayedTransition(ViewGroup, Object)}.
1453f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
1463f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    void setNameOverridesReordered(final View sceneRoot,
1473f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final ArrayList<View> sharedElementsOut, final ArrayList<View> sharedElementsIn,
1483f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final ArrayList<String> inNames, final Map<String, String> nameOverrides) {
1493f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        final int numSharedElements = sharedElementsIn.size();
1503f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        final ArrayList<String> outNames = new ArrayList<>();
1513f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1523f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        for (int i = 0; i < numSharedElements; i++) {
1533f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final View view = sharedElementsOut.get(i);
1543f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final String name = ViewCompat.getTransitionName(view);
1553f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            outNames.add(name);
1563f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (name == null) {
1573f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                continue;
1583f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
1593f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            ViewCompat.setTransitionName(view, null);
1603f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final String inName = nameOverrides.get(name);
1613f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            for (int j = 0; j < numSharedElements; j++) {
1623f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                if (inName.equals(inNames.get(j))) {
1633f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    ViewCompat.setTransitionName(sharedElementsIn.get(j), name);
1643f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    break;
1653f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
1663f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
1673f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
1683f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1693f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        OneShotPreDrawListener.add(sceneRoot, new Runnable() {
1703f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            @Override
1713f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            public void run() {
1723f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                for (int i = 0; i < numSharedElements; i++) {
1733f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    ViewCompat.setTransitionName(sharedElementsIn.get(i), inNames.get(i));
1743f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    ViewCompat.setTransitionName(sharedElementsOut.get(i), outNames.get(i));
1753f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
1763f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
1773f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        });
1783f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
1793f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
1803f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
1813f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
1823f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     *
1833f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
1843f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     *                           a normal View or a ViewGroup with
1853f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
1863f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * @param view               The base of the view hierarchy to look in.
1873f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
1883f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    void captureTransitioningViews(ArrayList<View> transitioningViews, View view) {
1893f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        if (view.getVisibility() == View.VISIBLE) {
1903f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (view instanceof ViewGroup) {
1913f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                ViewGroup viewGroup = (ViewGroup) view;
1923f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                if (ViewGroupCompat.isTransitionGroup(viewGroup)) {
1933f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    transitioningViews.add(viewGroup);
1943f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                } else {
1953f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    int count = viewGroup.getChildCount();
1963f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    for (int i = 0; i < count; i++) {
1973f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                        View child = viewGroup.getChildAt(i);
1983f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                        captureTransitioningViews(transitioningViews, child);
1993f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    }
2003f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
2013f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            } else {
2023f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                transitioningViews.add(view);
2033f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
2043f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
2053f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
2063f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2073f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2083f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Finds all views that have transition names in the hierarchy under the given view and
2093f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * stores them in {@code namedViews} map with the name as the key.
2103f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2113f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    void findNamedViews(Map<String, View> namedViews, View view) {
2123f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        if (view.getVisibility() == View.VISIBLE) {
2133f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            String transitionName = ViewCompat.getTransitionName(view);
2143f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (transitionName != null) {
2153f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                namedViews.put(transitionName, view);
2163f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
2173f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (view instanceof ViewGroup) {
2183f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                ViewGroup viewGroup = (ViewGroup) view;
2193f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                int count = viewGroup.getChildCount();
2203f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                for (int i = 0; i < count; i++) {
2213f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    View child = viewGroup.getChildAt(i);
2223f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    findNamedViews(namedViews, child);
2233f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
2243f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
2253f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
2263f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
2273f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2283f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2293f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     *Applies the prepared {@code nameOverrides} to the view hierarchy.
2303f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2313f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    void setNameOverridesOrdered(final View sceneRoot,
2323f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final ArrayList<View> sharedElementsIn, final Map<String, String> nameOverrides) {
2333f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        OneShotPreDrawListener.add(sceneRoot, new Runnable() {
2343f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            @Override
2353f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            public void run() {
2363f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                final int numSharedElements = sharedElementsIn.size();
2373f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                for (int i = 0; i < numSharedElements; i++) {
2383f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    View view = sharedElementsIn.get(i);
2393f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    String name = ViewCompat.getTransitionName(view);
2403f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    if (name != null) {
2413f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                        String inName = findKeyForValue(nameOverrides, name);
2423f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                        ViewCompat.setTransitionName(view, inName);
2433f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    }
2443f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
2453f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
2463f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        });
2473f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
2483f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2493f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2503f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * After the transition has started, remove all targets that we added to the transitions
2513f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * so that the transitions are left in a clean state.
2523f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2533f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void scheduleRemoveTargets(Object overallTransitionObj,
2543f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            Object enterTransition, ArrayList<View> enteringViews,
2553f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            Object exitTransition, ArrayList<View> exitingViews,
2563f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            Object sharedElementTransition, ArrayList<View> sharedElementsIn);
2573f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2583f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2593f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Swap the targets for the shared element transition from those Views in sharedElementsOut
2603f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * to those in sharedElementsIn
2613f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2623f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void swapSharedElementTargets(Object sharedElementTransitionObj,
2633f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            ArrayList<View> sharedElementsOut, ArrayList<View> sharedElementsIn);
2643f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2653f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2663f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * This method removes the views from transitions that target ONLY those views and
2673f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * replaces them with the new targets list.
2683f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * The views list should match those added in addTargets and should contain
2693f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * one view that is not in the view hierarchy (state.nonExistentView).
2703f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2713f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void replaceTargets(Object transitionObj, ArrayList<View> oldTargets,
2723f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            ArrayList<View> newTargets);
2733f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2743f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2753f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Adds a View target to a transition. If transitionObj is null, nothing is done.
2763f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2773f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void addTarget(Object transitionObj, View view);
2783f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2793f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2803f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Remove a View target to a transition. If transitionObj is null, nothing is done.
2813f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2823f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void removeTarget(Object transitionObj, View view);
2833f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2843f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
2853f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Sets the epicenter of a transition to a rect object. The object can be modified until
2863f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * the transition runs.
2873f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
2883f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    public abstract void setEpicenter(Object transitionObj, Rect epicenter);
2893f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
2903f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    void scheduleNameReset(final ViewGroup sceneRoot,
2913f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final ArrayList<View> sharedElementsIn, final Map<String, String> nameOverrides) {
2923f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        OneShotPreDrawListener.add(sceneRoot, new Runnable() {
2933f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            @Override
2943f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            public void run() {
2953f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                final int numSharedElements = sharedElementsIn.size();
2963f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                for (int i = 0; i < numSharedElements; i++) {
2973f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    final View view = sharedElementsIn.get(i);
2983f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    final String name = ViewCompat.getTransitionName(view);
2993f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    final String inName = nameOverrides.get(name);
3003f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    ViewCompat.setTransitionName(view, inName);
3013f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
3023f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
3033f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        });
3043f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
3053f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
3063f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
3073f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Uses a breadth-first scheme to add startView and all of its children to views.
3083f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * It won't add a child if it is already in views.
3093f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
3103f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    protected static void bfsAddViewChildren(final List<View> views, final View startView) {
3113f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        final int startIndex = views.size();
3123f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        if (containedBeforeIndex(views, startView, startIndex)) {
3133f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            return; // This child is already in the list, so all its children are also.
3143f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
3153f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        views.add(startView);
3163f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        for (int index = startIndex; index < views.size(); index++) {
3173f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final View view = views.get(index);
3183f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (view instanceof ViewGroup) {
3193f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                ViewGroup viewGroup = (ViewGroup) view;
3203f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                final int childCount =  viewGroup.getChildCount();
3213f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                for (int childIndex = 0; childIndex < childCount; childIndex++) {
3223f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    final View child = viewGroup.getChildAt(childIndex);
3233f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    if (!containedBeforeIndex(views, child, startIndex)) {
3243f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                        views.add(child);
3253f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                    }
3263f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                }
3273f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
3283f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
3293f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
3303f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
3313f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
3323f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Does a linear search through views for view, limited to maxIndex.
3333f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
3343f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    private static boolean containedBeforeIndex(final List<View> views, final View view,
3353f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            final int maxIndex) {
3363f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        for (int i = 0; i < maxIndex; i++) {
3373f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (views.get(i) == view) {
3383f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                return true;
3393f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
3403f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
3413f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        return false;
3423f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
3433f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
3443f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
3453f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Simple utility to detect if a list is null or has no elements.
3463f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
3473f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    protected static boolean isNullOrEmpty(List list) {
3483f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        return list == null || list.isEmpty();
3493f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
3503f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
3513f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    /**
3523f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     * Utility to find the String key in {@code map} that maps to {@code value}.
3533f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki     */
3543f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    @SuppressWarnings("WeakerAccess")
3553f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    static String findKeyForValue(Map<String, String> map, String value) {
3563f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        for (Map.Entry<String, String> entry : map.entrySet()) {
3573f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            if (value.equals(entry.getValue())) {
3583f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki                return entry.getKey();
3593f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki            }
3603f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        }
3613f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki        return null;
3623f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki    }
3633f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki
3643f82583302c46d84017633ce93ef8c7b3278eb5eYuichi Araki}
365