Skip to content

Restored traditional shared element support (Android)#705

Merged
grahammendick merged 27 commits intomasterfrom
old-shared
Jun 11, 2023
Merged

Restored traditional shared element support (Android)#705
grahammendick merged 27 commits intomasterfrom
old-shared

Conversation

@grahammendick
Copy link
Owner

Dropped support for traditional shared elements, in #528, in favour of Material container transforms. But container transforms don't support more than one shared element at a time so bringing back traditional support.

Added sharedElements prop to the NavigationStack. It receives either a string or a string array. If it's a string it will use a container transform. If it's an array it will use the traditional transform.

Android doesn't support animations during a shared element transition. It only supports fragment transitions. But can't use these yet because React Native doesn't support them. React Native has a bug where images disappear from the exiting scene during the transition. Need to PR setLegacyVisibilityHandlingEnabled in ReactImageView, then can revisit fragment transition support. So can, for example, fade in and out the scenes during a shared element transition.

The shared element motion transition on zoom sample is still working - but readying it for supporting the old way of doing shared elements. So can have multiple on the page and not don't need a material container transform
Original shared element means not the new material container transform shared element. The ChangeTransform transition caused the old shared element to disappear when remapping - so click red on grid, click brown on details, click back and red would be invisible. Had to override endViewTransition in SharedElementView and force it back to visible
Added transition name to both the shared element view and the first child so that the NavigationStack can decide which is the shared element. Need this because don't know whether it's the container or the child until the navigation happens (the plain is string shared el prop = container, array shared el prop = child)
Can't statically define the transition because don't know whether it's the transitionset or materialcontainertransform
No need for separate one for old because there's only ever one shared elements array for navigation
If shared elements is a string then use transition set. If it's an array use container transform
If sharedElement(s) prop is a string then used material container transform instead of transition set. Also need to use the shared element view instead of its first child
The transition still works because it has its own default duration
Custom animations don't run when there are any transitions (for example, shared el). Need to use transitions instead. But then there are 2 problems

When going back the disappearing scene content disappears. The fragment is destroyed immediately without waiting for the transition to complete. So the scene is popped and removed on the React side which removes it on native. Delayed the popped event call until the transition completes. The Enter transition runs when popping too (when no return transition is specified).

Even with this in place any image on a fragment transitioning away (into stack or off the stack) disappears. Fixed this by calling startViewTransition on the scenes. This prevents them being removed from their parent NavigationStackView and so images don't detach and stay visible.
Gave a time limit to postpone the shared element for. If the shared element doesn't happen in that time the navigation will start anyway
Tried to call onRest from the fragment but the scene parent is some overlay so can't get to the NavigaitonStackView from there. Moved the transition listeners into the stack so can call onRest. Had to put the onRest in both enter and exit transitions so that it's called with the correct crumb - enter when forward and exit when back
Need to give shared element time to appear, just don't want it stuck forever
Set the animation to 0 because custom animations don't run during a shared element transition
The child is the shared element when not using container transform. So have to ensure only the first child has the transition name
If change shared element children from A, B to B, A then A gets removed at 0 then added at 1. Nothing happens to B. So ended up with both A and B having the transition name.
Made sure to remove transition name from A when it's added at position 1
@grahammendick grahammendick merged commit e9deae9 into master Jun 11, 2023
@grahammendick grahammendick deleted the old-shared branch June 11, 2023 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant