software-mansion / react-native-screens

Native navigation primitives for your React Native app.
https://docs.swmansion.com/react-native-screens/
MIT License
3.05k stars 516 forks source link

[Android] Visibility Artifact During Page Transition and Possible Solution #1968

Open alabsi91 opened 11 months ago

alabsi91 commented 11 months ago

The Issue

In the new Android 13 screen transition, an issue arises when the new screen pushes the old one, causing a white or black layer to appear between them. While this problem may exist in the old screen transition, it becomes more noticeable in the new version.

Note In the following examples to make the animation more obvious, I adjusted the animation durations in the files located at node_modules\react-native-screens\android\src\main\res\v33\anim-v33.

Default Fixed

The Fix

Fortunately, I have fixed this issue by implementing the following changes:

  1. Step One: Create a file at android\app\src\main\res\drawable\alpha_screen.xml.

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:opacity="opaque">
    <item android:gravity="fill">
        <color android:color="@android:color/transparent" />
    </item>
    </layer-list>
  2. Step Two: Add the following line to the file at android\app\src\main\res\values\styles.xml.

    <resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
    +       <item name="android:windowBackground">@drawable/alpha_screen</item>
    </style>
    </resources>
  3. Step Three: For older Android versions, you might have to make the default navigation background color transparent:

<NavigationContainer>
    <Stack.Navigator
       screenOptions={{contentStyle: {backgroundColor: 'transparent'}}} // 👈  add this
       initialRouteName="screen1">
       <Stack.Screen name="screen1" component={Screen1} />
       <Stack.Screen name="screen2" component={Screen2} />
    </Stack.Navigator>
</NavigationContainer>

Steps to reproduce

  1. Setup a new project with react-navigation

Snack or a link to a repository

https://github.com/alabsi91/rn-screens-android-transitions-animation-fix

Screens version

3.27.0

React Native version

0.72.6

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

Android emulator

Device model

Android 13

Acknowledgements

Yes

github-actions[bot] commented 11 months ago

Hey! 👋

It looks like you've omitted a few important sections from the issue template.

Please complete Description section.

kkafar commented 11 months ago

Hey, this looks great, thanks for contributing! I'll get back to you once I have opportunity to test these changes

alabsi91 commented 10 months ago

UPDATE: This approach does not work on One UI Samsung devices; you will still see black edges during the transition animation. The only fix I found is to set the screen options presentation to 'transparentModal' This will have a different transition animation, and I'm not sure if it has any performance drawbacks.