diff options
| author | George Mount <mount@google.com> | 2016-11-21 16:33:22 -0800 |
|---|---|---|
| committer | George Mount <mount@google.com> | 2016-11-21 17:30:11 -0800 |
| commit | 4efeb4f4d47a2ea5c37da9b0ad52cb288e94483e (patch) | |
| tree | 9442770ffe97942c87115b25cfb1205be3340210 /core/java/android | |
| parent | d4f9d37424752a0774cdf9190dc12887c70daec2 (diff) | |
Fix NPE when a shared element doesn't have a matching transitionName.
Bug 33053923
Also added an early error check when the same shared element is
used for multiple shared elements in the source or target fragment.
Test: If5dfbac66cfd9e60660439ce5c519547de3ef1d0
Change-Id: Iac3ab8c1b8ea0208a0c76e043654184dd634948d
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/BackStackRecord.java | 6 | ||||
| -rw-r--r-- | core/java/android/app/FragmentTransition.java | 39 |
2 files changed, 40 insertions, 5 deletions
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index e222fee6e409..abb098f05184 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -534,6 +534,12 @@ final class BackStackRecord extends FragmentTransaction implements if (mSharedElementSourceNames == null) { mSharedElementSourceNames = new ArrayList<String>(); mSharedElementTargetNames = new ArrayList<String>(); + } else if (mSharedElementTargetNames.contains(name)) { + throw new IllegalArgumentException("A shared element with the target name '" + + name + "' has already been added to the transaction."); + } else if (mSharedElementSourceNames.contains(transitionName)) { + throw new IllegalArgumentException("A shared element with the source name '" + + transitionName + " has already been added to the transaction."); } mSharedElementSourceNames.add(transitionName); mSharedElementTargetNames.add(name); diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java index 088fd08d97a8..33244481c289 100644 --- a/core/java/android/app/FragmentTransition.java +++ b/core/java/android/app/FragmentTransition.java @@ -367,9 +367,11 @@ class FragmentTransition { } if (exitingViews != null) { - ArrayList<View> tempExiting = new ArrayList<>(); - tempExiting.add(nonExistentView); - replaceTargets(exitTransition, exitingViews, tempExiting); + if (exitTransition != null) { + ArrayList<View> tempExiting = new ArrayList<>(); + tempExiting.add(nonExistentView); + replaceTargets(exitTransition, exitingViews, tempExiting); + } exitingViews.clear(); exitingViews.add(nonExistentView); } @@ -490,9 +492,17 @@ class FragmentTransition { if (nameOverrides.isEmpty()) { sharedElementTransition = null; + if (outSharedElements != null) { + outSharedElements.clear(); + } + if (inSharedElements != null) { + inSharedElements.clear(); + } } else { - sharedElementsOut.addAll(outSharedElements.values()); - sharedElementsIn.addAll(inSharedElements.values()); + addSharedElementsWithMatchingNames(sharedElementsOut, outSharedElements, + nameOverrides.keySet()); + addSharedElementsWithMatchingNames(sharedElementsIn, inSharedElements, + nameOverrides.values()); } if (enterTransition == null && exitTransition == null && sharedElementTransition == null) { @@ -538,6 +548,25 @@ class FragmentTransition { } /** + * Add Views from sharedElements into views that have the transitionName in the + * nameOverridesSet. + * + * @param views Views list to add shared elements to + * @param sharedElements List of shared elements + * @param nameOverridesSet The transition names for all views to be copied from + * sharedElements to views. + */ + private static void addSharedElementsWithMatchingNames(ArrayList<View> views, + ArrayMap<String, View> sharedElements, Collection<String> nameOverridesSet) { + for (int i = sharedElements.size() - 1; i >= 0; i--) { + View view = sharedElements.valueAt(i); + if (view != null && nameOverridesSet.contains(view.getTransitionName())) { + views.add(view); + } + } + } + + /** * Configures the shared elements of an unoptimized fragment transaction's transition. * This retrieves the shared elements of the incoming fragments, and schedules capturing * the incoming fragment's shared elements. It also maps the views, and sets up the epicenter |
