-
-
Notifications
You must be signed in to change notification settings - Fork 530
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(iOS): restore old header animation to prevent content jump (#2563)
## Description Fixes #2550 Empirical research shows that UIKit uses `interruptibleAnimatorForTransition:` method on `UIViewAnimatedTransitioning` (our `RNSStackAnimator`) for navigation item animation. This allowed us customizing navigation item timing curve & animation style, however it has caused unexpected content jumps (see #2550 or video below 👇). > [!important] > This PR reverts changes to navigation item animation introduced with v4. I guess it could be considered breaking unless it weren't a bit broken => I'm treating this as a necessary fix > & will try to bring back "new behaviour" soon, once we figure why `interruptibleAnimatorForTransition:` causes such bugs. https://github.com/user-attachments/assets/000fa79d-b01a-4261-941b-c5922e0d17f6 After the changes this looks as follows: https://github.com/user-attachments/assets/42870bab-304e-4a9d-b253-42d94c6159e7 ## Changes - **Add reproduction** - **Do not override `interruptibleAnimatorForTransition:` preventing content jump** ## Test code and steps to reproduce `TestAnimation` ## Checklist - [x] Included code example that can be used to test this change - [ ] Ensured that CI passes
- Loading branch information
Showing
3 changed files
with
110 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { NavigationContainer, RouteProp } from '@react-navigation/native'; | ||
import { NativeStackNavigationProp, createNativeStackNavigator } from '@react-navigation/native-stack'; | ||
import React from 'react'; | ||
import { View } from 'react-native'; | ||
import { Button, Square } from '../shared'; | ||
|
||
type ParamList = { | ||
Home: undefined; | ||
Second: undefined; | ||
Third: undefined; | ||
Fourth: undefined; | ||
Fifth: undefined; | ||
} | ||
|
||
type RoutePropBase<RouteName extends keyof ParamList> = { | ||
navigation: NativeStackNavigationProp<ParamList>, | ||
route: RouteProp<ParamList, RouteName>; | ||
} | ||
|
||
const Stack = createNativeStackNavigator<ParamList>(); | ||
|
||
function Contents(): React.ReactNode { | ||
return ( | ||
<View> | ||
<Square size={200} color="lightblue" /> | ||
</View> | ||
); | ||
} | ||
|
||
function Home({ navigation }: RoutePropBase<'Home'>): React.ReactNode { | ||
return ( | ||
<View style={{ flex: 1, backgroundColor: 'lightgreen', justifyContent: 'center', alignItems: 'center' }}> | ||
<View style={{ width: '100%', height: 20, backgroundColor: 'red' }} /> | ||
<Button title="Go Second" onPress={() => navigation.navigate('Second')} /> | ||
<Contents /> | ||
</View> | ||
); | ||
} | ||
|
||
|
||
function Second({ navigation }: RoutePropBase<'Second'>): React.ReactNode { | ||
return ( | ||
<View style={{ flex: 1, backgroundColor: 'lightseagreen', justifyContent: 'center', alignItems: 'center' }}> | ||
<Button title="Go Third" onPress={() => navigation.navigate('Third')} /> | ||
<Button title="Go back" onPress={() => navigation.popTo('Home')} /> | ||
<Contents /> | ||
</View> | ||
); | ||
} | ||
|
||
function Third({ navigation }: RoutePropBase<'Third'>): React.ReactNode { | ||
return ( | ||
<View style={{ flex: 1, backgroundColor: 'lightcoral', justifyContent: 'center', alignItems: 'center' }}> | ||
<Button title="Go Fourth" onPress={() => navigation.navigate('Fourth')} /> | ||
<Button title="Go back" onPress={() => navigation.popTo('Second')} /> | ||
<Contents /> | ||
</View> | ||
); | ||
} | ||
|
||
function Fourth({ navigation }: RoutePropBase<'Fourth'>): React.ReactNode { | ||
return ( | ||
<View style={{ flex: 1, backgroundColor: 'orange', justifyContent: 'center', alignItems: 'center' }}> | ||
<Button title="Go Fifth" onPress={() => navigation.navigate('Fifth')} /> | ||
<Button title="Go back" onPress={() => navigation.popTo('Second')} /> | ||
<Contents /> | ||
</View> | ||
); | ||
} | ||
|
||
function Fifth({ navigation }: RoutePropBase<'Fifth'>): React.ReactNode { | ||
return ( | ||
<View style={{ flex: 1, backgroundColor: 'pink', justifyContent: 'center', alignItems: 'center' }}> | ||
<Button title="Go back" onPress={() => navigation.popTo('Fourth')} /> | ||
<Contents /> | ||
</View> | ||
); | ||
} | ||
|
||
export default function App() { | ||
return ( | ||
<NavigationContainer> | ||
<Stack.Navigator screenOptions={{ | ||
fullScreenGestureEnabled: true, | ||
animation: 'simple_push', | ||
//animationMatchesGesture: true, | ||
}}> | ||
<Stack.Screen name="Home" component={Home} /> | ||
<Stack.Screen name="Second" component={Second} options={{ | ||
headerShown: true, | ||
}}/> | ||
<Stack.Screen name="Third" component={Third} options={{ | ||
headerShown: true, | ||
}} /> | ||
<Stack.Screen name="Fourth" component={Fourth} options={{ | ||
headerShown: false, | ||
}} /> | ||
<Stack.Screen name="Fifth" component={Fifth} options={{ | ||
headerShown: true, | ||
}} /> | ||
</Stack.Navigator> | ||
</NavigationContainer> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters