/* * 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 android.support.transition; import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; import android.support.v4.app.FragmentTransitionImpl; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /** * @hide */ // This is instantiated in android.support.v4.app.FragmentTransition @SuppressWarnings("unused") @RestrictTo(LIBRARY_GROUP) public class FragmentTransitionSupport extends FragmentTransitionImpl { @Override public boolean canHandle(Object transition) { return transition instanceof Transition; } @Override public Object cloneTransition(Object transition) { Transition copy = null; if (transition != null) { copy = ((Transition) transition).clone(); } return copy; } @Override public Object wrapTransitionInSet(Object transition) { if (transition == null) { return null; } TransitionSet transitionSet = new TransitionSet(); transitionSet.addTransition((Transition) transition); return transitionSet; } @Override public void setSharedElementTargets(Object transitionObj, View nonExistentView, ArrayList sharedViews) { TransitionSet transition = (TransitionSet) transitionObj; final List 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(Object transitionObj, 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(Object transitionObj, ArrayList 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 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()); } @Override public Object mergeTransitionsTogether(Object transition1, Object transition2, 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(Object exitTransitionObj, final View fragmentView, final ArrayList exitingViews) { Transition exitTransition = (Transition) exitTransitionObj; exitTransition.addListener(new Transition.TransitionListener() { @Override public void onTransitionStart(@NonNull Transition transition) { } @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) { } }); } @Override public Object mergeTransitionsInSequence(Object exitTransitionObj, Object enterTransitionObj, 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(ViewGroup sceneRoot, Object transition) { TransitionManager.beginDelayedTransition(sceneRoot, (Transition) transition); } @Override public void scheduleRemoveTargets(final Object overallTransitionObj, final Object enterTransition, final ArrayList enteringViews, final Object exitTransition, final ArrayList exitingViews, final Object sharedElementTransition, final ArrayList sharedElementsIn) { final Transition overallTransition = (Transition) overallTransitionObj; overallTransition.addListener(new Transition.TransitionListener() { @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) { } @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(Object sharedElementTransitionObj, ArrayList sharedElementsOut, ArrayList sharedElementsIn) { TransitionSet sharedElementTransition = (TransitionSet) sharedElementTransitionObj; if (sharedElementTransition != null) { sharedElementTransition.getTargets().clear(); sharedElementTransition.getTargets().addAll(sharedElementsIn); replaceTargets(sharedElementTransition, sharedElementsOut, sharedElementsIn); } } @Override public void replaceTargets(Object transitionObj, ArrayList oldTargets, ArrayList 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 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(Object transitionObj, View view) { if (transitionObj != null) { Transition transition = (Transition) transitionObj; transition.addTarget(view); } } @Override public void removeTarget(Object transitionObj, View view) { if (transitionObj != null) { Transition transition = (Transition) transitionObj; transition.removeTarget(view); } } @Override public void setEpicenter(Object transitionObj, final 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; } }); } } }