2 votes

Appeler une animation dans 2 widgets différents à partir d'un troisième (pas le widget parent)

J'ai 2 pages ( Page1 y Page2 ) Pour naviguer entre eux, je dispose d'une fonction personnalisée de type PrimaryMenu qui est le même pour les deux pages. Le site PrimaryMenu est contenu dans BodyPage1 y BodyPage2 respectivement. Je dispose également d'un Header widget. Les deux pages sont animées, tout comme l'en-tête.

Ce que je cherche à faire, c'est appuyer sur l'une des InkWell l'animation est inversée sur la page actuelle, puis la nouvelle page est appelée. Je sais comment appeler la nouvelle page, je comprends à peu près comment utiliser GlobalKey mais je commence à penser que cela ne peut pas être fait avec GlobalKey . Je vais vous montrer ci-dessous les différents widgets que j'ai : lien dartpad au cas où https://dartpad.dev/88b8536ea7888b5621d7d80acdcd2887

class Header extends StatefulWidget {
  @override
  _HeaderState createState() => _HeaderState();
}

class _HeaderState extends State<Header> with SingleTickerProviderStateMixin {
  AnimationController transitionAnimation;

  @override
  void initState() {
    super.initState();
    transitionAnimation = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );
    transitionAnimation.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        color: Color(0x88dddddd),
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SizedBox(
              width: 8,
            ),
            AnimatedBuilder(
              animation: transitionAnimation,
              builder: (context, child) {
                return SlideTransition(
                  position: Tween<Offset>(
                          begin: const Offset(-2, 0), end: const Offset(0, 0))
                      .animate(CurvedAnimation(
                          curve: const Interval(0, 0.3,
                              curve: Curves.easeInOutBack),
                          parent: transitionAnimation)),
                  child: child,
                );
              },
              child: Container(
                height: 100,
                width: MediaQuery.of(context).size.width * 0.135,
                color: Colors.pink,
              ),
            ),
            Expanded(
              child: Container(),
            ),
            Container(
              width: 100,
              height: 50,
              color: Colors.purple,
            ),
            SizedBox(
              width: 8,
            ),
            Container(
              height: 50,
              width: 50,
              color: Colors.amber,
            ),
            SizedBox(
              width: 8,
            )
          ],
        ));
  }
}

class Page1 extends StatefulWidget {
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: PreferredSize(
        preferredSize: Size(MediaQuery.of(context).size.width, 120),
        child: Header(),
      ),
      body: BodyPage1(),
    );
  }
}

class PrimaryMenu extends StatefulWidget {
  @override
  _PrimaryMenuState createState() => _PrimaryMenuState();
}

class _PrimaryMenuState extends State<PrimaryMenu> {
  @override
  Widget build(BuildContext context) {
    return Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width * 0.15,
        color: Colors.blue,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
                height: 40,
                width: MediaQuery.of(context).size.width * 0.135,
                color: Colors.grey,
                child: InkWell(
                  onTap: () {
                    print('1');
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => Page1(),
                        ));
                  },
                )),
            SizedBox(height: 16),
            Container(
                height: 40,
                width: MediaQuery.of(context).size.width * 0.135,
                color: Colors.black,
                child: InkWell(
                  onTap: () {
                    print('2');
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => Page2(),
                        ));
                  },
                )),
          ],
        ));
  }
}

class BodyPage1 extends StatefulWidget {

  @override
  _BodyPage1State createState() => _BodyPage1State();
}

class _BodyPage1State extends State<BodyPage1>
    with SingleTickerProviderStateMixin {
  AnimationController transitionAnimation;

  @override
  void initState() {
    super.initState();
    transitionAnimation = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );
    transitionAnimation.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        AnimatedBuilder(
            animation: transitionAnimation,
            builder: (context, child) {
              return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve:
                            const Interval(0, 0.3, curve: Curves.easeInOutBack),
                        parent: transitionAnimation)),
                child: child,
              );
            },
            child: PrimaryMenu()),
        AnimatedBuilder(
          animation: transitionAnimation,
          builder: (context, child) {
            return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve: const Interval(0.3, 1, curve: Curves.easeIn),
                        parent: transitionAnimation)),
                child: child);
          },
          child: Padding(
            padding: EdgeInsets.only(top: 140, left: 20, right: 20, bottom: 20),
            child: Container(
              height: MediaQuery.of(context).size.height - 140,
              width: (MediaQuery.of(context).size.width * .85) - 40,
              color: Colors.grey,
            ),
          ),
        )
      ],
    );
  }
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: PreferredSize(
        preferredSize: Size(MediaQuery.of(context).size.width, 120),
        child: Header(),
      ),
      body: BodyPage2(),
    );
  }
}

class BodyPage2 extends StatefulWidget {
  @override
  _BodyPage2State createState() => _BodyPage2State();
}

class _BodyPage2State extends State<BodyPage2>
    with SingleTickerProviderStateMixin {
  AnimationController transitionAnimation;

  @override
  void initState() {
    super.initState();
    transitionAnimation = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );
    transitionAnimation.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        AnimatedBuilder(
            animation: transitionAnimation,
            builder: (context, child) {
              return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve:
                            const Interval(0, 0.3, curve: Curves.easeInOutBack),
                        parent: transitionAnimation)),
                child: child,
              );
            },
            child: PrimaryMenu()),
        AnimatedBuilder(
          animation: transitionAnimation,
          builder: (context, child) {
            return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve: const Interval(0.3, 1, curve: Curves.easeIn),
                        parent: transitionAnimation)),
                child: child);
          },
          child: Padding(
            padding: EdgeInsets.only(top: 140, left: 20, right: 20, bottom: 20),
            child: Container(
              height: MediaQuery.of(context).size.height - 140,
              width: (MediaQuery.of(context).size.width * .85) - 40,
              color: Colors.black,
            ),
          ),
        )
      ],
    );
  }
}

J'ai également créé un dartpad montrant ce que j'ai réussi à faire avec GlobalKey, mais je n'arrive à le faire fonctionner que si j'utilise une clé de type FloatingActionButton en el Scaffold - https://dartpad.dev/5979f44ecaa9cf2e22b4ce0cc9c23aa8

Désolé qu'il y ait beaucoup de code, j'ai essayé de le condenser autant que possible.

2voto

bluenile Points 4368

Tout ce que vous avez à faire, c'est de passer le contrôleur d'animation de la BodyPage respective à votre PrimaryMenu qui est responsable de l'appel des Page1 et Page2. Une fois que l'AnimationController est disponible pour le PrimaryMenu, il inversera d'abord l'animation, puis appellera la page correspondante. Veuillez voir le code de travail ci-dessous :

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(visualDensity: VisualDensity.adaptivePlatformDensity),
      debugShowCheckedModeBanner: false,
      home: Page1(),
    );
  }
}

class Header extends StatefulWidget {
  @override
  _HeaderState createState() => _HeaderState();
}

class _HeaderState extends State<Header> with SingleTickerProviderStateMixin {
  AnimationController transitionAnimation;

  @override
  void initState() {
    super.initState();
    transitionAnimation = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );
    transitionAnimation.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        color: const Color(0x88dddddd),
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const SizedBox(
              width: 8,
            ),
            AnimatedBuilder(
              animation: transitionAnimation,
              builder: (context, child) {
                return SlideTransition(
                  position: Tween<Offset>(
                          begin: const Offset(-2, 0), end: const Offset(0, 0))
                      .animate(CurvedAnimation(
                          curve: const Interval(0, 0.3,
                              curve: Curves.easeInOutBack),
                          parent: transitionAnimation)),
                  child: child,
                );
              },
              child: Container(
                height: 100,
                width: MediaQuery.of(context).size.width * 0.135,
                color: Colors.pink,
              ),
            ),
            Expanded(
              child: Container(),
            ),
            Container(
              width: 100,
              height: 50,
              color: Colors.purple,
            ),
            const SizedBox(
              width: 8,
            ),
            Container(
              height: 50,
              width: 50,
              color: Colors.amber,
            ),
            const SizedBox(
              width: 8,
            )
          ],
        ));
  }
}

class Page1 extends StatefulWidget {
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: PreferredSize(
        preferredSize: Size(MediaQuery.of(context).size.width, 120),
        child: Header(),
      ),
      body: BodyPage1(),
    );
  }
}

class PrimaryMenu extends StatefulWidget {
  final AnimationController controller;

  const PrimaryMenu({Key key, this.controller}) : super(key: key);
  @override
  _PrimaryMenuState createState() => _PrimaryMenuState();
}

class _PrimaryMenuState extends State<PrimaryMenu> {
  @override
  Widget build(BuildContext context) {
    return Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width * 0.15,
        color: Colors.blue,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
                height: 40,
                width: MediaQuery.of(context).size.width * 0.135,
                color: Colors.grey,
                child: InkWell(
                  onTap: () async {
                    print('1');
                    await widget.controller
                        .reverse()
                        .then((value) => Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => Page1(),
                            )));
                  },
                )),
            const SizedBox(height: 16),
            Container(
                height: 40,
                width: MediaQuery.of(context).size.width * 0.135,
                color: Colors.black,
                child: InkWell(
                  onTap: () async {
                    print('2');
                    await widget.controller
                        .reverse()
                        .then((value) => Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => Page2(),
                            )));
                  },
                )),
          ],
        ));
  }
}

class BodyPage1 extends StatefulWidget {
  @override
  _BodyPage1State createState() => _BodyPage1State();
}

class _BodyPage1State extends State<BodyPage1>
    with SingleTickerProviderStateMixin {
  AnimationController transitionAnimation;

  @override
  void initState() {
    super.initState();
    transitionAnimation = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );
    transitionAnimation.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        AnimatedBuilder(
            animation: transitionAnimation,
            builder: (context, child) {
              return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve:
                            const Interval(0, 0.3, curve: Curves.easeInOutBack),
                        parent: transitionAnimation)),
                child: child,
              );
            },
            child: PrimaryMenu(
              controller: transitionAnimation,
            )),
        AnimatedBuilder(
          animation: transitionAnimation,
          builder: (context, child) {
            return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve: const Interval(0.3, 1, curve: Curves.easeIn),
                        parent: transitionAnimation)),
                child: child);
          },
          child: Padding(
            padding: const EdgeInsets.only(
                top: 140, left: 20, right: 20, bottom: 20),
            child: Container(
              height: MediaQuery.of(context).size.height - 140,
              width: (MediaQuery.of(context).size.width * .85) - 40,
              color: Colors.grey,
            ),
          ),
        )
      ],
    );
  }
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: PreferredSize(
        preferredSize: Size(MediaQuery.of(context).size.width, 120),
        child: Header(),
      ),
      body: BodyPage2(),
    );
  }
}

class BodyPage2 extends StatefulWidget {
  @override
  _BodyPage2State createState() => _BodyPage2State();
}

class _BodyPage2State extends State<BodyPage2>
    with SingleTickerProviderStateMixin {
  AnimationController transitionAnimation;

  @override
  void initState() {
    super.initState();
    transitionAnimation = AnimationController(
      duration: const Duration(seconds: 3),
      vsync: this,
    );
    transitionAnimation.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        AnimatedBuilder(
            animation: transitionAnimation,
            builder: (context, child) {
              return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve:
                            const Interval(0, 0.3, curve: Curves.easeInOutBack),
                        parent: transitionAnimation)),
                child: child,
              );
            },
            child: PrimaryMenu(
              controller: transitionAnimation,
            )),
        AnimatedBuilder(
          animation: transitionAnimation,
          builder: (context, child) {
            return SlideTransition(
                position: Tween<Offset>(
                        begin: const Offset(-2, 0), end: const Offset(0, 0))
                    .animate(CurvedAnimation(
                        curve: const Interval(0.3, 1, curve: Curves.easeIn),
                        parent: transitionAnimation)),
                child: child);
          },
          child: Padding(
            padding: const EdgeInsets.only(
                top: 140, left: 20, right: 20, bottom: 20),
            child: Container(
              height: MediaQuery.of(context).size.height - 140,
              width: (MediaQuery.of(context).size.width * .85) - 40,
              color: Colors.black,
            ),
          ),
        )
      ],
    );
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X