Repository: flutter
Issue: [go_router] ShellRoute transition is not working properly v2
Labels: package,has reproducible steps,P2,p: go_router,team-go_router,triaged-go_router,found in release: 3.13,found in release: 3.16

### Is there an existing issue for this?

- [X] I have searched the [existing package issues](https://github.com/flutter/flutter/issues?q=is%3Aopen+is%3Aissue+label%3Apackage)
- [X] I have read the [guide to filing a bug](https://flutter.dev/docs/resources/bug-reports)

### What package does this bug report belong to?

go_router

### What target platforms are you seeing this bug on?

Android

### Have you already upgraded your packages?

Yes

### Dependency versions

<details><summary>pubspec.lock</summary>

```lock
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
  async:
    dependency: transitive
    description:
      name: async
      sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
      url: "https://pub.dev"
    source: hosted
    version: "2.11.0"
  boolean_selector:
    dependency: transitive
    description:
      name: boolean_selector
      sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  characters:
    dependency: transitive
    description:
      name: characters
      sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
      url: "https://pub.dev"
    source: hosted
    version: "1.3.0"
  clock:
    dependency: transitive
    description:
      name: clock
      sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
      url: "https://pub.dev"
    source: hosted
    version: "1.1.1"
  collection:
    dependency: transitive
    description:
      name: collection
      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
      url: "https://pub.dev"
    source: hosted
    version: "1.17.2"
  cupertino_icons:
    dependency: "direct main"
    description:
      name: cupertino_icons
      sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
      url: "https://pub.dev"
    source: hosted
    version: "1.0.6"
  fake_async:
    dependency: transitive
    description:
      name: fake_async
      sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
      url: "https://pub.dev"
    source: hosted
    version: "1.3.1"
  flutter:
    dependency: "direct main"
    description: flutter
    source: sdk
    version: "0.0.0"
  flutter_lints:
    dependency: "direct dev"
    description:
      name: flutter_lints
      sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
      url: "https://pub.dev"
    source: hosted
    version: "2.0.3"
  flutter_test:
    dependency: "direct dev"
    description: flutter
    source: sdk
    version: "0.0.0"
  flutter_web_plugins:
    dependency: transitive
    description: flutter
    source: sdk
    version: "0.0.0"
  go_router:
    dependency: "direct main"
    description:
      name: go_router
      sha256: "2ccd74480706e0a70a0e0dfa9543dede41bc11d0fe3b146a6ad7b7686f6b4407"
      url: "https://pub.dev"
    source: hosted
    version: "11.1.4"
  lints:
    dependency: transitive
    description:
      name: lints
      sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  logging:
    dependency: transitive
    description:
      name: logging
      sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
      url: "https://pub.dev"
    source: hosted
    version: "1.2.0"
  matcher:
    dependency: transitive
    description:
      name: matcher
      sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
      url: "https://pub.dev"
    source: hosted
    version: "0.12.16"
  material_color_utilities:
    dependency: transitive
    description:
      name: material_color_utilities
      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
      url: "https://pub.dev"
    source: hosted
    version: "0.5.0"
  meta:
    dependency: transitive
    description:
      name: meta
      sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
      url: "https://pub.dev"
    source: hosted
    version: "1.9.1"
  path:
    dependency: transitive
    description:
      name: path
      sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
      url: "https://pub.dev"
    source: hosted
    version: "1.8.3"
  sky_engine:
    dependency: transitive
    description: flutter
    source: sdk
    version: "0.0.99"
  source_span:
    dependency: transitive
    description:
      name: source_span
      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
      url: "https://pub.dev"
    source: hosted
    version: "1.10.0"
  stack_trace:
    dependency: transitive
    description:
      name: stack_trace
      sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
      url: "https://pub.dev"
    source: hosted
    version: "1.11.0"
  stream_channel:
    dependency: transitive
    description:
      name: stream_channel
      sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.1"
  string_scanner:
    dependency: transitive
    description:
      name: string_scanner
      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
      url: "https://pub.dev"
    source: hosted
    version: "1.2.0"
  term_glyph:
    dependency: transitive
    description:
      name: term_glyph
      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
      url: "https://pub.dev"
    source: hosted
    version: "1.2.1"
  test_api:
    dependency: transitive
    description:
      name: test_api
      sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
      url: "https://pub.dev"
    source: hosted
    version: "0.6.0"
  vector_math:
    dependency: transitive
    description:
      name: vector_math
      sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
      url: "https://pub.dev"
    source: hosted
    version: "2.1.4"
  web:
    dependency: transitive
    description:
      name: web
      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
      url: "https://pub.dev"
    source: hosted
    version: "0.1.4-beta"
sdks:
  dart: ">=3.1.3 <4.0.0"
  flutter: ">=3.7.0"

```

</details>


### Steps to reproduce

1. Execute flutter run on the code sample
2. Navigate between pages and you should be able to see the issue.

### Expected results

The push transition and the pop transition should be animated in the same way.

### Actual results

The transitions only works when you push a new route, the popped route is not animated. I followed the steps mentioned by @chunhtai in the previous [issue](https://github.com/flutter/flutter/issues/121355#issuecomment-1454137345 ), copying and modifying the `_ZoomPageTransition` in flutter/lib/src/material/page_transitions_theme.dart. But the transitions still don't work correctly even with using `secondaryAnimation`

### Code sample

<details><summary>Code sample</summary>

```dart
// ignore_for_file: unused_element

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

final router = GoRouter(
  initialLocation: '/page1',
  routes: [
    ShellRoute(
      builder: (context, state, child) {
        return HomePage(child: child);
      },
      routes: [
        GoRoute(
          path: '/page1',
          name: "page1",
          // builder: (context, state) => const Page1(),
          pageBuilder: (context, state) {
            return FadeTransitionPage(key: state.pageKey, child: const Page1());
          },
        ),

        GoRoute(
          path: '/page2',
          name: "page2",
          // builder: (context, state) => const Page2(),
          pageBuilder: (context, state) {
            return FadeTransitionPage(key: state.pageKey, child: const Page2());
          },
        ),

        GoRoute(
          path: '/page3',
          name: "page3",
          // builder: (context, state) => const Page3(),
          pageBuilder: (context, state) {
            return FadeTransitionPage(key: state.pageKey, child: const Page3());
          },
        )
      ], 
    ),
  ]
);

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(useMaterial3: true),
      routerConfig: router,
    );
  }
}

class HomePage extends StatefulWidget {
  final Widget child;

  const HomePage({
    super.key,
    required this.child
  });

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
  static const _routes = ["page1", "page2", "page3"];

  int _routeIndex = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Go Router Issue'),
      ),
      body: widget.child,
      bottomNavigationBar: NavigationBar(
        selectedIndex: _routeIndex,
        onDestinationSelected: (index) {
          setState(() => _routeIndex = index);
          context.goNamed(_routes[index]);
        },
        destinations: const [
          NavigationDestination(
            icon: Icon(Icons.looks_one_rounded), 
            label: "Page 1"
          ),

          NavigationDestination(
            icon: Icon(Icons.looks_two_rounded), 
            label: "Page 2"
          ),

          NavigationDestination(
            icon: Icon(Icons.looks_3_rounded), 
            label: "Page 3"
          )
        ],        
      ),
    );
  }
}

class Page1 extends StatelessWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context) {
    return const Align(
      alignment: Alignment(0.0, -0.2),
      child: Text('PAGE 1', style: TextStyle(fontSize: 48)),
    );
  }
}

class Page2 extends StatelessWidget {
  const Page2({super.key});

  @override
  Widget build(BuildContext context) {
    return const Align(
      alignment: Alignment(0.0, 0.0),
      child: Text('PAGE 2', style: TextStyle(fontSize: 48)),
    );
  }
}

class Page3 extends StatelessWidget {
  const Page3({super.key});

  @override
  Widget build(BuildContext context) {
    return const Align(
      alignment: Alignment(0.0, 0.2),
      child: Text('PAGE 3', style: TextStyle(fontSize: 48)),
    );
  }
}

class FadeTransitionPage extends CustomTransitionPage {
  const FadeTransitionPage({
    super.key,
    required super.child, 
  }) : super(
    transitionsBuilder: _transitionBuilder,
    transitionDuration: const Duration(milliseconds: 1000),
    reverseTransitionDuration: const Duration(milliseconds: 1000)
  );

  static Widget _transitionBuilder(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    return _FadePageTransition(animation: animation, secondaryAnimation: secondaryAnimation, child: child);
  }
}


class _FadePageTransition extends StatelessWidget {
  const _FadePageTransition({
    super.key,
    required this.animation,
    required this.secondaryAnimation,
    required this.child,
  });

  final Animation<double> animation;
  final Animation<double> secondaryAnimation;
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return DualTransitionBuilder(
      animation: animation,
      forwardBuilder: (
        BuildContext context,
        Animation<double> animation,
        Widget? child,
      ) {
        return _FadeEnterTransition(
          animation: animation,
          child: child,
        );
      },
      reverseBuilder: (
        BuildContext context,
        Animation<double> animation,
        Widget? child,
      ) {
        return _FadeExitTransition(
          animation: animation,
          reverse: true,
          child: child,
        );
      },
      child: DualTransitionBuilder(
        animation: ReverseAnimation(secondaryAnimation),
        forwardBuilder: (
          BuildContext context,
          Animation<double> animation,
          Widget? child,
        ) {
          return _FadeEnterTransition(
            animation: animation,
            reverse: true,
            child: child,
          );
        },
        reverseBuilder: (
          BuildContext context,
          Animation<double> animation,
          Widget? child,
        ) {
          return _FadeExitTransition(
            animation: animation,
            child: child,
          );
        },
        child: child,
      ),
    );
  }
}

class _FadeEnterTransition extends StatelessWidget {
  const _FadeEnterTransition({
    super.key,
    required this.animation,
    this.reverse = false,
    required this.child,
  });

  final Animation<double> animation;
  final Widget? child;
  final bool reverse;

  static final Animatable<double> _fadeInTransition = Tween<double>(begin: 0.0, end: 1.00);

  @override
  Widget build(BuildContext context) {
    final Animation<double> fadeTransition = reverse
      ? kAlwaysCompleteAnimation
      : _fadeInTransition.animate(animation);

    return FadeTransition(
      opacity: fadeTransition,
      child: child,
    );
  }
}

class _FadeExitTransition extends StatelessWidget {
  const _FadeExitTransition({
    super.key,
    required this.animation,
    this.reverse = false,
    required this.child,
  });

  final Animation<double> animation;
  final bool reverse;
  final Widget? child;

  static final Animatable<double> _fadeOutTransition = Tween<double>(begin: 1.0, end: 0.0);

  @override
  Widget build(BuildContext context) {
    final Animation<double> fadeTransition = reverse
      ? _fadeOutTransition.animate(animation)
      : kAlwaysCompleteAnimation;

    return FadeTransition(
      opacity: fadeTransition,
      child: child,
    );
  }
}
```

</details>


### Screenshots or Videos

<details>
<summary>Screenshots / Video demonstration</summary>



https://github.com/flutter/flutter/assets/54115437/d0afa256-c8ba-481a-80ea-40f5d85eb6d0


</details>


### Logs

<details><summary>Logs</summary>

```console
[Paste your logs here]
```

</details>


### Flutter Doctor output

<details><summary>Doctor output</summary>

```console
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.13.6, on Microsoft Windows [Versi¢n 10.0.23570.1000], locale es-MX)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.5.0)
[√] Android Studio (version 2022.3)
[√] VS Code (version 1.83.1)
[√] Connected device (4 available)
[√] Network resources
```

</details>