Flutter: flip animation

The translation was prepared as part of the " Flutter Mobile Developer " course .



We invite all comers to the second day of the two-day online intensive
“We create an application on Flutter for Web, iOS and Android” . We continue to write the application (this will be an application with network operation: loading a list of entities + filtering them + making a settings block in the application, where you can change the application theme (colors)). Join us!






When I first saw the widget AnimationSwitcher



, I thought I could turn it over by exposing its back.





I was wrong: AnimationSwitcher



allows ... to switch between different widgets with the animation you specified (the default animation is a fading transition). This component is too versatile for this purpose.





I had to read carefully ...

, , .





flutter, -, animated_card_switcher, , , , .





:









  • AnimationSwitcher





  • .









, .





, , , , AnimationSwitcher



, (, , ).





Like a piece of cake!
!

, :





Widget __buildLayout({Key key, String faceName, Color backgroundColor}) {
  return Container(
    key: key,
    decoration: BoxDecoration(
      shape: BoxShape.rectangle,
      borderRadius: BorderRadius.circular(20.0),
      color: backgroundColor,
    ),
    child: Center(
      child: Text(faceName.substring(0, 1), style: TextStyle(fontSize: 80.0)),
    ),
  );
      
      



, :





Widget _buildFront() {
  return __buildLayout(
    key: ValueKey(true),
    backgroundColor: Colors.blue,
    faceName: "F",
  );
}

Widget _buildRear() {
  return __buildLayout(
    key: ValueKey(false),
    backgroundColor: Colors.blue.shade700,
    faceName: "R",
  );
}
      
      



AnimationSwitcher

AnimationSwitcher



.





StatefulWidget



build



, , .





class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  bool _displayFront;
  bool _flipXAxis;

  @override
  void initState() {
    super.initState();
    _displayFront = true;
    _flipXAxis = true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: Container(
          constraints: BoxConstraints.tight(Size.square(200.0)),
          child: _buildFlipAnimation(),
      ),
    );
  }
}
      
      



_build Flip Animation



, .





:





Widget _buildFlipAnimation() {
  return GestureDetector(
    onTap: () => setState(() =>_showFrontSide = !_showFrontSide),
    child: AnimatedSwitcher(
      duration: Duration(milliseconds: 600),
      child: _showFrontSide ? _buildFront() : _buildRear(),
    ),
  );
}
      
      



, , , . , .





At least something is happening.
, - .

Y. , AnimationSwitcher



, transitionBuilder



.





, : 180° (pi). AnimatedBuidler



Transform



.





Widget __transitionBuilder(Widget widget, Animation<double> animation) {
  final rotateAnim = Tween(begin: pi, end: 0.0).animate(animation);
  return AnimatedBuilder(
    animation: rotateAnim,
    child: widget,
    builder: (context, widget) {
      return Transform(
        transform: Matrix4.rotationY(value),
        child: widget,
        alignment: Alignment.center,
      );
    },
  );
}
      
      



, , . , .





The final part appears too quickly.
.

, .





:





  • : .





  • .





layoutBuilder



AnimationSwitcher



.





layoutBuilder: (widget, list) => Stack(children: [widget, ...list]),
      
      



, , pi/2 0.0. () .





Widget __transitionBuilder(Widget widget, Animation<double> animation) {
  final rotateAnim = Tween(begin: pi, end: 0.0).animate(animation);
  return AnimatedBuilder(
    animation: rotateAnim,
    child: widget,
    builder: (context, widget) {
      final isUnder = (ValueKey(_showFrontSide) != widget.key);
      final value = isUnder ? min(rotateAnim.value, pi / 2) : rotateAnim.value;
      return Transform(
        transform: Matrix4.rotationY(value),
        child: widget,
        alignment: Alignment.center,
      );
    },
  );
}
      
      



, ! , , "tilt" () .





We need depth ... Sweet little fluffy depth.
... .

"" 0,0 . , , . , 0,2, -0,2.





, Matrix4, .





Widget __transitionBuilder(Widget widget, Animation<double> animation) {
  final rotateAnim = Tween(begin: pi, end: 0.0).animate(animation);
  return AnimatedBuilder(
    animation: rotateAnim,
    child: widget,
    builder: (context, widget) {
      final isUnder = (ValueKey(_showFrontSide) != widget.key);
      var tilt = ((animation.value - 0.5).abs() - 0.5) * 0.003;
      tilt *= isUnder ? -1.0 : 1.0;
      final value = isUnder ? min(rotateAnim.value, pi / 2) : rotateAnim.value;
      return Transform(
        transform: Matrix4.rotationY(value)..setEntry(3, 0, tilt),
        child: widget,
        alignment: Alignment.center,
      );
    },
  );
}
      
      



Matrix4 : https://medium.com/flutter-community/advanced-flutter-matrix4-and-perspective-transformations-a79404a0d828.





, , AnimationSwitcher.





Curves are always better!
!

:





Widget _buildFlipAnimation() {
  return GestureDetector(
    onTap: _switchCard,
    child: AnimatedSwitcher(
      duration: Duration(milliseconds: 4600),
      transitionBuilder: __transitionBuilder,
      layoutBuilder: (widget, list) => Stack(children: [widget, ...list]),
      child: _showFrontSide ? _buildFront() : _buildRear(),
      switchInCurve: Curves.easeInBack,
      switchOutCurve: Curves.easeOutBack,
    ),
  );
}
      
      



.





Oh Nooooo….
….

, , , . .





Animation in multi-frame mode ...

, flipped



, .





switchInCurve: Curves.easeInBack,
switchOutCurve: Curves.easeInBack.flipped,
      
      



Sloooow Mooooo (now perfect)
Sloooow Mooooo ( )

, : 30 ( ), ( ).





, . , (), . , , , 6 , 1 2 ...





Copy and paste this example wisely :)
:)

. , ( ) “ ”, - , !





, , .





Flutter Twitter






"Flutter Mobile Developer"





- « Flutter Web, iOS Android»








All Articles